Skip to content

Feature/compt 57 cacheable cacheevict decorators#3

Merged
y-aithnini merged 8 commits intodevelopfrom
feature/COMPT-57-cacheable-cacheevict-decorators
Apr 3, 2026
Merged

Feature/compt 57 cacheable cacheevict decorators#3
y-aithnini merged 8 commits intodevelopfrom
feature/COMPT-57-cacheable-cacheevict-decorators

Conversation

@y-aithnini
Copy link
Copy Markdown

Summary

  • What does this PR change?

Why

  • Why is this change needed?

Checklist

  • Added/updated tests (if behavior changed)
  • npm run lint passes
  • npm run typecheck passes
  • npm test passes
  • npm run build passes
  • Added a changeset (npx changeset) if this affects consumers

Notes

  • Anything reviewers should pay attention to?

@y-aithnini y-aithnini requested a review from a team as a code owner April 3, 2026 11:15
Copilot AI review requested due to automatic review settings April 3, 2026 11:15
@y-aithnini y-aithnini merged commit ccd8c89 into develop Apr 3, 2026
1 check passed
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 3, 2026

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds consumer-facing method decorators to CacheKit to support automatic cache-aside reads and post-operation cache eviction, wired into the module lifecycle so decorators can access CacheService without explicit injection.

Changes:

  • Added @Cacheable and @CacheEvict decorators and exported them from the public entrypoint.
  • Introduced utilities for cache key template resolution and a module-scoped CacheService reference used by decorators.
  • Updated CacheModule to populate the decorator-accessible CacheService reference during onModuleInit().

Reviewed changes

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

Show a summary per file
File Description
tsconfig.json Updates TS path aliases (currently introduces a duplicate @utils/* key).
src/utils/resolve-cache-key.util.ts Adds runtime {n} placeholder interpolation for cache key templates.
src/utils/cache-service-ref.ts Adds a module-scoped singleton reference used by decorators to access CacheService.
src/index.ts Exposes Cacheable / CacheEvict as part of the package public API.
src/decorators/cacheable.decorator.ts Implements cache-aside behavior around method execution.
src/decorators/cache-evict.decorator.ts Implements cache eviction after successful method execution.
src/cache-kit.module.ts Populates the decorator-accessible cache service reference on module init.

Comment on lines +77 to +78
// Persist the result under the resolved key for future calls
await cacheService.set(resolvedKey, result, ttlSeconds);
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

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

Cacheable will attempt to cache whatever the wrapped method returns. If the method returns undefined (common for void/command-style methods), JSON.stringify(undefined) yields undefined, which is not valid JSON and will cause reads to always miss (or potentially fail depending on the store implementation). Consider skipping cacheService.set() when the result is undefined, or coercing/handling it explicitly.

Suggested change
// Persist the result under the resolved key for future calls
await cacheService.set(resolvedKey, result, ttlSeconds);
// Persist the result under the resolved key for future calls.
// Skip caching undefined because some cache stores serialize values as JSON,
// and JSON.stringify(undefined) does not produce a valid cache payload.
if (result !== undefined) {
await cacheService.set(resolvedKey, result, ttlSeconds);
}

Copilot uses AI. Check for mistakes.
Comment on lines +46 to +52
* Called once by CacheModule.onModuleInit().
*
* @param service - The resolved CacheService from NestJS DI
*/
set(service: CacheService): void {
// Overwrite any prior value — safe for hot-reload scenarios
_instance = service;
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

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

CacheServiceRef.set() unconditionally overwrites the previously stored instance. If CacheModule.register() is imported more than once in the same process (e.g., different feature modules with different cache configs), whichever module initializes last will silently take over and all decorators will use the wrong CacheService. Consider preventing re-initialization (throw if already set with a different instance) or otherwise scoping the reference so multiple module instances can coexist safely.

Suggested change
* Called once by CacheModule.onModuleInit().
*
* @param service - The resolved CacheService from NestJS DI
*/
set(service: CacheService): void {
// Overwrite any prior value — safe for hot-reload scenarios
_instance = service;
* Called by CacheModule.onModuleInit().
*
* Re-initialisation is allowed only when the same instance is provided again
* (for example, during an idempotent bootstrap path). A different instance is
* rejected because decorators resolve this module-scoped reference globally,
* and silently replacing it would make them use the wrong CacheService.
*
* @param service - The resolved CacheService from NestJS DI
* @throws {Error} If a different CacheService instance was already registered
*/
set(service: CacheService): void {
if (_instance === null) {
_instance = service;
return;
}
if (_instance !== service) {
throw new Error(
"[CacheKit] CacheServiceRef has already been initialised with a different instance. " +
"Multiple CacheModule.register() or CacheModule.registerAsync() imports in the same " +
"process are not supported by the global decorator cache reference.",
);
}

Copilot uses AI. Check for mistakes.
Comment on lines +55 to +61
// Method decorators for automatic caching and cache invalidation.
// Apply these to service methods — no manual CacheService injection needed.

// Cache-aside decorator: returns cached value or calls the method and stores the result
export { Cacheable } from "./decorators/cacheable.decorator";
// Cache eviction decorator: deletes the cache entry after the method executes
export { CacheEvict } from "./decorators/cache-evict.decorator";
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

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

This PR adds new public exports (Cacheable, CacheEvict) from the package entrypoint. Since this changes the consumer-facing API, add a changeset (npx changeset) so the version/changelog is updated consistently with the repo’s release workflow.

Copilot uses AI. Check for mistakes.
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.

2 participants