Skip to content

fix: reset API state on close#1430

Open
Krishan27 wants to merge 2 commits into
open-feature:mainfrom
Krishan27:fix/1374-reset-api-state-on-close
Open

fix: reset API state on close#1430
Krishan27 wants to merge 2 commits into
open-feature:mainfrom
Krishan27:fix/1374-reset-api-state-on-close

Conversation

@Krishan27

@Krishan27 Krishan27 commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Fixes #1374.

Updates the close() shutdown path so it fully resets API-managed state after provider shutdown, including providers, hooks, event handlers, global evaluation context, and transaction-context propagator state.

clearProviders() remains provider-only for backward compatibility, matching maintainer guidance.

@Krishan27 Krishan27 requested review from a team as code owners June 19, 2026 18:00
@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 59d9c7cd-331b-4fbc-b01e-b7c4ca816a76

📥 Commits

Reviewing files that changed from the base of the PR and between 842e998 and 2370531.

📒 Files selected for processing (4)
  • packages/server/test/open-feature.spec.ts
  • packages/shared/src/open-feature.ts
  • packages/web/src/open-feature.ts
  • packages/web/test/open-feature.spec.ts
💤 Files with no reviewable changes (1)
  • packages/web/src/open-feature.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/server/test/open-feature.spec.ts
  • packages/web/test/open-feature.spec.ts
  • packages/shared/src/open-feature.ts

📝 Walkthrough

Walkthrough

OpenFeatureCommonAPI.close() is refactored to fully reset API state after shutting down providers: hooks, evaluation contexts, client event caches, and API emitter handlers are all cleared. A new private _shutdownAllProviders() helper is extracted. Server and web OpenFeatureAPI subclasses add close() overrides that reset domain-scoped providers, the default provider wrapper, and (server only) the transaction context propagator. Tests across server, web, and nest packages verify the new reset semantics.

Changes

Full API state reset on close()

Layer / File(s) Summary
Shared close() teardown and _shutdownAllProviders extraction
packages/shared/src/open-feature.ts
close() now clears _hooks, evaluation context, domain-scoped context, client event handler/emitter caches, and all API emitter handlers after awaiting the new private _shutdownAllProviders(). clearProvidersAndSetDefault() is updated to call _shutdownAllProviders() directly with dedicated error logging, then always resets domain providers and recreates the default ProviderWrapper.
Server close() override and test coverage
packages/server/src/open-feature.ts, packages/server/test/open-feature.spec.ts
Server OpenFeatureAPI adds an async close() override that calls super.close(), clears _domainScopedProviders, resets _defaultProvider to NOOP_PROVIDER in NOT_READY state, and restores _transactionContextPropagator. Tests assert these reset semantics and verify clearProviders() remains provider-only without affecting hooks, contexts, or handlers.
Web close() override and test coverage
packages/web/src/open-feature.ts, packages/web/test/open-feature.spec.ts
Web OpenFeatureAPI adds an async close() override that calls super.close(), clears _domainScopedProviders, and resets _defaultProvider to NOOP_PROVIDER in NOT_READY state. clearProviders() is updated to remove a domain-scoped context clear. Tests assert close() reset semantics and verify clearProviders() remains provider-only.
Nest test reorganization for API state reset
packages/nest/test/open-feature.module.spec.ts
The "without configured providers" client-injection test block is relocated to run after provider-dependent tests, with a comment noting that module close fully resets OpenFeature API state per spec requirement 1.6.2.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~15 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: resetting API state on close, which directly addresses issue #1374.
Description check ✅ Passed The description clearly explains the changes: updating close() to reset API-managed state including providers, hooks, event handlers, evaluation context, and transaction-context propagator, while keeping clearProviders() provider-only.
Linked Issues check ✅ Passed The PR fully addresses issue #1374 requirements: close() now resets providers, hooks, event handlers, evaluation context, and transaction context propagators per spec 1.6.2, while clearProviders() remains provider-only for backward compatibility.
Out of Scope Changes check ✅ Passed All code changes are directly scoped to addressing issue #1374: implementing close() behavior per spec 1.6.2 and maintaining backward compatibility for clearProviders().
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

Implements spec requirement 1.6.2: close() now fully resets all
API-managed state after provider shutdown, including providers,
global and domain-scoped hooks, event handlers, global evaluation
context, domain-scoped evaluation context, and (server) transaction
context propagator.

clearProviders() remains provider-only for backward compatibility,
as guided by the maintainers.

Fixes open-feature#1374.

Signed-off-by: Krishan Kant Sharma <krishansharma0327@gmail.com>
@Krishan27 Krishan27 force-pushed the fix/1374-reset-api-state-on-close branch from 9ee9e52 to 842e998 Compare June 19, 2026 18:05

