Skip to content

Commit

Permalink
🐛(backend) submit for signature handle timeout delete signing procedure
Browse files Browse the repository at this point in the history
When the method `submit_for_signature` needs to delete a signing procedure
because some elements have changed overtime in the contract definition
and before the student signed the document, it appears that it may take
a while on the signature provider side to execute the deletion.
In order to handle and update our contract, we have added a try
except block to catch the timeout issue, and proceed to update the contract
as if we would have received the response from the signature provider.
Before we added the fix, the contract would keep the old reference that would
not work when the student wanted to sign the document, causing another error
because it has already been deleted after the timeout we have set in the
signature backend. In some cases, due to the timeout error, when we attempt
to delete the outdated reference, we would then have a NOT_FOUND status
code, we should also reset the contrat submission value as well to restart with
a new contrat to submit.
  • Loading branch information
jonathanreveille committed Sep 20, 2024
1 parent ce938db commit de0653e
Show file tree
Hide file tree
Showing 6 changed files with 859 additions and 7 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ and this project adheres to

### Fixed

- Handle timeout and exception in `submit_for_signature` to
update the contract without the outdated references
- Improve signature backend `handle_notification` error catching
- Allow to cancel an enrollment order linked to an archived course run

Expand Down Expand Up @@ -50,7 +52,6 @@ and this project adheres to

- Do not update OpenEdX enrollment if this one is already
up-to-date on the remote lms
-

## [2.4.0] - 2024-06-21

Expand Down
7 changes: 7 additions & 0 deletions src/backend/joanie/core/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,10 @@ class CertificateGenerationError(Exception):
Exception raised when the certificate generation process fails due to the order not meeting
all specified conditions.
"""


class BackendTimeout(Exception):
"""
Exception raised when a backend reaches the timeout set when we are waiting
for the response.
"""
18 changes: 14 additions & 4 deletions src/backend/joanie/core/models/products.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from urllib3.util import Retry

from joanie.core import enums
from joanie.core.exceptions import CertificateGenerationError
from joanie.core.exceptions import BackendTimeout, CertificateGenerationError
from joanie.core.fields.schedule import OrderPaymentScheduleEncoder
from joanie.core.flows.order import OrderFlow
from joanie.core.models.accounts import User
Expand All @@ -38,6 +38,7 @@
from joanie.core.utils import issuers, webhooks
from joanie.core.utils.payment_schedule import generate as generate_payment_schedule
from joanie.signature.backends import get_signature_backend
from joanie.signature.exceptions import DeleteSignatureProcedureFailed

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -965,9 +966,18 @@ def submit_for_signature(self, user: User):
)

if should_be_resubmitted:
backend_signature.delete_signing_procedure(
contract.signature_backend_reference
)
# The signature provider may delay confirming deletion. If timeout occurs, reset
# submission values, as the signature provider will delete them. In an edge case, the
# reference `contract.signature_backend_reference` cannot be used and may already
# be deleted causing a 'not found' error from the signature provider.
try:
backend_signature.delete_signing_procedure(
contract.signature_backend_reference
)
except (BackendTimeout, DeleteSignatureProcedureFailed):
pass
contract.reset_submission_for_signature()
was_already_submitted = False

# We want to submit or re-submit the contract for signature in three cases:
# 1- the contract was never submitted for signature before
Expand Down
17 changes: 16 additions & 1 deletion src/backend/joanie/signature/backends/lex_persona.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
from django.core.exceptions import ValidationError

import requests
from requests.exceptions import ReadTimeout
from rest_framework.request import Request
from sentry_sdk import capture_exception

from joanie.core import enums, models
from joanie.core.exceptions import BackendTimeout
from joanie.core.utils.contract import order_has_organization_owner
from joanie.signature import exceptions
from joanie.signature.backends.base import BaseSignatureBackend
Expand Down Expand Up @@ -528,7 +530,20 @@ def delete_signing_procedure(self, reference_id: str):
url = f"{base_url}/api/workflows/{reference_id}"
headers = {"Authorization": f"Bearer {token}"}

response = requests.delete(url, headers=headers, timeout=timeout)
try:
response = requests.delete(url, headers=headers, timeout=timeout)
except ReadTimeout as exception:
logger.error(
exception,
extra={
"context": {
"signature_backend_reference": reference_id,
}
},
)
raise BackendTimeout(
f"Deletion request is taking longer than expected for reference: {reference_id}"
) from exception

if not response.ok:
logger.error(
Expand Down
Loading

0 comments on commit de0653e

Please sign in to comment.