From f7ef8149686dcd52577270218780452116ffc8ad Mon Sep 17 00:00:00 2001 From: Zach Mullen Date: Thu, 24 Aug 2023 15:32:48 -0400 Subject: [PATCH] WIP More robust DOI commitment flow --- isic/core/services/collection/doi.py | 48 ++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/isic/core/services/collection/doi.py b/isic/core/services/collection/doi.py index 2bd04730..377f2891 100644 --- a/isic/core/services/collection/doi.py +++ b/isic/core/services/collection/doi.py @@ -57,6 +57,17 @@ def collection_build_doi(*, collection: Collection, doi_id: str) -> dict: } +def collection_build_draft_doi(*, doi_id: str) -> dict: + return { + "data": { + "type": "dois", + "attributes": { + "doi": doi_id, + }, + } + } + + def collection_generate_random_doi_id(): # pad DOI with leading zeros so all DOIs are prefix/6 digits return f"{settings.ISIC_DATACITE_DOI_PREFIX}/{random.randint(10_000, 999_999):06}" @@ -91,20 +102,29 @@ def _datacite_create_doi(doi: dict) -> None: def collection_create_doi(*, user: User, collection: Collection) -> Doi: collection_check_create_doi_allowed(user=user, collection=collection) doi_id = collection_generate_random_doi_id() + draft_doi = collection_build_draft_doi(doi_id=doi_id) doi = collection_build_doi(collection=collection, doi_id=doi_id) - try: - _datacite_create_doi(doi) - except HTTPError as e: - logger.error(e) - raise ValidationError("Something went wrong creating the DOI.") - else: - with transaction.atomic(): - doi = Doi(id=doi_id, creator=user, url=f"https://doi.org/{doi_id}") - doi.full_clean() - doi.save() - collection_lock(collection=collection) - collection_update(collection=collection, doi=doi, ignore_lock=True) - logger.info("User %d created DOI %s for collection %d", user.id, doi.id, collection.id) - + with transaction.atomic(): + # First, create the local DOI record to validate uniqueness within our known set + doi = Doi(id=doi_id, creator=user, url=f"https://doi.org/{doi_id}") + doi.full_clean() + doi.save() + + # Lock the collection, set the DOI on it + collection_lock(collection=collection) + collection_update(collection=collection, doi=doi, ignore_lock=True) + + try: + # Reserve the DOI using the draft mechanism + _datacite_create_doi(draft_doi) + except HTTPError as e: + logger.error(e) + # Transaction will rollback, nothing in our database will change + raise ValidationError("Something went wrong creating the DOI.") + else: + logger.info("User %d created DOI %s for collection %d", user.id, doi.id, collection.id) + + # Convert to a published DOI. Only question now is what happens if this fails. + _datacite_create_doi(doi) return doi