@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)
packages/shared/src/open-feature.ts (1)

422-439: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Deduplicate provider instances before calling onClose().

_shutdownAllProviders() currently closes the default wrapper provider and every domain wrapper provider independently. If the same provider instance is bound in multiple scopes, onClose() is invoked multiple times. That can trigger double-shutdown side effects for non-idempotent providers.

Suggested fix
   private async _shutdownAllProviders(): Promise<void> {
-    try {
-      await this?._defaultProvider.provider?.onClose?.();
-    } catch (err) {
-      this.handleShutdownError(this._defaultProvider.provider, err);
-    }
-
-    const wrappers = Array.from(this._domainScopedProviders);
-
-    await Promise.all(
-      wrappers.map(async ([, wrapper]) => {
-        try {
-          await wrapper?.provider.onClose?.();
-        } catch (err) {
-          this.handleShutdownError(wrapper?.provider, err);
-        }
-      }),
-    );
+    const uniqueProviders = new Set<P>([
+      this._defaultProvider.provider,
+      ...Array.from(this._domainScopedProviders.values()).map((wrapper) => wrapper.provider),
+    ]);
+
+    await Promise.all(
+      Array.from(uniqueProviders).map(async (provider) => {
+        try {
+          await provider?.onClose?.();
+        } catch (err) {
+          this.handleShutdownError(provider, err);
+        }
+      }),
+    );
   }
🤖 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 `@packages/shared/src/open-feature.ts` around lines 422 - 439, In the
`_shutdownAllProviders()` method, the same provider instance can have
`onClose()` called multiple times if it's bound to multiple scopes (default and
domain-scoped). Deduplicate the provider instances by collecting all unique
providers from both the default provider and domain-scoped wrappers into a
single collection (such as a Set), then iterate through the deduplicated
collection once to call `onClose()` on each unique provider instance to avoid
triggering double-shutdown side effects.
🧹 Nitpick comments (1)
packages/web/test/open-feature.spec.ts (1)

308-334: ⚡ Quick win

Add an explicit domain-scoped context assertion for clearProviders().

This block validates global context retention but does not lock the domain-scoped context contract. Adding one test here (either “retained” or “cleared,” per intended behavior) will prevent future ambiguity/regressions.

🤖 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 `@packages/web/test/open-feature.spec.ts` around lines 308 - 334, The
clearProviders() test suite in the 'does not clear global hooks', 'does not
clear global evaluation context', and 'does not remove API-level event handlers'
tests validates global-level contract retention but lacks explicit coverage for
domain-scoped context behavior. Add a new test case within the
describe('clearProviders() remains provider-only') block that sets a
domain-specific context, calls clearProviders(), and then explicitly asserts
whether the domain-scoped context is retained or cleared as intended by the API
contract. This prevents future regressions around domain-scoped context
handling.
🤖 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 `@packages/shared/src/open-feature.ts`:
- Around line 422-439: In the `_shutdownAllProviders()` method, the same
provider instance can have `onClose()` called multiple times if it's bound to
multiple scopes (default and domain-scoped). Deduplicate the provider instances
by collecting all unique providers from both the default provider and
domain-scoped wrappers into a single collection (such as a Set), then iterate
through the deduplicated collection once to call `onClose()` on each unique
provider instance to avoid triggering double-shutdown side effects.

---

Nitpick comments:
In `@packages/web/test/open-feature.spec.ts`:
- Around line 308-334: The clearProviders() test suite in the 'does not clear
global hooks', 'does not clear global evaluation context', and 'does not remove
API-level event handlers' tests validates global-level contract retention but
lacks explicit coverage for domain-scoped context behavior. Add a new test case
within the describe('clearProviders() remains provider-only') block that sets a
domain-specific context, calls clearProviders(), and then explicitly asserts
whether the domain-scoped context is retained or cleared as intended by the API
contract. This prevents future regressions around domain-scoped context
handling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: fdffd2a9-618f-47ff-8731-92f1e997fc7a

📥 Commits

Reviewing files that changed from the base of the PR and between 3c01041 and 9ee9e52.

📒 Files selected for processing (6)
  • packages/nest/test/open-feature.module.spec.ts
  • packages/server/src/open-feature.ts
  • packages/server/test/open-feature.spec.ts
  • packages/shared/src/open-feature.ts
  • packages/web/src/open-feature.ts
  • packages/web/test/open-feature.spec.ts

Signed-off-by: Krishan Kant Sharma <krishansharma0327@gmail.com>
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.

shutdown/close doesn't fully reset API state

2 participants