Repository navigation
fix(low-code): evaluate concurrency_level with the normalized config - #1205
Merged
Baz (bazarnov) merged 1 commit intoOct 6, 2026
Merged
Conversation
`ConcurrencyLevel` was built from the raw config, while every other component reads `self._config`, the copy that `config_normalization_rules` migrated and transformed. A migration that rewrote the worker count took effect one run late, and a transformation never did.
👋 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@bazarnov/fix-concurrency-level-normalized-config#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 bazarnov/fix-concurrency-level-normalized-configPR Slash CommandsAirbyte Maintainers can execute the following slash commands on your PR:
|
Anatolii Yatsuk (tolik0)
approved these changes
Oct 6, 2026
Baz (bazarnov)
deleted the
bazarnov/fix-concurrency-level-normalized-config
branch
October 6, 2026 12:16
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.
Overview
👉 TL;DR: Connectors now size their worker pool from the config after its migrations and transformations run, not from the config as stored. Before, a migration that changed the worker count took effect one sync late, and a transformation that changed it never took effect.
Specifically,
ConcurrentDeclarativeSource.__init__builds theConcurrencyLevelcomponent fromself._configinstead of the rawconfigargument, sodefault_concurrencyinterpolates the output ofspec.config_normalization_rules.Changes
concurrent_declarative_source.py: passconfig=self._configto theConcurrencyLevelcomponent instead ofconfig=config or {}. Streams, authenticators,api_budget, dynamic streams andcheckalready readself._config.test_concurrent_declarative_source.py: addtest_concurrency_level_uses_normalized_config, parametrized overconfig_migrationsandtransformations. Each case rewritesnum_workersfrom 1 to 4 and asserts the thread pool has 4 workers.Review Spotlight
Reviewers with limited time, please review first:
concurrent_declarative_source.py#L239-L251:self._configis neverNone(or {}), so it replacesconfig or {}directlyconcurrent_declarative_source.py#L355-L373: without aspec,self._configis the raw config, so those manifests see no changetest_concurrent_declarative_source.py#L1800-L1833: the new testRisks
default_concurrencyreads. The platform saves migrated configs, so a migration was missed on one run per connection. Transformations are never saved, so one that drivesdefault_concurrencywas ignored on every run.source-striperaisesnum_workersfrom 1 to 2 in a migration. On the run that migrates a storednum_workers: 1, the pool now has 2 workers instead of 1, the same as later runs. Built from the real manifest with a dummy config: pool size 1 onmain, 2 with the fix.source-zendesk-supportraisesnum_workersbelow 2 to 2, and its[config.get('num_workers', 4), 2] | maxclamp already yields 2, so its pool size is unchanged. After it moves to a CDK release with this fix, the clamp becomes optional. No action required.master): 537 connectormanifest.yamlfiles (git ls-tree -r --name-only origin/master -- airbyte-integrations/connectors | grep -E '/manifest\.yaml$'); 54 declareconcurrency_level(git grep -l concurrency_level origin/master -- 'airbyte-integrations/connectors/*/manifest.yaml' 'airbyte-integrations/connectors/*/**/manifest.yaml'), 39 of them interpolate config and 15 use a constant; the same grep finds 20 withconfig_normalization_rules, all of which also declareconcurrency_level. For those 20, a script compared the config fields eachdefault_concurrencyreads with the fields each migration or transformation writes. The custom transformations insource-github,source-mailchimpandsource-google-analytics-data-apiwere read by hand and do not affect concurrency.config_normalization_rules, the Connector Builder and the manifest server (both forcedefault_concurrency: 1). Records, state, catalogs and the manifest schema are unchanged. Custom manifests in Cloud cannot be scanned; their concurrency now follows the same config their streams already read.Test plan
python -m pytest "unit_tests/sources/declarative/test_concurrent_declarative_source.py::test_concurrency_level_uses_normalized_config" -q -p no:cacheprovidermainsource (git checkout origin/main -- airbyte_cdk/sources/declarative/concurrent_declarative_source.py): 2 failed,assert 1 == 4python -m pytest unit_tests/sources/declarative/test_concurrent_declarative_source.py unit_tests/sources/declarative/parsers unit_tests/legacy -q -p no:cacheprovider -k "not test_read_with_concurrent_and_synchronous_streams": 647 passed, 3 deselected. The 3 deselected tests fail locally on macOS with the SQLite cache race from Cached parent stream with more than one partition corrupts the shared sqlite request cache under concurrent reads (no such table: responses,file is not a database,no more rows available) #1150, onmaintoo.python -m pytest unit_tests/connector_builder -q -p no:cacheprovider: 63 passed.ruff format --checkandruff checkon both files,mypy --config-file mypy.ini airbyte_cdk/sources/declarative/concurrent_declarative_source.py: clean.Fixes #1147