Repository navigation
feat(declarative): add SyncTokenCursor for server-issued sync tokens (1/2: capture and commit) - #1234
devin-ai-integration[bot] wants to merge 4 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>
|
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-cursor#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-cursorPR Slash CommandsAirbyte Maintainers can execute the following slash commands on your PR:
|
PyTest Results (Fast)5 803 tests +49 5 772 ✅ +49 8m 10s ⏱️ - 3m 29s Results for commit 39add2c. ± Comparison against base commit 73ccaa9. This pull request removes 1 and adds 50 tests. Note that renamed tests count towards both.♻️ This comment has been updated with latest results. |
PyTest Results (Full)5 806 tests +49 5 775 ✅ +49 16m 57s ⏱️ + 6m 49s Results for commit 39add2c. ± Comparison against base commit 73ccaa9. This pull request removes 1 and adds 50 tests. Note that renamed tests count towards both.♻️ This comment has been updated with latest results. |
Co-Authored-By: bot_apk <apk@cognition.ai>
Summary
Adds
SyncTokenCursor, a declarative incremental sync type for APIs that return an opaque, server-issued sync token in the response envelope (AshbysyncToken, Google/Todoist sync tokens, Box stream positions, Graph/Dataverse delta tokens). This is PR 1 of 2 (capture and commit). PR 2, stacked on this one, addsRESET_SYNC_TOKENrecovery.Resolves https://github.com/airbytehq/airbyte-internal-issues/issues/17213:
Close on merge: yes — internally filed, no customer to confirm with. (Close after PR 2 merges as well.)
Changes
SyncTokenCursorwith five settings:token_path,token_option,completion_condition,initial_token,cursor_field. It is added toDeclarativeStream.incremental_sync.anyOf. The definition usesadditionalProperties: trueso that stream-level$parametersstill validate.SyncTokenCursor(incremental/sync_token_cursor.py):{"state_type": "sync_token", "token": "<token>"}.PerPartitionKeySerializer.completion_conditionand carries a valid string or int token. It is committed inclose_partition, so state is queued after every record of the traversal.SyncTokenRequestOptionsProvider: sends the stored token, otherwiseinitial_token, otherwise nothing, throughtoken_option. For partitioned streams it is wrapped inPerPartitionRequestOptionsProvider.SimpleRetriever: newpage_observerhook (PageCompleted(stream_slice, response, pagination_exhausted)). It is called after a page's records are yielded and after the next page token is computed. It is bound only forSyncTokenCursorand isNone(inert) for every other stream.DefaultStream: newsource_defined_incrementalflag. A token stream advertises[full_refresh, incremental],source_defined_cursor: true,is_resumable: true, anddefault_cursor_field: [](or[cursor_field]). It never advertisesnull.GroupingPartitionRouterAsyncRetrieverincremental_dependencyin either directiontokenpagination_reset.limitsCustomRetrieverwarningExample (Ashby):
Reproduction (before the change)
On
main(v7.37.0), a manifest whose stream usesincremental_sync: {type: SyncTokenCursor, ...}failsConcurrentDeclarativeSource(source_config=manifest)withjsonschema.exceptions.ValidationError: Validation against json schema defined in declarative_component_schema.yaml schema failed.incremental_synconly acceptsDatetimeBasedCursorandIncrementingCountCursor.Declarative-First Evaluation
This is a CDK feature, not a connector change.
DatetimeBasedCursorandIncrementingCountCursorboth derive state from record values, and no existing declarative component can capture a value from the response envelope and commit it only when the traversal completes. The new component is built-in and declarative, so adopters need no custom Python components.Test Coverage
unit_tests/sources/declarative/incremental/test_sync_token_cursor.py: unit tests for T-TOKEN, T-CAP, T-FOREIGN, T-SCHEMA, T-DISC and T-VALID, plus the cursor state rules.unit_tests/sources/declarative/incremental/test_sync_token_cursor_integration.py: end-to-end tests throughConcurrentDeclarativeSource.readwithHttpMocker, asserting exact request bodies. Covers T-BOOT, T-INC, T-NOECHO, T-EMPTY, T-FAIL, T-BUILDER, T-INIT, T-PAR (3 partitions), T-RESUME and T-INERT.main(schema validation error) and pass with this change.main: two date-only parsing tests in file-based, and a schema-test fixture race under-n auto.Breaking change
None. This is an additive, opt-in component. Existing cursors, streams and the retriever are unchanged when the cursor is not used:
page_observerisNone, andsource_defined_incrementaldefaults toFalse.Link to Devin session: https://app.devin.ai/sessions/94b41efe75db43e78eb5a4f8d5f58484
Open in Devin Desktop: https://app.devin.ai/desktop/session/94b41efe75db43e78eb5a4f8d5f58484?variant=devin