@reprova/sdk 0.5.0 → 0.6.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/README.md +75 -0
- package/dist/cjs/context.js +28 -0
- package/dist/cjs/distributionBaselinePoller.js +87 -0
- package/dist/cjs/distributionDrift.js +170 -0
- package/dist/cjs/drizzle.js +204 -0
- package/dist/cjs/frameworkAdapter.js +2 -0
- package/dist/cjs/httpFetch.js +59 -0
- package/dist/cjs/idempotency.js +132 -0
- package/dist/cjs/idempotencySettingsPoller.js +71 -0
- package/dist/cjs/index.js +96 -0
- package/dist/cjs/invariantInference.js +90 -0
- package/dist/cjs/invariantRules.js +142 -0
- package/dist/cjs/knex.js +86 -0
- package/dist/cjs/kysely.js +175 -0
- package/dist/cjs/legacyPrisma.js +130 -0
- package/dist/cjs/mikroorm.js +74 -0
- package/dist/cjs/mongoSchemaReporter.js +85 -0
- package/dist/cjs/mongoose.js +335 -0
- package/dist/cjs/nPlusOne.js +0 -0
- package/dist/cjs/nest.js +136 -0
- package/dist/cjs/nextjs.js +180 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/prisma.js +363 -0
- package/dist/cjs/proto.gen.js +4 -0
- package/dist/cjs/registry.js +100 -0
- package/dist/cjs/retryStorm.js +70 -0
- package/dist/cjs/rulesPoller.js +77 -0
- package/dist/cjs/sdk.js +1231 -0
- package/dist/cjs/sequelize.js +108 -0
- package/dist/cjs/shape.js +45 -0
- package/dist/cjs/stack.js +51 -0
- package/dist/cjs/transport.js +71 -0
- package/dist/cjs/typeorm.js +200 -0
- package/dist/context.d.ts +18 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js.map +1 -1
- package/dist/distributionBaselinePoller.d.ts +36 -0
- package/dist/distributionBaselinePoller.d.ts.map +1 -0
- package/dist/distributionBaselinePoller.js +84 -0
- package/dist/distributionBaselinePoller.js.map +1 -0
- package/dist/distributionDrift.d.ts +41 -0
- package/dist/distributionDrift.d.ts.map +1 -0
- package/dist/distributionDrift.js +161 -0
- package/dist/distributionDrift.js.map +1 -0
- package/dist/drizzle.d.ts.map +1 -1
- package/dist/drizzle.js +10 -4
- package/dist/drizzle.js.map +1 -1
- package/dist/frameworkAdapter.d.ts +5 -0
- package/dist/frameworkAdapter.d.ts.map +1 -0
- package/dist/frameworkAdapter.js +2 -0
- package/dist/frameworkAdapter.js.map +1 -0
- package/dist/httpFetch.d.ts +13 -0
- package/dist/httpFetch.d.ts.map +1 -0
- package/dist/httpFetch.js +54 -0
- package/dist/httpFetch.js.map +1 -0
- package/dist/idempotency.d.ts +26 -0
- package/dist/idempotency.d.ts.map +1 -0
- package/dist/idempotency.js +124 -0
- package/dist/idempotency.js.map +1 -0
- package/dist/idempotencySettingsPoller.d.ts +23 -0
- package/dist/idempotencySettingsPoller.d.ts.map +1 -0
- package/dist/idempotencySettingsPoller.js +68 -0
- package/dist/idempotencySettingsPoller.js.map +1 -0
- package/dist/index.d.ts +30 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -3
- package/dist/index.js.map +1 -1
- package/dist/invariantInference.d.ts +28 -0
- package/dist/invariantInference.d.ts.map +1 -0
- package/dist/invariantInference.js +87 -0
- package/dist/invariantInference.js.map +1 -0
- package/dist/invariantRules.d.ts +16 -0
- package/dist/invariantRules.d.ts.map +1 -0
- package/dist/invariantRules.js +104 -0
- package/dist/invariantRules.js.map +1 -0
- package/dist/knex.d.ts.map +1 -1
- package/dist/knex.js +1 -0
- package/dist/knex.js.map +1 -1
- package/dist/kysely.d.ts.map +1 -1
- package/dist/kysely.js +2 -1
- package/dist/kysely.js.map +1 -1
- package/dist/legacyPrisma.d.ts +6 -0
- package/dist/legacyPrisma.d.ts.map +1 -0
- package/dist/legacyPrisma.js +128 -0
- package/dist/legacyPrisma.js.map +1 -0
- package/dist/mikroorm.d.ts +2 -0
- package/dist/mikroorm.d.ts.map +1 -0
- package/dist/mikroorm.js +72 -0
- package/dist/mikroorm.js.map +1 -0
- package/dist/mongoSchemaReporter.d.ts +23 -0
- package/dist/mongoSchemaReporter.d.ts.map +1 -0
- package/dist/mongoSchemaReporter.js +82 -0
- package/dist/mongoSchemaReporter.js.map +1 -0
- package/dist/mongoose.d.ts +48 -0
- package/dist/mongoose.d.ts.map +1 -0
- package/dist/mongoose.js +331 -0
- package/dist/mongoose.js.map +1 -0
- package/dist/nPlusOne.d.ts +52 -0
- package/dist/nPlusOne.d.ts.map +1 -0
- package/dist/nPlusOne.js +0 -0
- package/dist/nPlusOne.js.map +1 -0
- package/dist/nest.d.ts +13 -0
- package/dist/nest.d.ts.map +1 -1
- package/dist/nest.js +39 -0
- package/dist/nest.js.map +1 -1
- package/dist/nextjs.d.ts +27 -0
- package/dist/nextjs.d.ts.map +1 -0
- package/dist/nextjs.js +178 -0
- package/dist/nextjs.js.map +1 -0
- package/dist/prisma.d.ts +21 -5
- package/dist/prisma.d.ts.map +1 -1
- package/dist/prisma.js +247 -22
- package/dist/prisma.js.map +1 -1
- package/dist/proto.gen.d.ts +10 -2
- package/dist/proto.gen.d.ts.map +1 -1
- package/dist/registry.d.ts +1 -0
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +24 -0
- package/dist/registry.js.map +1 -1
- package/dist/retryStorm.d.ts +42 -0
- package/dist/retryStorm.d.ts.map +1 -0
- package/dist/retryStorm.js +65 -0
- package/dist/retryStorm.js.map +1 -0
- package/dist/rulesPoller.d.ts +26 -0
- package/dist/rulesPoller.d.ts.map +1 -0
- package/dist/rulesPoller.js +74 -0
- package/dist/rulesPoller.js.map +1 -0
- package/dist/sdk.d.ts +48 -7
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +619 -47
- package/dist/sdk.js.map +1 -1
- package/dist/sequelize.d.ts.map +1 -1
- package/dist/sequelize.js +4 -3
- package/dist/sequelize.js.map +1 -1
- package/dist/stack.d.ts.map +1 -1
- package/dist/stack.js +6 -3
- package/dist/stack.js.map +1 -1
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +2 -1
- package/dist/transport.js.map +1 -1
- package/dist/typeorm.d.ts +1 -0
- package/dist/typeorm.d.ts.map +1 -1
- package/dist/typeorm.js +133 -1
- package/dist/typeorm.js.map +1 -1
- package/package.json +14 -5
package/dist/proto.gen.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proto.gen.d.ts","sourceRoot":"","sources":["../src/proto.gen.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,qBAAqB,GAAG,UAAU,GAAG,gBAAgB,GAAG,WAAW,GAAG,aAAa,GAAG,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"proto.gen.d.ts","sourceRoot":"","sources":["../src/proto.gen.ts"],"names":[],"mappings":"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"}
|
package/dist/registry.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ReprovaContext, FootprintQuery } from './context.js';
|
|
2
2
|
export declare function registerContext(ctx: ReprovaContext): void;
|
|
3
3
|
export declare function completeContext(ctx: ReprovaContext): void;
|
|
4
|
+
export declare function findContextByTraceId(traceId: string): ReprovaContext | undefined;
|
|
4
5
|
export interface ConcurrentRequestSnapshot {
|
|
5
6
|
trace_id: string;
|
|
6
7
|
offset_ms: number;
|
package/dist/registry.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAwCnE,wBAAgB,eAAe,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAGzD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CASzD;AAKD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAEhF;AAID,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,WAAW,GAAG,WAAW,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAChC,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACvC,CAAC;IACF,cAAc,CAAC,EAAE;QAAE,OAAO,EAAE,cAAc,EAAE,CAAA;KAAE,CAAC;CAChD;AAOD,wBAAgB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,yBAAyB,EAAE,CAmBnF;AA2BD,wBAAgB,qBAAqB,IAAI,IAAI,CAI5C"}
|
package/dist/registry.js
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import { stripHeaders } from './stack.js';
|
|
2
2
|
const active = new Set();
|
|
3
3
|
const recent = [];
|
|
4
|
+
// Recovery index for when AsyncLocalStorage's active store has gone missing
|
|
5
|
+
// partway through a request — keyed by traceId rather than object identity,
|
|
6
|
+
// because the framework layer that lost the ALS store may ALSO have
|
|
7
|
+
// constructed a brand-new request object with no reference in common with
|
|
8
|
+
// the one instrumentHttpServers saw (Next.js App Router builds its own Fetch
|
|
9
|
+
// API Request rather than reusing the raw http.IncomingMessage; Pages Router
|
|
10
|
+
// and Express-style frameworks mutate the SAME object instead, which is what
|
|
11
|
+
// ctxByRequest in sdk.ts already handles). traceId survives that boundary
|
|
12
|
+
// because contextFromIncoming writes the resolved value back onto the raw
|
|
13
|
+
// request's headers before handing off to whatever dispatches next — any
|
|
14
|
+
// correct request implementation must copy incoming headers, so the injected
|
|
15
|
+
// traceparent is guaranteed to reach a freshly-constructed request even when
|
|
16
|
+
// object identity doesn't. See nextjs.ts's wrapRouteHandler for the consumer.
|
|
17
|
+
const byTraceId = new Map();
|
|
4
18
|
const RECENT_CAP = 16;
|
|
5
19
|
const RETENTION_MS = 5000;
|
|
6
20
|
const COHORT_CAP = 8; // must match capture_payload.json's maxItems
|
|
@@ -8,17 +22,26 @@ const BODY_CAP = 16 * 1024;
|
|
|
8
22
|
const FOOTPRINT_QUERY_CAP = 200;
|
|
9
23
|
export function registerContext(ctx) {
|
|
10
24
|
active.add(ctx);
|
|
25
|
+
byTraceId.set(ctx.traceId, ctx);
|
|
11
26
|
}
|
|
12
27
|
export function completeContext(ctx) {
|
|
13
28
|
// 'finish' and 'close' can both fire for one response — only move once.
|
|
14
29
|
if (!active.delete(ctx))
|
|
15
30
|
return;
|
|
31
|
+
if (byTraceId.get(ctx.traceId) === ctx)
|
|
32
|
+
byTraceId.delete(ctx.traceId);
|
|
16
33
|
recent.push({ ctx, endedAt: new Date() });
|
|
17
34
|
const cutoff = Date.now() - RETENTION_MS;
|
|
18
35
|
while (recent.length > RECENT_CAP || (recent.length > 0 && recent[0].endedAt.getTime() < cutoff)) {
|
|
19
36
|
recent.shift();
|
|
20
37
|
}
|
|
21
38
|
}
|
|
39
|
+
// Looks up a still-in-flight context by its traceId. Returns undefined once
|
|
40
|
+
// the request has completed (completeContext already removed it) — recovery
|
|
41
|
+
// only ever targets a request that is still being handled.
|
|
42
|
+
export function findContextByTraceId(traceId) {
|
|
43
|
+
return byTraceId.get(traceId);
|
|
44
|
+
}
|
|
22
45
|
// snapshotCohort returns every other request that overlapped the failing one:
|
|
23
46
|
// all currently-active contexts, plus recently-completed ones that ended at or
|
|
24
47
|
// after the failing request started (their writes shaped the state the failing
|
|
@@ -65,6 +88,7 @@ function toSnapshot(ctx, failingStart, state, endedAt) {
|
|
|
65
88
|
// Test hook: clears all registry state between tests.
|
|
66
89
|
export function resetRegistryForTests() {
|
|
67
90
|
active.clear();
|
|
91
|
+
byTraceId.clear();
|
|
68
92
|
recent.length = 0;
|
|
69
93
|
}
|
|
70
94
|
//# sourceMappingURL=registry.js.map
|
package/dist/registry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAe1C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;AACzC,MAAM,MAAM,GAAqB,EAAE,CAAC;AAEpC,MAAM,UAAU,GAAG,EAAE,CAAC;AACtB,MAAM,YAAY,GAAG,IAAI,CAAC;AAC1B,MAAM,UAAU,GAAG,CAAC,CAAC,CAAC,6CAA6C;AACnE,MAAM,QAAQ,GAAG,EAAE,GAAG,IAAI,CAAC;AAC3B,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEhC,MAAM,UAAU,eAAe,CAAC,GAAmB;IACjD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { OutboundCall } from './context.js';
|
|
2
|
+
export interface RetryStormFinding {
|
|
3
|
+
host: string;
|
|
4
|
+
method: string;
|
|
5
|
+
path: string;
|
|
6
|
+
count: number;
|
|
7
|
+
failureCount: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Groups a request's recorded outbound calls by (host, method, pathname —
|
|
11
|
+
* query string stripped) and flags any group that both repeats at or above
|
|
12
|
+
* the threshold AND includes at least one failing call.
|
|
13
|
+
*
|
|
14
|
+
* Both conditions matter: repetition alone doesn't distinguish a retry storm
|
|
15
|
+
* from legitimate pagination or batch fetching against a healthy dependency
|
|
16
|
+
* (all 200s) — requiring at least one failure targets specifically "the app
|
|
17
|
+
* kept calling a target that was failing," the actual retry-amplification
|
|
18
|
+
* pattern, not "the app called the same endpoint several times." Query
|
|
19
|
+
* string is stripped before grouping because a real retry commonly varies a
|
|
20
|
+
* request id or cache-busting param per attempt — grouping on the exact
|
|
21
|
+
* path would make every retry look like a distinct, one-off call and never
|
|
22
|
+
* cross the threshold.
|
|
23
|
+
*/
|
|
24
|
+
export declare function detectRetryStorm(calls: OutboundCall[], threshold: number): RetryStormFinding[];
|
|
25
|
+
/**
|
|
26
|
+
* A stable, digit-free description — same fingerprinting reasoning as
|
|
27
|
+
* describeNPlusOne: the exact count varies request to request, and must not
|
|
28
|
+
* appear in the message or two occurrences of the same underlying storm
|
|
29
|
+
* would never fingerprint into the same issue.
|
|
30
|
+
*/
|
|
31
|
+
export declare function describeRetryStorm(finding: RetryStormFinding): string;
|
|
32
|
+
/**
|
|
33
|
+
* A real Error subclass, not a plain Error with `.name` reassigned — same
|
|
34
|
+
* reasoning as PotentialNPlusOneQuery: capture() derives the payload's
|
|
35
|
+
* error.type (which becomes the issue title verbatim) from
|
|
36
|
+
* err.constructor.name, which for a plain Error is always "Error" no matter
|
|
37
|
+
* what `.name` gets set to afterward.
|
|
38
|
+
*/
|
|
39
|
+
export declare class PotentialRetryStorm extends Error {
|
|
40
|
+
constructor(finding: RetryStormFinding);
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=retryStorm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retryStorm.d.ts","sourceRoot":"","sources":["../src/retryStorm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IAEf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;CACtB;AAWD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAmB9F;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAErE;AAED;;;;;;GAMG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,iBAAiB;CAGvC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// A call counts as failed for this purpose if it never got a real response
|
|
2
|
+
// (status 0, the SDK's convention for a network error or timeout — see
|
|
3
|
+
// sdk.ts's patchedFetch) or the server itself reported failure (5xx). 4xx is
|
|
4
|
+
// deliberately excluded: a repeated 404 or 401 is a caller bug, not a
|
|
5
|
+
// struggling dependency being hammered.
|
|
6
|
+
function isFailingCall(call) {
|
|
7
|
+
return call.status === 0 || call.status >= 500;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Groups a request's recorded outbound calls by (host, method, pathname —
|
|
11
|
+
* query string stripped) and flags any group that both repeats at or above
|
|
12
|
+
* the threshold AND includes at least one failing call.
|
|
13
|
+
*
|
|
14
|
+
* Both conditions matter: repetition alone doesn't distinguish a retry storm
|
|
15
|
+
* from legitimate pagination or batch fetching against a healthy dependency
|
|
16
|
+
* (all 200s) — requiring at least one failure targets specifically "the app
|
|
17
|
+
* kept calling a target that was failing," the actual retry-amplification
|
|
18
|
+
* pattern, not "the app called the same endpoint several times." Query
|
|
19
|
+
* string is stripped before grouping because a real retry commonly varies a
|
|
20
|
+
* request id or cache-busting param per attempt — grouping on the exact
|
|
21
|
+
* path would make every retry look like a distinct, one-off call and never
|
|
22
|
+
* cross the threshold.
|
|
23
|
+
*/
|
|
24
|
+
export function detectRetryStorm(calls, threshold) {
|
|
25
|
+
if (threshold <= 0)
|
|
26
|
+
return [];
|
|
27
|
+
const groups = new Map();
|
|
28
|
+
for (const call of calls) {
|
|
29
|
+
const pathname = call.path.split('?')[0] ?? call.path;
|
|
30
|
+
const key = `${call.host} ${call.method} ${pathname}`;
|
|
31
|
+
let g = groups.get(key);
|
|
32
|
+
if (!g) {
|
|
33
|
+
g = { host: call.host, method: call.method, path: pathname, count: 0, failureCount: 0 };
|
|
34
|
+
groups.set(key, g);
|
|
35
|
+
}
|
|
36
|
+
g.count++;
|
|
37
|
+
if (isFailingCall(call))
|
|
38
|
+
g.failureCount++;
|
|
39
|
+
}
|
|
40
|
+
return [...groups.values()]
|
|
41
|
+
.filter((g) => g.count >= threshold && g.failureCount > 0)
|
|
42
|
+
.sort((a, b) => b.count - a.count);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A stable, digit-free description — same fingerprinting reasoning as
|
|
46
|
+
* describeNPlusOne: the exact count varies request to request, and must not
|
|
47
|
+
* appear in the message or two occurrences of the same underlying storm
|
|
48
|
+
* would never fingerprint into the same issue.
|
|
49
|
+
*/
|
|
50
|
+
export function describeRetryStorm(finding) {
|
|
51
|
+
return `Repeated failing calls to ${finding.method} ${finding.host}${finding.path} — possible retry storm without backoff`;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A real Error subclass, not a plain Error with `.name` reassigned — same
|
|
55
|
+
* reasoning as PotentialNPlusOneQuery: capture() derives the payload's
|
|
56
|
+
* error.type (which becomes the issue title verbatim) from
|
|
57
|
+
* err.constructor.name, which for a plain Error is always "Error" no matter
|
|
58
|
+
* what `.name` gets set to afterward.
|
|
59
|
+
*/
|
|
60
|
+
export class PotentialRetryStorm extends Error {
|
|
61
|
+
constructor(finding) {
|
|
62
|
+
super(describeRetryStorm(finding));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=retryStorm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retryStorm.js","sourceRoot":"","sources":["../src/retryStorm.ts"],"names":[],"mappings":"AAWA,2EAA2E;AAC3E,uEAAuE;AACvE,6EAA6E;AAC7E,sEAAsE;AACtE,wCAAwC;AACxC,SAAS,aAAa,CAAC,IAAkB;IACvC,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC;AACjD,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAqB,EAAE,SAAiB;IACvE,IAAI,SAAS,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IAE9B,MAAM,MAAM,GAAG,IAAI,GAAG,EAA6B,CAAC;IACpD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC;QACtD,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC;QACtD,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,CAAC,CAAC,EAAE,CAAC;YACP,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;YACxF,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,CAAC;QACD,CAAC,CAAC,KAAK,EAAE,CAAC;QACV,IAAI,aAAa,CAAC,IAAI,CAAC;YAAE,CAAC,CAAC,YAAY,EAAE,CAAC;IAC5C,CAAC;IAED,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;SACxB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,SAAS,IAAI,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC;SACzD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AACvC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAA0B;IAC3D,OAAO,6BAA6B,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,yCAAyC,CAAC;AAC7H,CAAC;AAED;;;;;;GAMG;AACH,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,OAA0B;QACpC,KAAK,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;IACrC,CAAC;CACF"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { InvariantRule } from './invariantRules.js';
|
|
2
|
+
interface RulesPollerOptions {
|
|
3
|
+
endpoint: string;
|
|
4
|
+
apiKey: string;
|
|
5
|
+
intervalMs?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare class RulesPoller {
|
|
8
|
+
private rules;
|
|
9
|
+
private timer;
|
|
10
|
+
private lastWarnAt;
|
|
11
|
+
private readonly endpoint;
|
|
12
|
+
private readonly apiKey;
|
|
13
|
+
private readonly intervalMs;
|
|
14
|
+
constructor(opts: RulesPollerOptions);
|
|
15
|
+
start(): void;
|
|
16
|
+
stop(): void;
|
|
17
|
+
getEnabledRules(): InvariantRule[];
|
|
18
|
+
refresh(): Promise<void>;
|
|
19
|
+
seed(body: {
|
|
20
|
+
rules?: InvariantRule[];
|
|
21
|
+
}): void;
|
|
22
|
+
private applyResponse;
|
|
23
|
+
private warnOnce;
|
|
24
|
+
}
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=rulesPoller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rulesPoller.d.ts","sourceRoot":"","sources":["../src/rulesPoller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGzD,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AASD,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAExB,IAAI,EAAE,kBAAkB;IAMpC,KAAK,IAAI,IAAI;IAMb,IAAI,IAAI,IAAI;IAWZ,eAAe,IAAI,aAAa,EAAE;IAI5B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB9B,IAAI,CAAC,IAAI,EAAE;QAAE,KAAK,CAAC,EAAE,aAAa,EAAE,CAAA;KAAE,GAAG,IAAI;IAI7C,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,QAAQ;CAOjB"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { httpFetch } from './httpFetch.js';
|
|
2
|
+
const WARN_INTERVAL_MS = 60_000;
|
|
3
|
+
// Periodically fetches the tenant's business-invariant rules from the
|
|
4
|
+
// control plane and caches the enabled subset in memory — the mechanism
|
|
5
|
+
// that lets a dashboard-authored rule take effect in a running process
|
|
6
|
+
// without a recompile/redeploy. Same start()/stop()/setInterval+unref shape
|
|
7
|
+
// as BatchTransport (transport.ts), the SDK's other background timer.
|
|
8
|
+
export class RulesPoller {
|
|
9
|
+
rules = [];
|
|
10
|
+
timer = null;
|
|
11
|
+
lastWarnAt = 0;
|
|
12
|
+
endpoint;
|
|
13
|
+
apiKey;
|
|
14
|
+
intervalMs;
|
|
15
|
+
constructor(opts) {
|
|
16
|
+
this.endpoint = opts.endpoint;
|
|
17
|
+
this.apiKey = opts.apiKey;
|
|
18
|
+
this.intervalMs = opts.intervalMs ?? 60_000;
|
|
19
|
+
}
|
|
20
|
+
start() {
|
|
21
|
+
void this.refresh(); // don't wait a full interval before rules are usable
|
|
22
|
+
this.timer = setInterval(() => void this.refresh(), this.intervalMs);
|
|
23
|
+
if (this.timer.unref)
|
|
24
|
+
this.timer.unref(); // don't block process exit
|
|
25
|
+
}
|
|
26
|
+
stop() {
|
|
27
|
+
if (this.timer) {
|
|
28
|
+
clearInterval(this.timer);
|
|
29
|
+
this.timer = null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// The rules currently cached, already filtered to enabled — the control
|
|
33
|
+
// plane returns every rule (dashboard needs to see disabled ones to
|
|
34
|
+
// manage them), so the filtering happens once here rather than on every
|
|
35
|
+
// query in the Prisma extension.
|
|
36
|
+
getEnabledRules() {
|
|
37
|
+
return this.rules;
|
|
38
|
+
}
|
|
39
|
+
async refresh() {
|
|
40
|
+
try {
|
|
41
|
+
const res = await httpFetch(this.endpoint, {
|
|
42
|
+
headers: { 'X-Reprova-Key': this.apiKey },
|
|
43
|
+
});
|
|
44
|
+
if (!res.ok) {
|
|
45
|
+
this.warnOnce(`reprova: rules fetch returned ${res.status}`);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const body = (await res.json());
|
|
49
|
+
this.applyResponse(body);
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
this.warnOnce(`reprova: rules fetch error: ${err.message}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Applies an already-fetched response body directly, with no network call
|
|
56
|
+
// — used by replay mode to seed a one-time snapshot the CLI fetched ahead
|
|
57
|
+
// of time (there's no live control plane to poll from inside a replayed
|
|
58
|
+
// app), so detection logic (invariantRules.ts) sees exactly the same
|
|
59
|
+
// shape it would from a real refresh().
|
|
60
|
+
seed(body) {
|
|
61
|
+
this.applyResponse(body);
|
|
62
|
+
}
|
|
63
|
+
applyResponse(body) {
|
|
64
|
+
this.rules = (body.rules ?? []).filter((r) => r.enabled);
|
|
65
|
+
}
|
|
66
|
+
warnOnce(msg) {
|
|
67
|
+
const now = Date.now();
|
|
68
|
+
if (now - this.lastWarnAt > WARN_INTERVAL_MS) {
|
|
69
|
+
this.lastWarnAt = now;
|
|
70
|
+
console.warn(msg);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=rulesPoller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rulesPoller.js","sourceRoot":"","sources":["../src/rulesPoller.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAQ3C,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEhC,sEAAsE;AACtE,wEAAwE;AACxE,uEAAuE;AACvE,4EAA4E;AAC5E,sEAAsE;AACtE,MAAM,OAAO,WAAW;IACd,KAAK,GAAoB,EAAE,CAAC;IAC5B,KAAK,GAA0C,IAAI,CAAC;IACpD,UAAU,GAAG,CAAC,CAAC;IACN,QAAQ,CAAS;IACjB,MAAM,CAAS;IACf,UAAU,CAAS;IAEpC,YAAY,IAAwB;QAClC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC;IAC9C,CAAC;IAED,KAAK;QACH,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,qDAAqD;QAC1E,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACrE,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK;YAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,2BAA2B;IACvE,CAAC;IAED,IAAI;QACF,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;IACH,CAAC;IAED,wEAAwE;IACxE,oEAAoE;IACpE,wEAAwE;IACxE,iCAAiC;IACjC,eAAe;QACb,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,OAAO;QACX,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE;gBACzC,OAAO,EAAE,EAAE,eAAe,EAAE,IAAI,CAAC,MAAM,EAAE;aAC1C,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,IAAI,CAAC,QAAQ,CAAC,iCAAiC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;gBAC7D,OAAO;YACT,CAAC;YACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAgC,CAAC;YAC/D,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,QAAQ,CAAC,+BAAgC,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IAED,0EAA0E;IAC1E,0EAA0E;IAC1E,wEAAwE;IACxE,qEAAqE;IACrE,wCAAwC;IACxC,IAAI,CAAC,IAAiC;QACpC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAEO,aAAa,CAAC,IAAiC;QACrD,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAC3D,CAAC;IAEO,QAAQ,CAAC,GAAW;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,GAAG,GAAG,IAAI,CAAC,UAAU,GAAG,gBAAgB,EAAE,CAAC;YAC7C,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC;YACtB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;CACF"}
|
package/dist/sdk.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import type { Response, RequestHandler, ErrorRequestHandler } from 'express';
|
|
2
|
+
export interface ExpressAppLike {
|
|
3
|
+
use(...args: unknown[]): unknown;
|
|
4
|
+
}
|
|
5
|
+
import type { ReprovaContext, FootprintQuery } from './context.js';
|
|
6
|
+
import type { ReprovaNestFilter, ReprovaNestInterceptor, NestAppLike } from './nest.js';
|
|
7
|
+
import type { InvariantRule } from './invariantRules.js';
|
|
8
|
+
import type { FrameworkAdapter } from './frameworkAdapter.js';
|
|
9
|
+
import type { MongooseInstanceLike } from './mongoose.js';
|
|
4
10
|
export interface ReprovaOptions {
|
|
5
11
|
dsn?: string;
|
|
6
12
|
release: string;
|
|
@@ -11,42 +17,77 @@ export interface ReprovaOptions {
|
|
|
11
17
|
};
|
|
12
18
|
instrumentHttp?: boolean;
|
|
13
19
|
processHandlers?: boolean;
|
|
20
|
+
n1Threshold?: number;
|
|
21
|
+
retryStormThreshold?: number;
|
|
22
|
+
rulesRefreshIntervalMs?: number;
|
|
14
23
|
}
|
|
15
24
|
export declare function forwardAsyncErrors(app: object): void;
|
|
16
25
|
export declare function replayErrorHandler(): ErrorRequestHandler;
|
|
17
26
|
export declare class Reprova {
|
|
18
27
|
private readonly opts;
|
|
19
28
|
private readonly transport;
|
|
29
|
+
private readonly rulesPoller;
|
|
30
|
+
private readonly idempotencySettingsPoller;
|
|
31
|
+
private readonly inferenceReporter;
|
|
32
|
+
private readonly distributionDriftReporter;
|
|
33
|
+
private readonly distributionBaselinePoller;
|
|
34
|
+
private readonly writeCountDriftReporter;
|
|
35
|
+
private readonly writeCountBaselinePoller;
|
|
36
|
+
private mongoSchemaReporter?;
|
|
37
|
+
private readonly instrumentedMongooseInstances;
|
|
38
|
+
private readonly idempotencyKeyCache;
|
|
39
|
+
private readonly duplicateReadCache;
|
|
20
40
|
readonly release: string;
|
|
21
|
-
readonly sdkVersion = "0.
|
|
41
|
+
readonly sdkVersion = "0.6.0";
|
|
22
42
|
readonly disabled: boolean;
|
|
43
|
+
readonly replayMode: boolean;
|
|
23
44
|
private migrationId;
|
|
45
|
+
private authClaimsExtractor?;
|
|
24
46
|
private readonly outboundOpts;
|
|
47
|
+
private readonly n1Threshold;
|
|
48
|
+
private readonly retryStormThreshold;
|
|
25
49
|
constructor(opts: ReprovaOptions);
|
|
50
|
+
getInvariantRules(): InvariantRule[];
|
|
26
51
|
static init(opts: ReprovaOptions): Reprova;
|
|
27
52
|
static getInstance(): Reprova | null;
|
|
28
53
|
setMigrationId(id: string): void;
|
|
54
|
+
registerFrameworkAdapter(adapter: FrameworkAdapter): void;
|
|
29
55
|
instrumentPrisma(client: unknown, opts?: {
|
|
30
56
|
dmmf?: unknown;
|
|
31
57
|
readMigrationId?: boolean;
|
|
32
58
|
}): Promise<void>;
|
|
33
|
-
|
|
59
|
+
instrumentMongoose(mongooseInstance: MongooseInstanceLike): void;
|
|
60
|
+
registerReferenceEdges(edges: {
|
|
61
|
+
fromCollection: string;
|
|
62
|
+
fromField: string;
|
|
63
|
+
toCollection: string;
|
|
64
|
+
array: boolean;
|
|
65
|
+
}[]): void;
|
|
66
|
+
setupExpress(app: ExpressAppLike): void;
|
|
34
67
|
requestHandler(): RequestHandler;
|
|
35
68
|
errorHandler(): ErrorRequestHandler;
|
|
36
69
|
captureError(err: Error, opts?: {
|
|
37
70
|
trigger?: string;
|
|
38
71
|
}): void;
|
|
39
72
|
nestExceptionFilter(): ReprovaNestFilter;
|
|
73
|
+
nestContextInterceptor(): ReprovaNestInterceptor;
|
|
40
74
|
setupNest(app: NestAppLike, opts?: {
|
|
41
75
|
prisma?: unknown;
|
|
42
76
|
dmmf?: unknown;
|
|
43
77
|
}): Promise<void>;
|
|
44
78
|
captureHttp5xx(err: Error | null, statusCode: number, responseBody: string): void;
|
|
79
|
+
captureNPlusOneIfAny(): void;
|
|
80
|
+
captureRetryStormIfAny(): void;
|
|
81
|
+
captureBusinessInvariantViolationsIfAny(): void;
|
|
82
|
+
captureWriteCountDriftIfAny(): void;
|
|
83
|
+
checkIdempotencyIfAny(body: unknown): void;
|
|
84
|
+
checkDistributionDriftIfAny(body: unknown): void;
|
|
45
85
|
capture(trigger: string, err: Error, ctx: ReprovaContext | undefined, extra?: {
|
|
46
86
|
response?: {
|
|
47
87
|
status: number;
|
|
48
88
|
body: string;
|
|
49
89
|
};
|
|
90
|
+
errorType?: string;
|
|
50
91
|
}): void;
|
|
51
92
|
attachProcessHandlers(): void;
|
|
52
93
|
runWithContext<T>(info: {
|
|
@@ -58,9 +99,9 @@ export declare class Reprova {
|
|
|
58
99
|
}, fn: () => T | Promise<T>): Promise<T>;
|
|
59
100
|
runJob<T>(name: string, fn: () => T | Promise<T>): Promise<T>;
|
|
60
101
|
private runInContext;
|
|
61
|
-
recordFootprint(query: FootprintQuery): void;
|
|
102
|
+
recordFootprint(query: FootprintQuery, rawRequest?: unknown): void;
|
|
62
103
|
private patchOutbound;
|
|
63
|
-
|
|
104
|
+
private disposeInternal;
|
|
64
105
|
}
|
|
65
106
|
export declare function wrapResponse(res: Response, sdk: Reprova): void;
|
|
66
107
|
//# sourceMappingURL=sdk.d.ts.map
|
package/dist/sdk.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"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"}
|