Skip to content

refactor(thermidor): interface-owned caches with cascade dispose#7914

Open
jfcere-coveo wants to merge 10 commits into
mainfrom
thermidor-cache-on-interface
Open

refactor(thermidor): interface-owned caches with cascade dispose#7914
jfcere-coveo wants to merge 10 commits into
mainfrom
thermidor-cache-on-interface

Conversation

@jfcere-coveo

@jfcere-coveo jfcere-coveo commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Module-level Map caches (slices, actions, selectors) are moved to per-interface ownership via a new InterfaceCacheRegistry. Each interface disposes its own caches on dispose(), and Engine.dispose() cascades to all registered interfaces — ensuring no orphaned state after teardown.

What changed

  • New: InterfaceCacheRegistry class with typed CacheKey<T> branded symbols and a getOrCreate<T>(key, factory) method
  • New: InterfaceHandle structural type replacing unsafe as unknown as casts
  • BaseInterface / ComposedInterface: own a registry, register with Engine via addInterface/removeInterface
  • Engine: tracks interfaces in a Set, cascade dispose() to all
  • 37 factory functions: signature changed from (interfaceId: string) to (iface: InterfaceHandle), extract internals via getHandleInternals
  • Loaders removed: dedup now handled natively by registry + engine idempotency
  • Steering: added class member ordering convention

Where to focus the review

File Why
src/core/interface/cache/interface-cache-registry.ts New class — the core primitive
src/core/interface/base-interface.ts Registry ownership, engine registration, dispose cascade
src/public/interfaces/compose.ts Same pattern for ComposedInterface (shared caches)
src/core/interface/engine/engine.ts addInterface/removeInterface, cascade dispose
src/core/interface/utils/interface-types.ts InterfaceHandle, updated EndpointStateScope
src/core/interface/utils/get-handle-internals.ts Dispatches to BaseInterface or ComposedInterface, returns cacheRegistry

The remaining ~60 files are mechanical: same migration pattern applied per feature module (remove Map, add CacheKey, use getHandleInternals) + call-site updates passing iface instead of stateId.

@changeset-bot

changeset-bot Bot commented Jul 2, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: bfcd9c5

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@svcsnykcoveo

svcsnykcoveo commented Jul 2, 2026

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

Comment thread packages/thermidor/src/core/interface/cart/cart-mutators.test.ts Fixed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors Thermidor’s interface lifecycle and caching model by moving feature-module caches (slices/actions/selectors) from module-level Maps into per-interface InterfaceCacheRegistry instances, and by having the Engine track interfaces so Engine.dispose() can cascade disposal.

Changes:

  • Introduces InterfaceCacheRegistry and updates internal getOrCreate* factories to cache per interface handle (rather than globally by stateId).
  • Updates BaseInterface, ComposedInterface, and Engine to support interface registration/deregistration and disposal semantics.
  • Updates public controllers/actions/mutators/selectors and tests to pass interface handles instead of stateId strings; removes legacy loader utilities.

Reviewed changes

