feat(declarative): allow DefaultErrorHandler.max_retries to be interpolated from config#1017
Open
devin-ai-integration[bot] wants to merge 1 commit intomainfrom
Conversation
…olated from config Co-Authored-By: bot_apk <apk@cognition.ai>
Contributor
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
👋 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/1778162508-default-error-handler-interpolatable-max-retries#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/1778162508-default-error-handler-interpolatable-max-retriesPR Slash CommandsAirbyte Maintainers can execute the following slash commands on your PR:
|
Anatolii Yatsuk (tolik0)
approved these changes
May 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Widens
DefaultErrorHandler.max_retriesto accept a Jinja-interpolatable string in addition to a literal integer, so connector authors can drive retry counts from the connector config — for example:Use case: connectors whose users share a single rate-limit budget across many connections (e.g. SP-API's per-
(application, selling_partner_account)token bucket) want a "fail-fast" knob to stop burning the shared quota on retry chains. Today this requires a custom Python error handler subclass; with this change a plain manifest field works.The string variant is resolved once in
__post_init__against the connector config and replaced in place with the resolvedint, so consumers oferror_handler.max_retries(notablyHttpClient._max_retries, which does arithmetic on it) keep getting anintand don't need to change.Files changed
declarative_component_schema.yaml—max_retriesbecomesanyOf: [integer, string]withinterpolation_context: [config]. Mirrors the existing pattern used byConcurrencyLevel.default_concurrency,CursorPagination.page_size,Rate.limit, etc.models/declarative_component_schema.py— generated Pydantic model widened toOptional[Union[int, str]]. Hand-edited rather than re-run throughbin/generate_component_manifest_files.py(Dagger-based codegen) — single-line change, but worth a sanity check that re-running codegen produces the same diff.requesters/error_handlers/default_error_handler.py:Optional[Union[int, str]](with a# type: ignore[assignment]and inline comment explaining the LSP widening relative to the abstract base class — post-__post_init__the value is alwaysint, matching the parent contract)InterpolatedString(...).eval(config=...)in__post_init___max_retries,_max_time) that were declared on the dataclass but never read anywhere in the codebaseunit_tests/.../test_default_error_handler.py— 8 new tests covering: default unspecified, literal int, zero, config-interpolated, Jinja.get(..., default)fallback, interpolation resolving to zero, interpolation resolving to a numeric string, and the explicitValueErrorpath when the interpolation doesn't resolve to an int.Backward-compatible: existing manifests passing a literal integer go through an unchanged code path.
Review & Testing Checklist for Human
models/declarative_component_schema.pymatches what the Dagger codegen would produce. I edited it directly (one field, one description, examples list) instead of re-runningbin/generate_component_manifest_files.py. Easiest verification: run the codegen locally and confirmgit diffis empty on that file.max_retries: Optional[Union[int, str]]is wider than the abstract base classErrorHandler.max_retries(Optional[int]). I added# type: ignore[assignment]because the__post_init__resolution makes the post-construction invariant match the parent contract — confirm this is the preferred handling vs. e.g. wideningErrorHandler.max_retriesitself (which I avoided to keep the abstract contract clean for non-declarative implementers likeHttpStatusErrorHandler).max_retriesform field correctly after the schema change toanyOf: [integer, string]. Other fields with this same shape (e.g.default_concurrency,page_size) already work in the Builder, so this should be a non-issue, but worth a 30-second visual check._max_retries/_max_timeprivate dataclass fields is safe. I grep'd for both and found no references, but if any external consumer constructedDefaultErrorHandlerand read those, that's a (very minor) break.poetry run pytest unit_tests/sources/declarative/requesters/error_handlers/test_default_error_handler.py(34 pass locally, including the 8 new ones).Notes
max_retriesonce at construction time rather than lazily on each property access (which is the patternConcurrencyLeveluses).HttpClientreadserror_handler.max_retrieson every retried request, so caching is the right call here, and the connector config is sync-static. Happy to revert to lazy resolution if reviewers prefer consistency withConcurrencyLevel.source-amazon-seller-partnerfeature request (oncall #11837). Without this PR, the same use case can be solved connector-side with a small custom error handler subclass; with this PR, it's a one-line manifest change.breakingChangesentry needed — strictly additive at the wire format and ABI level.Link to Devin session: https://app.devin.ai/sessions/9e16ef322dcd4c4fb40299b57494bd37