@leejpsd/nextjs-cache-handler 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +58 -0
- package/README.md +91 -12
- package/dist/cache-components/index.cjs +62 -6
- package/dist/cache-components/index.cjs.map +1 -1
- package/dist/cache-components/index.d.cts +1 -1
- package/dist/cache-components/index.d.ts +1 -1
- package/dist/cache-components/index.js +62 -6
- package/dist/cache-components/index.js.map +1 -1
- package/dist/incremental/index.d.cts +1 -1
- package/dist/incremental/index.d.ts +1 -1
- package/dist/index.cjs +62 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +62 -6
- package/dist/index.js.map +1 -1
- package/dist/ops/index.d.cts +1 -1
- package/dist/ops/index.d.ts +1 -1
- package/dist/shared/client/adapter-ioredis.d.cts +1 -1
- package/dist/shared/client/adapter-ioredis.d.ts +1 -1
- package/dist/shared/client/adapter-redis.d.cts +1 -1
- package/dist/shared/client/adapter-redis.d.ts +1 -1
- package/dist/{types-CgriT7My.d.cts → types-Dq1q6qXd.d.cts} +23 -1
- package/dist/{types-CgriT7My.d.ts → types-Dq1q6qXd.d.ts} +23 -1
- package/package.json +4 -2
package/dist/ops/index.d.cts
CHANGED
package/dist/ops/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Cluster, Redis } from 'ioredis';
|
|
2
|
-
import { R as RedisClientLike, a as RedisClientConfig } from '../../types-
|
|
2
|
+
import { R as RedisClientLike, a as RedisClientConfig } from '../../types-Dq1q6qXd.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Adapter for `ioredis` (and `ioredis.Cluster`).
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Cluster, Redis } from 'ioredis';
|
|
2
|
-
import { R as RedisClientLike, a as RedisClientConfig } from '../../types-
|
|
2
|
+
import { R as RedisClientLike, a as RedisClientConfig } from '../../types-Dq1q6qXd.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Adapter for `ioredis` (and `ioredis.Cluster`).
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RedisClientType } from 'redis';
|
|
2
|
-
import { R as RedisClientLike, a as RedisClientConfig } from '../../types-
|
|
2
|
+
import { R as RedisClientLike, a as RedisClientConfig } from '../../types-Dq1q6qXd.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Adapter for `redis@5` (the official `node-redis` client).
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RedisClientType } from 'redis';
|
|
2
|
-
import { R as RedisClientLike, a as RedisClientConfig } from '../../types-
|
|
2
|
+
import { R as RedisClientLike, a as RedisClientConfig } from '../../types-Dq1q6qXd.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Adapter for `redis@5` (the official `node-redis` client).
|
|
@@ -71,7 +71,7 @@ type FallbackStrategy = "auto" | "always" | "never";
|
|
|
71
71
|
* Optional — when not provided, only the process-local counters in
|
|
72
72
|
* `src/shared/metrics.ts` are updated.
|
|
73
73
|
*/
|
|
74
|
-
type MetricEventType = "cache.hit" | "cache.miss" | "cache.stale" | "cache.set" | "cache.set.failed" | "tag.invalidate.soft" | "tag.invalidate.hard" | "tag.expiration.read" | "redis.connect.failed" | "redis.timeout" | "fallback.activated" | "build_phase.skip";
|
|
74
|
+
type MetricEventType = "cache.hit" | "cache.miss" | "cache.stale" | "cache.stale.refresh.leader" | "cache.stale.refresh.follower" | "cache.stale.refresh.skipped" | "cache.set" | "cache.set.failed" | "tag.invalidate.soft" | "tag.invalidate.hard" | "tag.expiration.read" | "redis.connect.failed" | "redis.timeout" | "fallback.activated" | "build_phase.skip";
|
|
75
75
|
interface MetricEvent {
|
|
76
76
|
type: MetricEventType;
|
|
77
77
|
/** Operation latency in milliseconds, when measurable. */
|
|
@@ -141,6 +141,28 @@ interface CacheHandlerOptions {
|
|
|
141
141
|
* Default: `true`. Set to `false` to revert to "expire on revalidate" behavior.
|
|
142
142
|
*/
|
|
143
143
|
staleWhileRevalidate?: boolean;
|
|
144
|
+
/**
|
|
145
|
+
* Single-flight refresh lock for the SWR boundary.
|
|
146
|
+
*
|
|
147
|
+
* When enabled, only one handler instance per cache key attempts a
|
|
148
|
+
* background refresh during the stale window. Other instances continue
|
|
149
|
+
* serving the same stale entry until the leader publishes a fresh one or
|
|
150
|
+
* the lock TTL expires. Prevents N parallel refreshes (cache stampede)
|
|
151
|
+
* when many instances cross the `revalidate` boundary at the same time.
|
|
152
|
+
*
|
|
153
|
+
* Default: `false`. The marginal benefit at small scale is small because
|
|
154
|
+
* Next.js already serializes per-cacheKey refresh per process; turn this
|
|
155
|
+
* on when you have many instances and observe duplicate origin work
|
|
156
|
+
* around the revalidate boundary.
|
|
157
|
+
*/
|
|
158
|
+
singleFlight?: boolean;
|
|
159
|
+
/**
|
|
160
|
+
* Lock TTL in seconds for `singleFlight` mode. Default: 10.
|
|
161
|
+
*
|
|
162
|
+
* Long enough that a normal refresh can complete (most are sub-second),
|
|
163
|
+
* short enough that a crashed leader doesn't block followers for long.
|
|
164
|
+
*/
|
|
165
|
+
singleFlightLockTtlSec?: number;
|
|
144
166
|
/**
|
|
145
167
|
* Override the build-phase detector. Default checks
|
|
146
168
|
* `process.env.NEXT_PHASE === "phase-production-build"`.
|
|
@@ -71,7 +71,7 @@ type FallbackStrategy = "auto" | "always" | "never";
|
|
|
71
71
|
* Optional — when not provided, only the process-local counters in
|
|
72
72
|
* `src/shared/metrics.ts` are updated.
|
|
73
73
|
*/
|
|
74
|
-
type MetricEventType = "cache.hit" | "cache.miss" | "cache.stale" | "cache.set" | "cache.set.failed" | "tag.invalidate.soft" | "tag.invalidate.hard" | "tag.expiration.read" | "redis.connect.failed" | "redis.timeout" | "fallback.activated" | "build_phase.skip";
|
|
74
|
+
type MetricEventType = "cache.hit" | "cache.miss" | "cache.stale" | "cache.stale.refresh.leader" | "cache.stale.refresh.follower" | "cache.stale.refresh.skipped" | "cache.set" | "cache.set.failed" | "tag.invalidate.soft" | "tag.invalidate.hard" | "tag.expiration.read" | "redis.connect.failed" | "redis.timeout" | "fallback.activated" | "build_phase.skip";
|
|
75
75
|
interface MetricEvent {
|
|
76
76
|
type: MetricEventType;
|
|
77
77
|
/** Operation latency in milliseconds, when measurable. */
|
|
@@ -141,6 +141,28 @@ interface CacheHandlerOptions {
|
|
|
141
141
|
* Default: `true`. Set to `false` to revert to "expire on revalidate" behavior.
|
|
142
142
|
*/
|
|
143
143
|
staleWhileRevalidate?: boolean;
|
|
144
|
+
/**
|
|
145
|
+
* Single-flight refresh lock for the SWR boundary.
|
|
146
|
+
*
|
|
147
|
+
* When enabled, only one handler instance per cache key attempts a
|
|
148
|
+
* background refresh during the stale window. Other instances continue
|
|
149
|
+
* serving the same stale entry until the leader publishes a fresh one or
|
|
150
|
+
* the lock TTL expires. Prevents N parallel refreshes (cache stampede)
|
|
151
|
+
* when many instances cross the `revalidate` boundary at the same time.
|
|
152
|
+
*
|
|
153
|
+
* Default: `false`. The marginal benefit at small scale is small because
|
|
154
|
+
* Next.js already serializes per-cacheKey refresh per process; turn this
|
|
155
|
+
* on when you have many instances and observe duplicate origin work
|
|
156
|
+
* around the revalidate boundary.
|
|
157
|
+
*/
|
|
158
|
+
singleFlight?: boolean;
|
|
159
|
+
/**
|
|
160
|
+
* Lock TTL in seconds for `singleFlight` mode. Default: 10.
|
|
161
|
+
*
|
|
162
|
+
* Long enough that a normal refresh can complete (most are sub-second),
|
|
163
|
+
* short enough that a crashed leader doesn't block followers for long.
|
|
164
|
+
*/
|
|
165
|
+
singleFlightLockTtlSec?: number;
|
|
144
166
|
/**
|
|
145
167
|
* Override the build-phase detector. Default checks
|
|
146
168
|
* `process.env.NEXT_PHASE === "phase-production-build"`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leejpsd/nextjs-cache-handler",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "The only Redis cache handler for Next.js 16 that ships both cacheHandler (ISR) and cacheHandlers ('use cache') — production-validated for multi-instance deployments where @fortedigital lists 'Help needed'.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"next",
|
|
@@ -127,7 +127,9 @@
|
|
|
127
127
|
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.test.json",
|
|
128
128
|
"test": "vitest run",
|
|
129
129
|
"test:unit": "vitest run tests/unit",
|
|
130
|
-
"test:integration": "vitest run
|
|
130
|
+
"test:integration": "vitest run --config vitest.integration.config.ts",
|
|
131
|
+
"test:integration:up": "docker compose -f docker-compose.test.yml up -d --wait",
|
|
132
|
+
"test:integration:down": "docker compose -f docker-compose.test.yml down",
|
|
131
133
|
"test:watch": "vitest",
|
|
132
134
|
"test:coverage": "vitest run --coverage",
|
|
133
135
|
"format": "prettier --write \"src/**/*.{ts,tsx}\" \"tests/**/*.{ts,tsx}\"",
|