Copilot reviewed 112 out of 112 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
packages/thermidor/src/public/interfaces/search.ts Build path updated to adopt slices using the constructed interface handle.
packages/thermidor/src/public/interfaces/generative.ts Builds generative interface then adopts slice via interface-scoped cache factory.
packages/thermidor/src/public/interfaces/compose.ts Adds composed-owned cache registry, disposal guard, and engine registration.
packages/thermidor/src/public/interfaces/compose.test.ts Updates composed interface facade scoping expectations and naming.
packages/thermidor/src/public/controllers/search-box/search-box-controller.ts Controllers now adopt slices/selectors/actions via interface handle instead of stateId.
packages/thermidor/src/public/controllers/search-box/search-box-controller.test.ts Adjusts selector usage to getQuery(searchInterface) signature.
packages/thermidor/src/public/controllers/result-list/result-list-controller.ts Uses interface handle for slice + selectors.
packages/thermidor/src/public/controllers/result-list/result-list-controller.test.ts Updates action factory calls to accept the interface handle.
packages/thermidor/src/public/controllers/product-list/product-list-controller.ts Uses interface handle for slice + selectors.
packages/thermidor/src/public/controllers/pagination/pagination-controller.ts Uses interface handle for slice/actions/selectors; removes Dispatchable casting.
packages/thermidor/src/public/controllers/converse/converse-controller.ts Adopts generative slice via interface handle; runtime config now uses handles.
packages/thermidor/src/public/controllers/converse/converse-controller.test.ts Updates generative action factory calls to accept interface handle.
packages/thermidor/src/public/controllers/controllers-integration.test.ts Updates pagination actions to accept search/composed interface handles.
packages/thermidor/src/public/controllers/cart/cart-controller.ts Adopts cart slice and uses selectors/actions via interface handle.
packages/thermidor/src/public/controllers/cart/cart-controller.test.ts Updates cart/search-box factories to accept interface handle.
packages/thermidor/src/public/actions/search-parameters/search-parameters-actions.ts Uses interface handle for slice adoption and actions factory.
packages/thermidor/src/public/actions/search-box/search-box-state-getter.ts Uses interface handle for slice adoption and selectors factory.
packages/thermidor/src/public/actions/search-box/search-box-actions.ts Uses interface handle for slice adoption and actions factory.
packages/thermidor/src/public/actions/search-box/search-box-actions.test.ts Updates selectors factory calls to accept interface handle.
packages/thermidor/src/public/actions/cart/cart-actions.ts Uses interface handle for slice adoption and actions factory.
packages/thermidor/src/public/actions/cart/cart-actions.test.ts Updates selectors factory calls to accept interface handle.
packages/thermidor/src/index.ts Exports new InterfaceHandle type.
packages/thermidor/src/core/internal/triggers/triggers-slice.ts Migrates slice cache into interface-owned registry.
packages/thermidor/src/core/internal/triggers/triggers-actions.ts Migrates actions cache into interface-owned registry.
packages/thermidor/src/core/internal/sort/sort-slice.ts Migrates slice cache into interface-owned registry; injects actions dependency.
packages/thermidor/src/core/internal/sort/sort-selectors.ts Migrates selectors cache into interface-owned registry.
packages/thermidor/src/core/internal/sort/sort-actions.ts Migrates actions cache into interface-owned registry.
packages/thermidor/src/core/internal/search-parameters/search-parameters-slice.ts Migrates slice cache into interface-owned registry; injects actions dependency.
packages/thermidor/src/core/internal/search-parameters/search-parameters-selectors.ts Migrates selectors cache into interface-owned registry.
packages/thermidor/src/core/internal/search-parameters/search-parameters-actions.ts Migrates actions cache into interface-owned registry.
packages/thermidor/src/core/internal/search-box/search-box-slice.ts Migrates slice cache into interface-owned registry; injects actions dependency.
packages/thermidor/src/core/internal/search-box/search-box-slice.test.ts Updates tests to build minimal interfaces and call new factory signatures.
packages/thermidor/src/core/internal/search-box/search-box-selectors.ts Migrates selectors cache into interface-owned registry.
packages/thermidor/src/core/internal/search-box/search-box-actions.ts Migrates actions cache into interface-owned registry.
packages/thermidor/src/core/internal/result-list/result-list-slice.ts Migrates slice cache into interface-owned registry; injects actions/hydrate dependencies.
packages/thermidor/src/core/internal/result-list/result-list-slice.test.ts Updates tests to use interface handles and hydrate action factory.
packages/thermidor/src/core/internal/result-list/result-list-selectors.ts Migrates selectors cache into interface-owned registry.
packages/thermidor/src/core/internal/result-list/result-list-actions.ts Migrates actions cache into interface-owned registry.
packages/thermidor/src/core/internal/query-correction/query-correction-slice.ts Migrates slice cache into interface-owned registry; injects actions dependency.
packages/thermidor/src/core/internal/query-correction/query-correction-actions.ts Migrates actions cache into interface-owned registry.
packages/thermidor/src/core/internal/product-list/product-list-slice.ts Migrates slice cache into interface-owned registry; injects actions/hydrate dependencies.
packages/thermidor/src/core/internal/product-list/product-list-selectors.ts Migrates selectors cache into interface-owned registry.
packages/thermidor/src/core/internal/product-list/product-list-actions.ts Migrates actions cache into interface-owned registry.
packages/thermidor/src/core/internal/pagination/pagination-slice.ts Migrates slice cache into interface-owned registry; injects actions/hydrate dependencies.
packages/thermidor/src/core/internal/pagination/pagination-slice.test.ts Updates tests for new handle-based factories and hydrate dependency.
packages/thermidor/src/core/internal/pagination/pagination-selectors.ts Migrates selectors cache into interface-owned registry.
packages/thermidor/src/core/internal/pagination/pagination-actions.ts Migrates actions cache into interface-owned registry.
packages/thermidor/src/core/internal/generative/generative-slice.ts Migrates slice cache into interface-owned registry; injects actions dependency.
packages/thermidor/src/core/internal/generative/generative-selectors.ts Migrates selectors cache into interface-owned registry.
packages/thermidor/src/core/internal/generative/generative-actions.ts Migrates actions cache into interface-owned registry.
packages/thermidor/src/core/internal/facets/facets-slice.ts Migrates slice cache into interface-owned registry; injects actions/hydrate dependencies.
packages/thermidor/src/core/internal/facets/facets-slice.test.ts Updates tests for new handle-based factories and hydrate dependency.
packages/thermidor/src/core/internal/facets/facets-selectors.ts Migrates selectors cache into interface-owned registry.
packages/thermidor/src/core/internal/facets/facets-actions.ts Migrates actions cache into interface-owned registry.
packages/thermidor/src/core/internal/cart/cart-slice.ts Migrates slice cache into interface-owned registry; injects actions dependency.
packages/thermidor/src/core/internal/cart/cart-slice.test.ts Updates tests to create interface handle and inject actions into slice creation.
packages/thermidor/src/core/internal/cart/cart-selectors.ts Migrates selectors cache into interface-owned registry.
packages/thermidor/src/core/internal/cart/cart-actions.ts Migrates actions cache into interface-owned registry.
packages/thermidor/src/core/internal/api/search/search-thunk.ts Uses scope interface handle for thunk naming and slice adoption; response handler now takes a handle.
packages/thermidor/src/core/internal/api/search/search-thunk-slice.ts Migrates endpoint slice/selectors caches into interface-owned registry.
packages/thermidor/src/core/internal/api/search/search-response-handler.ts Response handler now scopes action factories by interface handle.
packages/thermidor/src/core/internal/api/search/search-request-selector.ts Uses scopeInterface for sharable selectors and baseInterface for base selectors.
packages/thermidor/src/core/internal/api/search/commerce-search-thunk.ts Uses scope interface handle for thunk naming and slice adoption; response handler now takes a handle.
packages/thermidor/src/core/internal/api/search/commerce-search-thunk-slice.ts Migrates commerce endpoint slice/selectors caches into interface-owned registry.
packages/thermidor/src/core/internal/api/search/commerce-search-response-handler.ts Response handler now scopes action factories by interface handle.
packages/thermidor/src/core/internal/api/search/commerce-search-request-selector.ts Uses scopeInterface for sharable selectors and baseInterface for base selectors.
packages/thermidor/src/core/internal/api/query-suggest/query-suggest-thunk.ts Thunk type now uses scopeInterface stateId.
packages/thermidor/src/core/internal/api/conversation-endpoint/conversation-endpoint-request-selector.ts Request selector now accepts interface handles for generative/cart selectors.
packages/thermidor/src/core/internal/api/commerce-query-suggest/commerce-query-suggest-thunk.ts Thunk type now uses scopeInterface stateId.
packages/thermidor/src/core/interface/utils/interface-types.ts Introduces InterfaceHandle; updates facade scoping contract to pass handles.
packages/thermidor/src/core/interface/utils/get-handle-internals.ts Returns {engine,stateId,cacheRegistry} for both base and composed handles.
packages/thermidor/src/core/interface/search-box/search-box-selectors.ts Public selector now requires an interface handle to resolve the cached selector.
packages/thermidor/src/core/interface/search-box/search-box-selectors.test.ts Updates tests to use a created interface handle for selector and slice adoption.
packages/thermidor/src/core/interface/search-box/search-box-mutators.ts Mutator now requires an interface handle (no default id).
packages/thermidor/src/core/interface/search-box/search-box-mutators.test.ts Updates tests to pass interface handle to mutator + selector.
packages/thermidor/src/core/interface/search-box/search-box-loader.ts Removes loader utility (no longer needed with interface-owned caches).
packages/thermidor/src/core/interface/search-box/search-box-loader.test.ts Removes loader tests.
packages/thermidor/src/core/interface/result-list/result-list-selectors.ts Public selector now requires an interface handle.
packages/thermidor/src/core/interface/result-list/result-list-selectors.test.ts Updates tests to use interface handle and new mutator signature.
packages/thermidor/src/core/interface/result-list/result-list-mutators.ts Mutator now requires an interface handle (no default id).
packages/thermidor/src/core/interface/result-list/result-list-mutators.test.ts Updates tests to pass interface handle to mutator + selector.
packages/thermidor/src/core/interface/result-list/result-list-loader.ts Removes loader utility (no longer needed with interface-owned caches).
packages/thermidor/src/core/interface/result-list/result-list-loader.test.ts Removes loader tests.
packages/thermidor/src/core/interface/pagination/pagination-selectors.ts Public selectors now require an interface handle.
packages/thermidor/src/core/interface/pagination/pagination-selectors.test.ts Updates tests to use interface handle and new mutator signature.
packages/thermidor/src/core/interface/pagination/pagination-mutators.ts Mutators now require an interface handle (no shared default actions).
packages/thermidor/src/core/interface/pagination/pagination-mutators.test.ts Updates tests to pass interface handle to mutators + selectors.
packages/thermidor/src/core/interface/generative/generative-loader.ts Removes loader utility (slice adoption done via interface factories).
packages/thermidor/src/core/interface/generative/generative-hydration.ts Hydration snapshot + hydrate action caching now keyed by interface handle; updates snapshot storage API.
packages/thermidor/src/core/interface/generative/generative-hydration.test.ts Updates tests to create real interfaces and use handle-based hydrate action caching.
packages/thermidor/src/core/interface/facets/facets-selectors.test.ts Updates tests to adopt slice using interface handle while exercising selectors.
packages/thermidor/src/core/interface/facets/facets-mutators.ts Mutator now requires an interface handle (no default actions).
packages/thermidor/src/core/interface/facets/facets-mutators.test.ts Updates tests for new mutator signature; currently very permissive assertions.
packages/thermidor/src/core/interface/engine/engine.ts Adds interface tracking + cascade dispose; updates hydration snapshot storage to track interface handle.
packages/thermidor/src/core/interface/engine/engine.test.ts Updates tests for new selector/mutator signatures and interface handle creation.
packages/thermidor/src/core/interface/engine/engine-dispose.test.ts Updates dispose tests for new selector/mutator signatures and handle creation.
packages/thermidor/src/core/interface/cart/cart-selectors.ts Removes re-exports and keeps handle-based internal selector access.
packages/thermidor/src/core/interface/cart/cart-mutators.ts Mutators now require an interface handle (no default id).
packages/thermidor/src/core/interface/cart/cart-mutators.test.ts Updates tests for new mutator signature; currently very permissive assertions.
packages/thermidor/src/core/interface/cart/cart-loader.ts Removes loader utility (slice adoption done via interface factories).
packages/thermidor/src/core/interface/cart/cart-loader.test.ts Removes loader tests.
packages/thermidor/src/core/interface/cache/interface-cache-registry.ts New per-interface cache registry with typed keys and disposal guards.
packages/thermidor/src/core/interface/base-interface.ts Adds cache registry ownership and engine registration; changes facade scoping to use handles.
packages/thermidor/src/core/interface/base-interface.test.ts Updates base interface tests for composed scoping and updated error messages.
packages/thermidor/src/core/interface/api/generative-endpoint/generative-runtime.ts Runtime config now accepts interface handles for request scoping.
packages/thermidor/src/core/index.ts Removes exports of deprecated loader utilities.
packages/thermidor/.kiro/steering/class-member-ordering.md Adds thermidor-specific class member ordering convention.
.kiro/specs/interface-owned-caches-and-cascade-dispose/tasks.md Adds implementation plan/spec documentation for the feature.
.kiro/specs/interface-owned-caches-and-cascade-dispose/requirements.md Adds requirements for interface-owned caches and cascade disposal.
.kiro/specs/interface-owned-caches-and-cascade-dispose/design.md Adds detailed design doc for the new caching/disposal architecture.
.kiro/specs/interface-owned-caches-and-cascade-dispose/.config.kiro Adds spec configuration metadata.
Comments suppressed due to low confidence (1)

