-
Notifications
You must be signed in to change notification settings - Fork 106
ETQ usager, je peux déposer mon dossier même si la vérification du SIRET est temporairement indisponible #13435
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
777546b
6a7a8fd
273cc98
01646e1
b64b64b
64182ad
e779f80
730bf73
6bc8dbe
29472ae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,16 @@ def has_async_external_data? | |
| true | ||
| end | ||
|
|
||
| # A condition based on one of this champ's columns (value_json) cannot be | ||
| # evaluated until the data is fetched: restore the blocking validation. | ||
| def permissive_external_data_validation? | ||
| !external_data_required_for_conditions? | ||
| end | ||
|
|
||
| def external_data_required_for_conditions? | ||
| dependent_conditions? | ||
|
E-L-T marked this conversation as resolved.
|
||
| end | ||
|
|
||
| def focusable_input_id(attribute = :value) | ||
| [input_id, :value].compact.join('-') | ||
| end | ||
|
|
@@ -34,17 +44,33 @@ def ready_for_external_call? | |
|
|
||
| def fetch_external_data | ||
| case APIEntrepriseService.create_etablissement_with_fallback(self, external_id.delete(" "), dossier.user&.id) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. on creait déjà l'etb en mode degradé quand api down ou 429, j'ai donc pas trop compris ces changements (on gere les 401/403/409/422/451...). Or dans ces cas la, je ne suis pas certains qu'on souhaite passer le dossier (a la limite, le 409 arrive quand on requete le meme objet au mm moment, limite faudrait remonter le cas dans Propale pour simplifier :
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Effectivement, c'est peut-être pas une bonne idée de laisser passer sans distinction tout ce qui est 401/403/409/422/451...
|
||
| in Success(etablissement) if etablissement.as_degraded_mode? | ||
| Failure(retryable: true, error: StandardError.new("API Entreprise: degraded mode"), code: 503) | ||
| in Success(etablissement) | ||
| # A degraded-mode etablissement (API Entreprise down) is accepted as is: | ||
| # the user is not blocked, background jobs backfill the data later and | ||
| # Dossier#any_etablissement_as_degraded_mode? keeps instructeurs from | ||
| # accepting the dossier in the meantime. | ||
| Success(etablissement:, value: external_id) | ||
| in Failure(type: :not_found, **) | ||
| Failure(retryable: false, error: StandardError.new('NotFound'), code: 404) | ||
| in Failure(type:, code:, retryable:, **) | ||
| Failure(retryable:, error: StandardError.new("API Entreprise: #{type}"), code:) | ||
| in Failure(type:, code:, retryable: true, **) | ||
| Failure(retryable: true, error: StandardError.new("API Entreprise: #{type}"), code:) | ||
| in Failure(type:, code:, **) | ||
| # Any other technical error also converges to degraded mode: only a 404 | ||
| # (nonexistent SIRET) leaves the champ in external_error. | ||
| Sentry.capture_message("SiretChamp: degraded mode fallback after API Entreprise error", extra: { champ: id, type:, code: }) | ||
| Success(etablissement: create_degraded_etablissement, value: external_id) | ||
| end | ||
| end | ||
|
|
||
| # Retries exhausted (API Entreprise flapping while the health checker still | ||
| # reports it up): converge to a degraded etablissement instead of | ||
| # external_error, so that Dossier#any_etablissement_as_degraded_mode? blocks | ||
| # acceptance and the backfill jobs recover the data later. | ||
| def handle_exhausted_external_data_retries! | ||
| update_external_data!(etablissement: create_degraded_etablissement, value: external_id) | ||
| external_data_fetched! | ||
| end | ||
|
|
||
| def search_terms | ||
| etablissement.present? ? etablissement.search_terms : [value] | ||
| end | ||
|
|
@@ -57,14 +83,29 @@ def save_additional_job_exception(exception, code) | |
|
|
||
| private | ||
|
|
||
| def create_degraded_etablissement | ||
| APIEntrepriseService.create_etablissement_as_degraded_mode(self, external_id.delete(" "), dossier.user&.id) | ||
| end | ||
|
|
||
| # We want to validate if SIRET really exists | ||
| # It's valid when an etablissement have been created in turbo with SIRET controller | ||
| # When API Entreprise is down, user won't be stuck because | ||
| # SIRET controller creates an etablissement in degraded mode | ||
| def validate_etablissement | ||
| return if external_id.blank? | ||
|
|
||
| # A degraded-mode etablissement carries no data yet: block until the | ||
| # backfill jobs complete it, so the condition can be evaluated. | ||
| if external_data_required_for_conditions? && etablissement&.as_degraded_mode? | ||
| errors.add(:external_id, :api_response_pending) | ||
| return | ||
| end | ||
|
|
||
| return if etablissement.present? | ||
| return if pending? | ||
| # Blocking on external_error is ExternalDataChampValidator's job; | ||
| # this validation only covers the synchronous idle/format-check path. | ||
| return if external_error? | ||
|
|
||
| validator = ActiveModel::Validations::SiretValidator.new(attributes: { value: true }) | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -47,7 +47,9 @@ module ChampExternalDataConcern | |
| end | ||
|
|
||
| event :external_data_fetched do | ||
| transitions from: [:fetching], to: :fetched | ||
| # waiting_for_job: a champ can converge to fetched from the retry_on | ||
| # exhaustion block (see #handle_exhausted_external_data_retries!) | ||
| transitions from: [:fetching, :waiting_for_job], to: :fetched | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Je suis un peu embété d'avoir un état fetched pour un champ ... qui ne l'ai pas. De plus, on va chercher a étendre cette mécanique à d'autres champs connectés. Du coup, je te proposerai bien, dans la machine à état, d'introduire un nouvelle état |
||
| end | ||
|
|
||
| event :external_data_error do | ||
|
|
@@ -72,6 +74,11 @@ def has_async_external_data? = false | |
|
|
||
| def external_data_needed_for_validation? = has_async_external_data? | ||
|
|
||
| # Called by ChampFetchExternalDataJob when all retry attempts are exhausted. | ||
| def handle_exhausted_external_data_retries! | ||
| external_data_error! | ||
| end | ||
|
|
||
| private | ||
|
|
||
| def ready_for_external_call? = external_id.present? | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.