@lensmcp/core 1.25.0 → 1.25.2
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/lib/flow-shape.d.ts +2 -2
- package/lib/pg-errors.d.ts +21 -0
- package/lib/pg-errors.js +1 -0
- package/lib/resource-store.d.ts +17 -0
- package/lib/resource-store.js +1 -1
- package/package.json +7 -2
package/lib/flow-shape.d.ts
CHANGED
|
@@ -70,7 +70,7 @@ export declare function trimFlowEvent(event: BaseEvent, opts?: FlowShapeOptions)
|
|
|
70
70
|
outcome?: "returned" | "threw" | undefined;
|
|
71
71
|
source: "nx" | "vite" | "typescript" | "eslint" | "rollup" | "client-runtime" | "chrome" | "react" | "valtio" | "nestjs" | "nextjs" | "db" | "redis" | "queue" | "memory" | "visual" | "perf" | "security" | "gateway" | "external" | "ai" | "lens";
|
|
72
72
|
category: "db" | "memory" | "visual" | "security" | "ai" | "build" | "lint" | "typecheck" | "test" | "runtime" | "render" | "trace" | "state" | "network" | "backend" | "performance" | "deps" | "cluster" | "agent";
|
|
73
|
-
severity: "
|
|
73
|
+
severity: "error" | "debug" | "info" | "warning" | "fatal";
|
|
74
74
|
title: string;
|
|
75
75
|
kind: string | undefined;
|
|
76
76
|
area: FlowArea;
|
|
@@ -139,7 +139,7 @@ export declare function buildFlowDetail(rawEvents: BaseEvent[], opts?: FlowShape
|
|
|
139
139
|
outcome?: "returned" | "threw" | undefined;
|
|
140
140
|
source: "nx" | "vite" | "typescript" | "eslint" | "rollup" | "client-runtime" | "chrome" | "react" | "valtio" | "nestjs" | "nextjs" | "db" | "redis" | "queue" | "memory" | "visual" | "perf" | "security" | "gateway" | "external" | "ai" | "lens";
|
|
141
141
|
category: "db" | "memory" | "visual" | "security" | "ai" | "build" | "lint" | "typecheck" | "test" | "runtime" | "render" | "trace" | "state" | "network" | "backend" | "performance" | "deps" | "cluster" | "agent";
|
|
142
|
-
severity: "
|
|
142
|
+
severity: "error" | "debug" | "info" | "warning" | "fatal";
|
|
143
143
|
title: string;
|
|
144
144
|
kind: string | undefined;
|
|
145
145
|
area: FlowArea;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a node-postgres connection error means — read from its code and message, the same way in the pool tap (an error
|
|
3
|
+
* it sees) and in the lens (an error a service only logged).
|
|
4
|
+
*
|
|
5
|
+
* The four that read alike and are not alike:
|
|
6
|
+
*
|
|
7
|
+
* pool-wait-timeout `timeout exceeded when trying to connect` — pg-pool's QUEUE wait: every connection of the
|
|
8
|
+
* service's OWN pool was taken (or still opening) for `connectionTimeoutMillis`. Postgres may
|
|
9
|
+
* have hundreds free. Also what a frozen process reads as: the wait's timer fires on wake,
|
|
10
|
+
* before the replies already waiting in the sockets are read.
|
|
11
|
+
* connect-timeout `Connection terminated due to connection timeout` — opening a NEW connection took longer than
|
|
12
|
+
* the limit (the server, the network, or this process's blocked loop).
|
|
13
|
+
* server-full SQLSTATE 53300 — Postgres itself is at `max_connections`.
|
|
14
|
+
* server-unreachable nothing answers at the address.
|
|
15
|
+
*/
|
|
16
|
+
export type PgConnectReason = 'pool-wait-timeout' | 'connect-timeout' | 'server-full' | 'server-unreachable' | 'pool-ended' | 'auth-failed';
|
|
17
|
+
export declare const PG_CONNECT_MEANING: Record<PgConnectReason, string>;
|
|
18
|
+
/** Any of the texts above, for finding them in a line a service logged. */
|
|
19
|
+
export declare const PG_CONNECT_TEXT: RegExp;
|
|
20
|
+
/** The reason a connect failed, or undefined when the error is not about getting a connection. */
|
|
21
|
+
export declare function pgConnectReason(err: unknown): PgConnectReason | undefined;
|
package/lib/pg-errors.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var d=Object.defineProperty;var n=(o,e)=>d(o,"name",{value:e,configurable:!0});var u=Object.defineProperty,l=n((o,e)=>u(o,"name",{value:e,configurable:!0}),"t");export const PG_CONNECT_MEANING={"pool-wait-timeout":"waited for a free connection in the service\u2019s own pool and the wait ran out \u2014 not Postgres refusing","connect-timeout":"opening a new connection to Postgres took longer than the limit","server-full":"Postgres is at its max_connections and refused a new connection","server-unreachable":"nothing answered at the database\u2019s address","pool-ended":"the code used a pool that had already been closed (an app being shut down)","auth-failed":"Postgres refused the user or password"};const a=[["pool-wait-timeout",/timeout exceeded when trying to connect/i],["connect-timeout",/Connection terminated due to connection timeout/i],["server-full",/sorry, too many clients already|remaining connection slots are reserved|too many connections for role/i],["pool-ended",/Cannot use a pool after calling end on the pool/i],["auth-failed",/password authentication failed|no pg_hba\.conf entry/i],["server-unreachable",/connect (ECONNREFUSED|EHOSTUNREACH|ETIMEDOUT)|getaddrinfo ENOTFOUND/i]],r={53300:"server-full","28P01":"auth-failed",28e3:"auth-failed",ECONNREFUSED:"server-unreachable",EHOSTUNREACH:"server-unreachable",ENOTFOUND:"server-unreachable"};export const PG_CONNECT_TEXT=new RegExp(a.map(([,o])=>o.source).join("|"),"i");export function pgConnectReason(o){const e=o,t=typeof e=="object"&&e&&typeof e.code=="string"?e.code:void 0;if(t&&r[t])return r[t];const s=typeof e=="string"?e:typeof e=="object"&&e&&typeof e.message=="string"?e.message:"";for(const[i,c]of a)if(c.test(s))return i}n(pgConnectReason,"pgConnectReason"),l(pgConnectReason,"pgConnectReason");
|
package/lib/resource-store.d.ts
CHANGED
|
@@ -8,6 +8,17 @@ import type { Unsubscribe } from './common.js';
|
|
|
8
8
|
export type ResourceValue = unknown;
|
|
9
9
|
export type ResourceProducer = () => ResourceValue | Promise<ResourceValue>;
|
|
10
10
|
export type ResourceUpdatedHandler = (uri: string, revision: number) => void;
|
|
11
|
+
export interface ResourceStoreOptions {
|
|
12
|
+
/**
|
|
13
|
+
* Recompute a resource at most once per this many milliseconds, however often it is marked dirty (0, the default:
|
|
14
|
+
* on every call). A lens session sets it: a reducer marks its resource dirty on EVERY event it folds, and finding out
|
|
15
|
+
* whether the resource changed means producing it whole and serialising it — `flow://recent` summarises every flow.
|
|
16
|
+
* At FoodGuard's 450 events a second that was most of the dashboard's CPU, and the backlog it left was ingested in
|
|
17
|
+
* one synchronous tick that held the event loop for up to 51 s (the dashboard's "Connection to the lens lost").
|
|
18
|
+
* Reads are never delayed: `read` produces the resource fresh. Only the revision and the notification wait.
|
|
19
|
+
*/
|
|
20
|
+
coalesceMs?: number;
|
|
21
|
+
}
|
|
11
22
|
/**
|
|
12
23
|
* The resource store. URIs are registered once; reading is cheap; the
|
|
13
24
|
* `markDirty` call bumps the revision counter and notifies subscribers
|
|
@@ -16,6 +27,11 @@ export type ResourceUpdatedHandler = (uri: string, revision: number) => void;
|
|
|
16
27
|
export declare class ResourceStore {
|
|
17
28
|
private readonly entries;
|
|
18
29
|
private readonly subs;
|
|
30
|
+
private readonly coalesceMs;
|
|
31
|
+
/** A recompute already scheduled per URI — every mark until it runs rides on it. */
|
|
32
|
+
private readonly queued;
|
|
33
|
+
private readonly lastRun;
|
|
34
|
+
constructor(opts?: ResourceStoreOptions);
|
|
19
35
|
register(uri: string, produce: ResourceProducer): Unsubscribe;
|
|
20
36
|
read(uri: string): Promise<ResourceValue>;
|
|
21
37
|
list(): string[];
|
|
@@ -25,6 +41,7 @@ export declare class ResourceStore {
|
|
|
25
41
|
* change.
|
|
26
42
|
*/
|
|
27
43
|
markDirty(uri: string): Promise<void>;
|
|
44
|
+
private recompute;
|
|
28
45
|
revision(uri: string): number | undefined;
|
|
29
46
|
subscribe(uri: string, handler: ResourceUpdatedHandler): Unsubscribe;
|
|
30
47
|
}
|
package/lib/resource-store.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var c=Object.defineProperty;var u=(n,e)=>c(n,"name",{value:e,configurable:!0});var h=Object.defineProperty,a=u((n,e)=>h(n,"name",{value:e,configurable:!0}),"o");export class ResourceStore{static{u(this,"ResourceStore")}static{a(this,"ResourceStore")}constructor(e={}){this.entries=new Map,this.subs=new Map,this.queued=new Map,this.lastRun=new Map,this.coalesceMs=Math.max(0,e.coalesceMs??0)}register(e,t){if(this.entries.has(e))throw new Error(`Resource already registered: ${e}`);return this.entries.set(e,{uri:e,produce:t,revision:0}),()=>{this.entries.delete(e),this.subs.delete(e),this.lastRun.delete(e)}}async read(e){const t=this.entries.get(e);if(!t)throw new Error(`Unknown resource: ${e}`);return t.produce()}list(){return[...this.entries.keys()]}markDirty(e){if(this.coalesceMs===0)return this.recompute(e);if(!this.entries.has(e))return Promise.resolve();const t=this.queued.get(e);if(t)return t;const s=Math.max(0,(this.lastRun.get(e)??Number.NEGATIVE_INFINITY)+this.coalesceMs-Date.now()),r=new Promise(i=>{const o=a(()=>{this.queued.delete(e),this.lastRun.set(e,Date.now()),this.recompute(e).then(i,()=>i())},"go");s===0?setImmediate(o):setTimeout(o,s).unref?.()});return this.queued.set(e,r),r}async recompute(e){const t=this.entries.get(e);if(!t)return;const s=await t.produce(),r=JSON.stringify(s);if(r===t.lastJson)return;t.lastJson=r,t.revision+=1;const i=this.subs.get(e);if(i)for(const o of i)try{o(e,t.revision)}catch{}}revision(e){return this.entries.get(e)?.revision}subscribe(e,t){let s=this.subs.get(e);return s||(s=new Set,this.subs.set(e,s)),s.add(t),()=>{s?.delete(t)}}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lensmcp/core",
|
|
3
|
-
"version": "1.25.
|
|
3
|
+
"version": "1.25.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -22,6 +22,11 @@
|
|
|
22
22
|
"import": "./lib/sql-shape.js",
|
|
23
23
|
"default": "./lib/sql-shape.js"
|
|
24
24
|
},
|
|
25
|
+
"./pg-errors": {
|
|
26
|
+
"types": "./lib/pg-errors.d.ts",
|
|
27
|
+
"import": "./lib/pg-errors.js",
|
|
28
|
+
"default": "./lib/pg-errors.js"
|
|
29
|
+
},
|
|
25
30
|
"./stores": {
|
|
26
31
|
"types": "./lib/stores.d.ts",
|
|
27
32
|
"import": "./lib/stores.js",
|
|
@@ -59,7 +64,7 @@
|
|
|
59
64
|
}
|
|
60
65
|
},
|
|
61
66
|
"dependencies": {
|
|
62
|
-
"@lensmcp/protocol-types": "1.25.
|
|
67
|
+
"@lensmcp/protocol-types": "1.25.2",
|
|
63
68
|
"tslib": "^2.3.0"
|
|
64
69
|
},
|
|
65
70
|
"license": "Apache-2.0",
|