packages/thermidor/src/core/interface/engine/engine.ts:122

  • After Engine.dispose(), the Engine instance still retains references to the Redux store, root reducer, and adopted slices, which can keep a large object graph alive if the Engine object itself remains referenced. Nulling these fields (as previously done) helps release memory earlier and better matches the PR’s memory-management goals.
    this.#interfaces.clear();
    this.#hydrationSnapshots.clear();
    this.#navigatorContextProvider = undefined;
    fullEngineWrappers.delete(this);
  }

Comment thread packages/thermidor/src/core/interface/base-interface.ts Outdated
Comment thread packages/thermidor/src/core/interface/engine/engine.ts
Comment thread packages/thermidor/src/public/interfaces/compose.test.ts Outdated
Comment thread packages/thermidor/src/core/interface/cart/cart-mutators.test.ts
Comment thread packages/thermidor/src/core/interface/cart/cart-mutators.test.ts
@pkg-pr-new

pkg-pr-new Bot commented Jul 2, 2026

Copy link
Copy Markdown
@coveo/atomic

npm i https://pkg.pr.new/@coveo/atomic@7914

@coveo/atomic-hosted-page

npm i https://pkg.pr.new/@coveo/atomic-hosted-page@7914

@coveo/atomic-legacy

npm i https://pkg.pr.new/@coveo/atomic-legacy@7914

