chore: Add async contract-test service for FDv1 - #481
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit bef49ae. Configure here.
| opts["big_segments"] = AsyncBigSegmentsConfig(**big_config) | ||
|
|
||
| if config_params.get("persistentDataStore") is not None: | ||
| opts["feature_store"] = _create_persistent_store(config_params["persistentDataStore"]) |
There was a problem hiding this comment.
Incompatible sync persistent stores
High Severity
_create_persistent_store returns sync FeatureStore instances from Redis/DynamoDB/Consul, but AsyncConfig.feature_store requires an AsyncFeatureStore. Advertising the persistent-store capabilities causes the harness to exercise this path, and later await store.get/init/... calls fail at runtime.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit bef49ae. Configure here.
| 'persistent-data-store-consul', | ||
| 'flag-change-listeners', | ||
| 'flag-value-change-listeners', | ||
| 'fdv1-fallback', |
There was a problem hiding this comment.
Unsupported fdv1-fallback capability
High Severity
The status response advertises fdv1-fallback, but dataSystem configuration raises NotImplementedError. That capability depends on FDv2 fdv1Fallback wiring, so the harness will select fallback tests that cannot succeed.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit bef49ae. Configure here.
Drop capabilities the FDv1-only async service cannot satisfy: the persistent-data-store-* entries (no async persistent feature store exists; the sync store cannot be awaited), fdv1-fallback (an FDv2 dataSystem feature that raises NotImplementedError), and the unrecognized 'async' entry. Remove the now-dead persistentDataStore handling and the _create_persistent_store helper, plus the unused _set_optional_time / _set_optional_value helpers and Callable import. Also close a partially-started client before returning 500 so it does not leak tasks or sessions, and align the migrator build-failure shape with the sync service (return 200 with the error string instead of raising).


Summary
Adds the async contract-test service so the SDK contract-test harness can exercise
AsyncLDClient. Covers FDv1 (streaming / polling / LDD), hooks, and migration handlers.What's included
contract-tests/async_service.py— async client entity + Flask routes for the contract-test harness (FDv1 config, evaluation, hooks, migrations).contract-tests/hook.py— hook test support shared by the service.Held back for a later PR (FDv2)
FDv2 support is deferred to PR 11. The
dataSystem(FDv2) branch inAsyncClientEntity.start()(which lazily importeddatasourcev2.async_polling/async_streaming) is not included here — it now raisesNotImplementedError("FDv2 (dataSystem) is not yet supported in the async contract-test service"). The FDv1 streaming / polling / LDD paths, hooks, and migration handlers are unchanged.Verification
async_service.pyandhook.pyimport cleanly (no reference to any held-backdatasourcev2.async_*module).pycodestyleandisort --check --atomicclean on both files (the repo'smypylint target runs onldclientonly, notcontract-tests).Note
Low Risk
Test-only harness code with no production SDK behavior changes; FDv2 explicitly rejected at startup.
Overview
Adds an async contract-test harness (
contract-tests/async_service.py) so the shared SDK contract suite can driveAsyncLDClientover the same HTTP shape as the existing Flask sync service, but implemented with aiohttp.The service wires harness configuration into
AsyncConfig(FDv1 streaming/polling/LDD, events, big segments, persistent stores, hooks) and exposes commands for evaluation, events, context helpers, migrations, and flag listeners.dataSystem(FDv2) configs fail fast withNotImplementedErroruntil a follow-up PR. Status advertises anasynccapability alongside the existing server-side feature set.hook.pygainsAsyncPostingHook, mirroringPostingHookbut implementingAsyncHookand posting hook callbacks viaasyncio.to_threadso the event loop stays unblocked.Reviewed by Cursor Bugbot for commit bef49ae. Bugbot is set up for automated code reviews on this repo. Configure here.