Repository navigation
feat(declarative): add RESET_SYNC_TOKEN recovery for SyncTokenCursor (2/3) - #1235
devin-ai-integration[bot] wants to merge 23 commits into
Conversation
Co-Authored-By: bot_apk <apk@cognition.ai>
Co-Authored-By: bot_apk <apk@cognition.ai>
Co-Authored-By: bot_apk <apk@cognition.ai>
Co-Authored-By: bot_apk <apk@cognition.ai>
Co-Authored-By: bot_apk <apk@cognition.ai>
|
I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".
|
👋 Greetings, Airbyte Team Member!Here are some helpful tips and reminders for your convenience. 💡 Show Tips and TricksTesting This CDK VersionYou can test this version of the CDK using the following: # Run the CLI from this branch:
uvx 'git+https://github.com/airbytehq/airbyte-python-cdk.git@devin/1792189821-opaque-token-reset#egg=airbyte-python-cdk[dev]' --help
# Update a connector to use the CDK from this branch ref:
cd airbyte-integrations/connectors/source-example
poe use-cdk-branch devin/1792189821-opaque-token-resetPR Slash CommandsAirbyte Maintainers can execute the following slash commands on your PR:
|
PyTest Results (Fast)6 097 tests 6 066 ✅ 6m 27s ⏱️ Results for commit acf0b95. ♻️ This comment has been updated with latest results. |
Co-Authored-By: bot_apk <apk@cognition.ai>
…9821-opaque-token-reset
Co-Authored-By: bot_apk <apk@cognition.ai>
Co-Authored-By: bot_apk <apk@cognition.ai>
…rsor' into devin/1792189821-opaque-token-reset Co-Authored-By: bot_apk <apk@cognition.ai> # Conflicts: # unit_tests/sources/declarative/incremental/test_sync_token_cursor_integration.py
Co-Authored-By: bot_apk <apk@cognition.ai>
…rsor' into devin/1792189821-opaque-token-reset
Co-Authored-By: bot_apk <apk@cognition.ai>
…tition routers Co-Authored-By: bot_apk <apk@cognition.ai>
…rsor' into devin/1792189821-opaque-token-reset
…set' into devin/1792471568-sync-token-request-path Bring in the current base (#1235, which includes #1234's review fixes) and resolve conflicts: - model_to_component_factory.py: keep both new static methods, _validate_sync_token_option_collisions (this PR) and _flatten_partition_router_models (base). - sync_token_request_options_provider.py: keep this PR's RequestPath support and _get_token helper; take the base's docstring, its removal of the dead `not self.token_option` check, and valid_types=(str,) for initial_token. - sync_token_cursor.py: say "sync token" in the log line of this PR's new first-commit branch, matching the base's rename. test_commit_observability_counts_completed_pages_per_partition fails otherwise.
Review: fix before mergeReviewed at What works: a reset never touches committed state. It re-reads only the rejected partition, from page 1 with a fresh paginator and record parser. It sends What needs fixing: what happens across syncs, and what the action exposes to connector authors. Keep P1: must fix1. A token that keeps getting rejected turns every sync into a silent full readWhere: Problem:
Requested change:
2. Recovery reports success without a replacement tokenWhere: Problem:
Requested change: track the partitions that reset in this attempt. On a reset partition's last page, require a valid token. If there isn't one, or Regression tests for 1 and 2, to append to
|
Co-Authored-By: bot_apk <apk@cognition.ai>
…rsor' into devin/1792189821-opaque-token-reset
Co-Authored-By: bot_apk <apk@cognition.ai>
|
☑️ Resolved in c192670 (merges #1234 at 4050495), except for the two items under "Not done yet" below.
Not done yet:
Posted by Devin, as requested by Patrick Nilan (@pnilan). |
…partition state - Remove the hand-added interpolation_context from the generated SyncTokenCursor model. The generator only emits the deprecated and deprecation_message extra keys. - Add a read test for a token stream used as a parent without incremental_dependency: the parent copy is read in full, sends no stored token and emits no state. - Cover more malformed partitioned state shapes and assert system_error. - Drop two tests whose names said malformed shapes are ignored. The malformed-state tests cover the same shapes, expect the failure and check that nothing is loaded.
…eset Co-Authored-By: bot_apk <apk@cognition.ai> # Conflicts: # unit_tests/sources/declarative/incremental/test_sync_token_cursor.py
Summary
Adds recovery for rejected or expired sync tokens, such as Ashby's
sync_token_expired. This is PR 2 of 3 in the stack. It builds onSyncTokenCursorfrom #1234, which is now merged tomain, and #1238 follows it.Part of https://github.com/airbytehq/airbyte-internal-issues/issues/17213. Merging this PR alone does not close the issue.
Changes
New
ResponseAction.RESET_SYNC_TOKEN, with matching schema and model enum entries. The schema now documents what the action does and its limits:SyncTokenCursorFAILinsteadExample filter:
HttpClientraisesSyncTokenResetRequiredExceptionfor that action, the same way it handlesRESET_PAGINATION.CompositeErrorHandlerkeeps the action instead of falling through to the next handler.SimpleRetrievercatches the exception and callsSyncTokenCursor.restart_without_token. It then re-reads only the rejected partition from page 1, without the stored token: it sendsinitial_token, or no token if none is configured.sync-token-resetanalytics message is emitted.Safeguards so a reset can't silently full-read on every sync:
after_reset: true. If the API rejects that token on the next sync, the stream fails with asystem_errorthat includes the API's reason. The next normal commit clears the flag.system_errorand keeps the committed token. That covers a failedcompletion_conditionand a token that is missing, empty or null.system_error, as does a rejected read that sent no token.Build-time validation: the factory raises
ValueErrorwhenRESET_SYNC_TOKENappears on a stream whoseincremental_syncisn't aSyncTokenCursor, or on a login requester, anAsyncRetrieverrequester or afile_uploaderrequester.Declarative-First Evaluation
This is a CDK feature, not a connector change.
RESET_PAGINATIONrestarts pagination but keeps the stored token, and no existing action drops it. The new action gives adopters a built-in declarative option.Test Coverage
after_resetRESET_PAGINATIONinterplayCompositeErrorHandlerinitial_tokensent on the re-readsuccess == falsecombined with a specific error code.test_http_client.pyandtest_composite_error_handler.py.Breaking change
None. The action is opt-in, and existing actions and streams are unchanged. The
after_resetstate field is new, but the state format hasn't been released yet.Not yet done
error-handling.mddocs section lives in airbytehq/airbyte, so it will ship separately.opaque_tokenstate.Link to Devin session: https://app.devin.ai/sessions/94b41efe75db43e78eb5a4f8d5f58484
Open in Devin Desktop: https://app.devin.ai/desktop/session/94b41efe75db43e78eb5a4f8d5f58484?variant=devin