@coveo/atomic-react

npm i https://pkg.pr.new/@coveo/atomic-react@7914

@coveo/auth

npm i https://pkg.pr.new/@coveo/auth@7914

@coveo/bueno

npm i https://pkg.pr.new/@coveo/bueno@7914

@coveo/create-atomic

npm i https://pkg.pr.new/@coveo/create-atomic@7914

@coveo/create-atomic-component

npm i https://pkg.pr.new/@coveo/create-atomic-component@7914

@coveo/create-atomic-component-project

npm i https://pkg.pr.new/@coveo/create-atomic-component-project@7914

@coveo/create-atomic-result-component

npm i https://pkg.pr.new/@coveo/create-atomic-result-component@7914

@coveo/create-atomic-rollup-plugin

npm i https://pkg.pr.new/@coveo/create-atomic-rollup-plugin@7914

@coveo/headless

npm i https://pkg.pr.new/@coveo/headless@7914

@coveo/headless-react

npm i https://pkg.pr.new/@coveo/headless-react@7914

@coveo/shopify

npm i https://pkg.pr.new/@coveo/shopify@7914

commit: bfcd9c5

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 112 out of 112 changed files in this pull request and generated 4 comments.

Comment thread packages/thermidor/src/core/interface/cache/interface-cache-registry.ts Outdated
Comment thread packages/thermidor/src/core/interface/cart/cart-selectors.ts
Comment thread packages/thermidor/src/core/interface/base-interface.ts Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants