Skip to content

chore: Add async contract-test service for FDv1 - #481

Draft
jsonbailey wants to merge 2 commits into
jb/sdk-2867/async-clientfrom
jb/sdk-2868/async-contract-tests
Draft

chore: Add async contract-test service for FDv1#481
jsonbailey wants to merge 2 commits into
jb/sdk-2867/async-clientfrom
jb/sdk-2868/async-contract-tests

Conversation

@jsonbailey

@jsonbailey jsonbailey commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

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 in AsyncClientEntity.start() (which lazily imported datasourcev2.async_polling / async_streaming) is not included here — it now raises NotImplementedError("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.py and hook.py import cleanly (no reference to any held-back datasourcev2.async_* module).
  • pycodestyle and isort --check --atomic clean on both files (the repo's mypy lint target runs on ldclient only, not contract-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 drive AsyncLDClient over 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 with NotImplementedError until a follow-up PR. Status advertises an async capability alongside the existing server-side feature set.

hook.py gains AsyncPostingHook, mirroring PostingHook but implementing AsyncHook and posting hook callbacks via asyncio.to_thread so 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.

@jsonbailey
jsonbailey requested a review from a team as a code owner August 5, 2026 22:26

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ 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.

Comment thread contract-tests/async_service.py Outdated
opts["big_segments"] = AsyncBigSegmentsConfig(**big_config)

if config_params.get("persistentDataStore") is not None:
opts["feature_store"] = _create_persistent_store(config_params["persistentDataStore"])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit bef49ae. Configure here.

Comment thread contract-tests/async_service.py Outdated
'persistent-data-store-consul',
'flag-change-listeners',
'flag-value-change-listeners',
'fdv1-fallback',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit bef49ae. Configure here.

@jsonbailey jsonbailey changed the title feat: Add async contract-test service for FDv1 chore: Add async contract-test service for FDv1 Aug 5, 2026
@jsonbailey
jsonbailey marked this pull request as draft August 5, 2026 23:08
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).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant