Skip to content

feat: expose variation ID, SDK status, and harden runtime safety - #14

Open
WuJiayi0307 wants to merge 9 commits into
featbit:masterfrom
WuJiayi0307:feat/openfeature-provider
Open

feat: expose variation ID, SDK status, and harden runtime safety#14
WuJiayi0307 wants to merge 9 commits into
featbit:masterfrom
WuJiayi0307:feat/openfeature-provider

Conversation

@WuJiayi0307

@WuJiayi0307 WuJiayi0307 commented Jul 22, 2026

Copy link
Copy Markdown

Summary

This PR now contains only the FeatBit Python SDK capabilities required by the standalone OpenFeature provider:

  • expose the stable variation ID as EvalDetail.variation_id
  • add thread-safe data-update status listeners through add_listener() / remove_listener()
  • preserve backward compatibility for existing EvalDetail construction, JSON output, and custom status-provider implementations
  • update the package version to 1.1.8

The OpenFeature provider implementation has been moved to the dedicated repository:
https://github.com/featbit/openfeature-provider-python-server

Status mapping support

The provider repository maps FeatBit SDK states as follows:

  • OK → OpenFeature READY
  • INTERRUPTEDSTALE
  • OFFFATAL
  • shutdown → NOT_READY

Validation

  • FeatBit SDK: 58 passed
  • Provider repository: 52 passed
  • Flake8: passed in both repositories
  • Wheel and source distributions: built successfully
  • Isolated install smoke test: OpenFeature Client → Provider → real FeatBit offline Evaluator returned v2, variant variation-v2, status READY

The SDK PR remains compatible with Python 3.6–3.12. The standalone provider requires Python 3.10+.

Summary by CodeRabbit

  • New Features

    • Evaluation details now include a stable variation ID.
    • Added listeners for data-update status changes.
    • SDK now supports Python 3.6 through 3.12.
  • Bug Fixes

    • Improved handling of invalid offline data and unsupported evaluation defaults.
    • Strengthened event delivery, streaming, and shutdown reliability.
    • Improved concurrent evaluation and data-update consistency.
    • Prevented background-thread and configuration-state leaks.
    • Improved data storage version and snapshot handling.
  • Documentation

    • Added reliability verification guidance and updated release information for version 1.1.8.

Greptile Summary

The PR exposes stable variation IDs and SDK update status while hardening evaluation, event delivery, synchronization, and shutdown behavior.

  • Adds EvalDetail.variation_id while preserving existing construction and serialization behavior.
  • Adds thread-safe status-listener support and state transitions.
  • Improves storage consistency, worker lifecycle management, exception isolation, and packaging validation.
  • Updates the package release metadata to version 1.1.8.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
fbclient/client.py Adds lifecycle synchronization, runtime exception isolation, unsupported-default handling, offline status updates, and safe component shutdown.
fbclient/common_types.py Extends evaluation details with an optional stable variation identifier while retaining backward-compatible defaults.
fbclient/status.py Maintains synchronized status state and listener notification behavior.
fbclient/data_storage.py Strengthens storage locking, snapshot handling, and version tracking.
fbclient/event_processor.py Improves dispatcher ownership, synchronous completion, error isolation, and deterministic shutdown.
fbclient/streaming.py Improves reconnect interruption, WebSocket cleanup, status reporting, and streaming-thread shutdown.
fbclient/notice_broadcaster.py Adds synchronized listener management, snapshot-based dispatch, and repeatable queue shutdown.
fbclient/utils/repeatable_task.py Separates task cancellation from internal thread state and makes worker termination deterministic.
.github/workflows/code-quality.yaml Expands CI to audit runtime resources, build distributions, and verify wheel contents.

Sequence Diagram

sequenceDiagram
    participant App
    participant Client as FBClient
    participant Evaluator
    participant Storage as DataStorage
    participant Events as EventProcessor
    participant Status as StatusProvider
    App->>Client: variation_detail(flag, user, default)
    Client->>Storage: read flag and segment data
    Client->>Evaluator: evaluate(flag, user)
    Evaluator-->>Client: value, reason, variation ID
    Client->>Events: enqueue evaluation event
    Client-->>App: EvalDetail
    Status-->>App: notify state listener
    App->>Client: stop()
    Client->>Events: stop and drain
    Client->>Status: transition to OFF
    Client-->>App: shutdown complete
Loading

Reviews (3): Last reviewed commit: "fix: address lifecycle and concurrency r..." | Re-trigger Greptile

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Changes

The SDK adds stable variation IDs and data-update status listeners, hardens client and background-thread shutdown, isolates event failures, adds runtime audits and integration checks, updates production packaging, and documents the 1.1.8 behavior and verification procedures.

SDK behavior and validation

Layer / File(s) Summary
Evaluation and status contracts
fbclient/common_types.py, fbclient/interfaces.py, fbclient/status.py, tests/test_fbclient.py, tests/test_data_update_status_provider.py
Evaluation details expose successful variation IDs. Status listeners support registration, ordered notifications, removal, and listener-failure isolation.
Runtime lifecycle and failure isolation
fbclient/client.py, fbclient/streaming.py, fbclient/event_processor.py, fbclient/notice_broadcaster.py, fbclient/data_storage.py, fbclient/config.py, fbclient/utils/..., fbclient/__init__.py
Client shutdown becomes idempotent and guarded. Event delivery, streaming, dispatching, notice broadcasting, repeatable tasks, storage, configuration defaults, HTTP certificate handling, and offline initialization receive lifecycle and concurrency updates.
Runtime safety validation
tests/test_runtime_safety.py, tests/test_data_storage.py, tests/test_event_processor.py, scripts/resource_audit.py, scripts/live_integration_check.py
Tests and scripts exercise concurrent evaluation, listener churn, shutdown behavior, thread cleanup, memory retention, storage ordering, event flushing, and live service evaluation.
Distribution and release surfaces
setup.py, MANIFEST.in, release/*, .github/workflows/code-quality.yaml
Production package discovery, source distribution contents, development extras, version metadata, and CI audit/build checks are updated.
Usage and reliability documentation
README.md, docs/REVIEW.md
Documentation describes Python 3.12 support, status-listener usage, variation detail fields, reliability checks, live verification, and operational considerations.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant FBClient
  participant Streaming
  participant EventProcessor
  participant NoticeBroadcater
  FBClient->>Streaming: stop and join
  FBClient->>EventProcessor: stop and join dispatcher
  FBClient->>NoticeBroadcater: enqueue sentinel and join
  FBClient-->>FBClient: mark closed and isolate component failures
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: exposing variation IDs, adding SDK status support, and improving runtime safety.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

🧹 Nitpick comments (1)
tests/test_fbclient.py (1)

32-39: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Lock down the unchanged JSON contract.

This verifies constructor compatibility but not the stated backward-compatible JSON output. Assert that to_json_dict() remains unchanged even when variation_id is provided.

Proposed test addition
     assert detail_with_id.variation_id == "variation-id"
+    assert detail_with_id.to_json_dict() == legacy_detail.to_json_dict()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_fbclient.py` around lines 32 - 39, Extend
test_eval_detail_variation_id_is_backward_compatible to call to_json_dict() on
detail_with_id and assert its serialized dictionary remains identical to the
established legacy JSON contract, excluding variation_id. Keep the existing
constructor and variation_id assertions unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@featbit_openfeature/provider.py`:
- Around line 84-94: Update shutdown so _flag_change_listener is cleared only
after _client.flag_tracker.remove_flag_change_notifier(listener) succeeds; if
removal raises, retain the listener reference so cleanup can be retried and
subsequent initialization cannot register a duplicate listener.

In `@README.md`:
- Line 21: Update the README installation sentence to say “Install the SDK using
pip” instead of “install the sdk in using pip,” while preserving the Python
compatibility statement.

In `@release/description.md`:
- Around line 4-6: Update the release-note section in description.md to use the
standard heading “Breaking changes” and the text “No breaking changes,” or
remove the empty section entirely.

---

Nitpick comments:
In `@tests/test_fbclient.py`:
- Around line 32-39: Extend test_eval_detail_variation_id_is_backward_compatible
to call to_json_dict() on detail_with_id and assert its serialized dictionary
remains identical to the established legacy JSON contract, excluding
variation_id. Keep the existing constructor and variation_id assertions
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 457f6a3b-e2e5-43ec-a493-af734f3ee36a

📥 Commits

Reviewing files that changed from the base of the PR and between 0ad40d8 and e09df9d.

📒 Files selected for processing (22)
  • .github/workflows/code-quality.yaml
  • MANIFEST.in
  • README.md
  • docs/openfeature.md
  • fbclient/__init__.py
  • fbclient/common_types.py
  • featbit_openfeature/__init__.py
  • featbit_openfeature/impl/__init__.py
  • featbit_openfeature/impl/context_converter.py
  • featbit_openfeature/impl/details_converter.py
  • featbit_openfeature/provider.py
  • featbit_openfeature/py.typed
  • release/description.md
  • release/package.json
  • setup.py
  • tests/openfeature/__init__.py
  • tests/openfeature/fixtures/bootstrap.json
  • tests/openfeature/test_context_converter.py
  • tests/openfeature/test_details_converter.py
  • tests/openfeature/test_offline_integration.py
  • tests/openfeature/test_provider.py
  • tests/test_fbclient.py
💤 Files with no reviewable changes (1)
  • fbclient/init.py

Comment thread featbit_openfeature/provider.py Outdated
Comment thread README.md Outdated
Comment thread release/description.md Outdated
@WuJiayi0307

Copy link
Copy Markdown
Author

Addressed all four review findings in 06d29d1:

  • preserve the flag-change listener when removal fails so shutdown can retry without duplicate registration
  • add a regression test for failed listener removal and retry
  • lock down the unchanged EvalDetail.to_json_dict() contract
  • fix the README installation sentence and release-note heading

Validation after the fixes: 105 passed, Flake8 passes, and both wheel and source distribution rebuild successfully. The three inline review threads are now marked addressed/outdated. GitHub Actions is still awaiting first-time fork approval from a repository maintainer.

@WuJiayi0307 WuJiayi0307 changed the title feat: add OpenFeature Python server provider feat: expose variation ID and data update status listeners Jul 23, 2026

@coderabbitai coderabbitai 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
fbclient/status.py (1)

59-84: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Preserve transition order when publishing callbacks.

Concurrent update_state calls can notify in reverse order: one thread can snapshot OK, release __lock, then another can publish INTERRUPTED before the first invokes its callback. Serialize queued publications in transition order while keeping user callbacks outside __lock, and add a concurrent ordering regression test.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fbclient/status.py` around lines 59 - 84, The update_state callback flow must
preserve state-transition order under concurrent calls. Modify update_state and
its listener-publication mechanism to queue committed states while holding the
existing lock, then drain that queue serially outside __lock so callbacks
execute in transition order without invoking user listeners under the lock; add
a concurrent regression test verifying ordered OK/INTERRUPTED publications.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@fbclient/status.py`:
- Around line 59-84: The update_state callback flow must preserve
state-transition order under concurrent calls. Modify update_state and its
listener-publication mechanism to queue committed states while holding the
existing lock, then drain that queue serially outside __lock so callbacks
execute in transition order without invoking user listeners under the lock; add
a concurrent regression test verifying ordered OK/INTERRUPTED publications.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 62070b14-1267-4839-993b-9a887e3830d5

📥 Commits

Reviewing files that changed from the base of the PR and between e09df9d and 824aee8.

📒 Files selected for processing (8)
  • MANIFEST.in
  • README.md
  • fbclient/interfaces.py
  • fbclient/status.py
  • release/description.md
  • release/package.json
  • tests/test_data_update_status_provider.py
  • tests/test_fbclient.py
💤 Files with no reviewable changes (1)
  • MANIFEST.in
🚧 Files skipped from review as they are similar to previous changes (2)
  • release/package.json
  • tests/test_fbclient.py

@deleteLater

Copy link
Copy Markdown
Contributor

@greptileai

@WuJiayi0307 WuJiayi0307 changed the title feat: expose variation ID and data update status listeners feat: expose variation ID, SDK status, and harden runtime safety Jul 29, 2026
@WuJiayi0307

Copy link
Copy Markdown
Author

Completed the Python SDK reliability review in bf4c842.

Key fixes:

  • deterministic/idempotent WebSocket, event dispatcher, periodic task, and notice broadcaster shutdown
  • listener registry synchronization and interruptible reconnect backoff
  • runtime event/shutdown exception isolation
  • safe invalid bootstrap/default handling
  • independent Config defaults
  • clean production wheel excluding tests and migrated OpenFeature code

Validation:

  • 66 tests passed
  • Flake8 passed
  • 80,000 evaluations / 8 workers: 0 errors, 0 leaked SDK threads
  • retained traced memory: 24,389 bytes (threshold 2 MiB)
  • clean wheel: 27 files, no tests/, no featbit_openfeature/
  • added docs/REVIEW.md, scripts/resource_audit.py, and scripts/live_integration_check.py

FeatBit Cloud:

  • the 2026-07-24 live run verified WebSocket connection/data sync, remote python-app-release evaluation, concurrent gray-release traffic, and reconnect after disconnect
  • the new live script makes WebSocket/status/evaluation/event/flush/shutdown verification repeatable without printing or persisting the environment secret

GitHub Actions still requires maintainer approval for this fork workflow.

@coderabbitai coderabbitai 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.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/REVIEW.md`:
- Around line 82-87: Update the live integration check in
scripts/live_integration_check.py to assert that the recorded state_after_close
equals StateType.OFF, preserving the checklist’s documented OFF transition claim
alongside the existing readiness and thread-cleanup checks.

In `@fbclient/event_processor.py`:
- Around line 82-84: Guard the self.__dispatcher.join(5.0) call in the event
processor shutdown path by checking that the current thread is not
self.__dispatcher, mirroring the existing guards in sibling shutdown
implementations. Preserve the subsequent is_alive warning behavior for joins
that are performed.

In `@fbclient/notice_broadcaster.py`:
- Around line 51-55: Move self.__notice_queue.put(notice) inside the
self.__lock-protected section in broadcast(), immediately after the __closed
check, so enqueueing is serialized with stop() setting __closed and adding the
shutdown sentinel.

In `@scripts/live_integration_check.py`:
- Around line 22-26: Update sdk_threads() and its baseline/comparison logic to
capture each matching thread as an ident-to-name mapping, compare leaked threads
by thread identity rather than name, and retain the mapped names only for
reporting. Apply the same identity-based handling to the referenced lines 92-94
while preserving the existing featbit- thread filter.

In `@scripts/resource_audit.py`:
- Around line 29-31: Validate the --workers and --evaluations arguments before
the audit begins, rejecting values below 1 to prevent invalid worker-pool usage.
Update the workload partitioning near the worker execution logic to use divmod,
distributing the remainder across workers so every requested evaluation is
processed exactly once.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 19fccbb1-7b77-467d-ac44-c56f2be15355

📥 Commits

Reviewing files that changed from the base of the PR and between 824aee8 and bf4c842.

📒 Files selected for processing (18)
  • .github/workflows/code-quality.yaml
  • README.md
  • docs/REVIEW.md
  • fbclient/client.py
  • fbclient/config.py
  • fbclient/event_processor.py
  • fbclient/notice_broadcaster.py
  • fbclient/status.py
  • fbclient/streaming.py
  • fbclient/utils/http_client.py
  • fbclient/utils/repeatable_task.py
  • release/description.md
  • scripts/live_integration_check.py
  • scripts/resource_audit.py
  • setup.py
  • tests/test_data_update_status_provider.py
  • tests/test_fbclient.py
  • tests/test_runtime_safety.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • fbclient/status.py

Comment thread docs/REVIEW.md
Comment thread fbclient/event_processor.py Outdated
Comment thread fbclient/notice_broadcaster.py Outdated
Comment thread scripts/live_integration_check.py Outdated
Comment thread scripts/resource_audit.py

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

🧹 Nitpick comments (4)
fbclient/config.py (1)

176-184: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

deepcopy can raise for non-copyable sslopt values.

WebSocketConfig.sslopt accepts any mapping. If a caller stores a non-copyable object there, for example an ssl.SSLContext, deepcopy(self.__websocket) raises and copy_config_in_a_new_env fails. Both config objects only expose read-only properties, so a shallow copy of the wrapper plus an isolated defaults copy is sufficient. Consider passing the existing instances, or catching the copy failure and falling back to the original object.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fbclient/config.py` around lines 176 - 184, Update copy_config_in_a_new_env
to avoid unconditionally deep-copying self.__http and self.__websocket, since
WebSocketConfig.sslopt may contain non-copyable values. Reuse the existing
configuration instances or shallow-copy only their wrappers, while retaining the
isolated defaults copy and explicit data_storage behavior.
fbclient/client.py (2)

169-185: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

stop() holds _stop_lock during component shutdown.

stop() keeps _stop_lock while it calls component.stop(). DefaultEventProcessor.stop() waits for the dispatcher for up to five seconds, and Streaming.stop() joins its thread. A concurrent stop() call from another thread therefore blocks for the whole shutdown instead of returning at the idempotency check. The behavior stays correct, so this is optional. To make the second caller return immediately, set and test _closed under the lock, then run the shutdown loop outside the lock.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fbclient/client.py` around lines 169 - 185, Update the client stop flow
around _stop_lock and the component shutdown loop: check and set _closed while
holding _stop_lock, then release the lock before calling each component.stop().
Preserve the existing idempotency behavior and per-component exception isolation
so concurrent stop() calls return immediately while the first caller completes
shutdown.

201-215: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Type inference runs before the None check.

simple_type_inference(default_value) executes before the default_value is None branch. The result is unused in that branch. Move the inference after the None check to avoid an unnecessary call and to keep the None path independent of inference behavior.

The static analysis hint about jsonify at Line 209 does not apply here. This module is not a web framework handler.

♻️ Proposed reorder
         default_value = self._config.get_default_value(key, default)
         try:
-            default_value_type = simple_type_inference(default_value)
             if default_value is None:
                 return None, None
-            elif default_value_type == 'boolean':
+            default_value_type = simple_type_inference(default_value)
+            if default_value_type == 'boolean':
                 return default_value_type, str(default_value).lower()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fbclient/client.py` around lines 201 - 215, Update __handle_default_value so
it checks default_value is None and returns (None, None) before calling
simple_type_inference; keep the existing boolean, JSON, and fallback conversions
unchanged, with inference-related exception handling applying only to non-None
values.

Source: Linters/SAST tools

fbclient/event_processor.py (1)

189-196: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

self.__closed = True is assigned twice.

Line 189 sets __closed in the success path. Line 194 sets it again in the finally block. Keep only the assignment in finally, because that path always runs.

The Ruff BLE001 hints on the surrounding except Exception blocks are intentional here. Shutdown isolates each cleanup step.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fbclient/event_processor.py` around lines 189 - 196, Remove the redundant
self.__closed = True assignment before the except block in the event dispatcher
shutdown logic, keeping the assignment in the finally block so it executes for
every cleanup outcome. Preserve the intentional broad exception handling and the
existing flush worker shutdown behavior.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@fbclient/data_storage.py`:
- Around line 37-48: Update InMemoryDataStorage.init so an initialized empty
version-zero snapshot with version equal to self.__version is accepted as an
idempotent no-op. Preserve rejection for older versions and non-empty snapshots,
and keep the existing initialization and version-advance behavior unchanged.

In `@fbclient/streaming.py`:
- Around line 125-134: Update __prepare_connection_timeout so
_WEBSOCKET_TIMEOUT_LOCK is held only while reading and setting the
process-global websocket timeout, then restore the previous timeout and release
the lock immediately after setdefaulttimeout completes. Ensure connection
establishment no longer retains the lock, and preserve exception cleanup if
setting the timeout fails.

In `@tests/test_runtime_safety.py`:
- Around line 165-176: Add an assertion in
test_config_copy_uses_independent_storage_and_exact_queue_capacity that
copied.events_max_in_queue equals 1, alongside the existing original capacity
assertion, so the copied configuration’s queue capacity is verified.

---

Nitpick comments:
In `@fbclient/client.py`:
- Around line 169-185: Update the client stop flow around _stop_lock and the
component shutdown loop: check and set _closed while holding _stop_lock, then
release the lock before calling each component.stop(). Preserve the existing
idempotency behavior and per-component exception isolation so concurrent stop()
calls return immediately while the first caller completes shutdown.
- Around line 201-215: Update __handle_default_value so it checks default_value
is None and returns (None, None) before calling simple_type_inference; keep the
existing boolean, JSON, and fallback conversions unchanged, with
inference-related exception handling applying only to non-None values.

In `@fbclient/config.py`:
- Around line 176-184: Update copy_config_in_a_new_env to avoid unconditionally
deep-copying self.__http and self.__websocket, since WebSocketConfig.sslopt may
contain non-copyable values. Reuse the existing configuration instances or
shallow-copy only their wrappers, while retaining the isolated defaults copy and
explicit data_storage behavior.

In `@fbclient/event_processor.py`:
- Around line 189-196: Remove the redundant self.__closed = True assignment
before the except block in the event dispatcher shutdown logic, keeping the
assignment in the finally block so it executes for every cleanup outcome.
Preserve the intentional broad exception handling and the existing flush worker
shutdown behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3ea2b556-5326-4a5a-aa50-de0d79e58c3e

📥 Commits

Reviewing files that changed from the base of the PR and between bf4c842 and bd770b1.

📒 Files selected for processing (14)
  • fbclient/client.py
  • fbclient/config.py
  • fbclient/data_storage.py
  • fbclient/event_processor.py
  • fbclient/interfaces.py
  • fbclient/status.py
  • fbclient/streaming.py
  • fbclient/update_processor.py
  • fbclient/utils/__init__.py
  • fbclient/utils/http_client.py
  • tests/test_data_storage.py
  • tests/test_event_processor.py
  • tests/test_fbclient.py
  • tests/test_runtime_safety.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • fbclient/utils/http_client.py
  • fbclient/interfaces.py

Comment thread fbclient/data_storage.py Outdated
Comment thread fbclient/streaming.py
Comment thread tests/test_runtime_safety.py

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@fbclient/client.py`:
- Around line 169-192: Update client.stop() around _stop_lock and the component
cleanup loop to track the shutdown owner thread and a completion event:
recursive calls from the owner must return immediately, while other concurrent
callers wait for shutdown completion. Ensure the completion event is set in a
finally block after all components have been attempted, including when cleanup
raises unexpectedly.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0caee1a0-e1d7-4cf7-9142-ce5869e8d991

📥 Commits

Reviewing files that changed from the base of the PR and between bd770b1 and 953d7c2.

📒 Files selected for processing (2)
  • fbclient/client.py
  • tests/test_runtime_safety.py

Comment thread fbclient/client.py Outdated
Comment thread fbclient/status.py Outdated
Comment thread fbclient/client.py
Comment thread fbclient/client.py
Comment thread fbclient/client.py
Comment thread fbclient/event_processor.py Outdated
Comment thread fbclient/notice_broadcaster.py Outdated
@dsun0720

dsun0720 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

我的和robot提的issue,处理过的要点resolve conversation

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.

3 participants