@mastra/pg 1.30.0-alpha.0 → 1.30.0-alpha.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/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/index.cjs +170 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +170 -3
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/observability/v-next/index.d.ts +3 -2
- package/dist/storage/domains/observability/v-next/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/span-query.d.ts +43 -0
- package/dist/storage/domains/observability/v-next/span-query.d.ts.map +1 -0
- package/dist/storage/domains/observability/v-next/trace-query.d.ts +7 -1
- package/dist/storage/domains/observability/v-next/trace-query.d.ts.map +1 -1
- package/dist/storage/domains/schedules/index.d.ts +2 -2
- package/dist/storage/domains/schedules/index.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/docs/SKILL.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -18280,6 +18280,166 @@ async function queryThreads(client, schema, plan, timeoutMs) {
|
|
|
18280
18280
|
}) : null }
|
|
18281
18281
|
});
|
|
18282
18282
|
}
|
|
18283
|
+
/** Compile a span-row filter with exactly the same rules as trace span predicates. */
|
|
18284
|
+
function compileSpanQueryPredicate(predicate, offset) {
|
|
18285
|
+
return compileScalarPredicate(predicate, SPAN_FIELDS, offset);
|
|
18286
|
+
}
|
|
18287
|
+
//#endregion
|
|
18288
|
+
//#region src/storage/domains/observability/v-next/span-query.ts
|
|
18289
|
+
const identityFields = [
|
|
18290
|
+
"organizationId",
|
|
18291
|
+
"resourceId",
|
|
18292
|
+
"traceId",
|
|
18293
|
+
"spanId"
|
|
18294
|
+
];
|
|
18295
|
+
const fields = [
|
|
18296
|
+
...identityFields,
|
|
18297
|
+
"parentSpanId",
|
|
18298
|
+
"name",
|
|
18299
|
+
"spanType",
|
|
18300
|
+
"entityType",
|
|
18301
|
+
"entityId",
|
|
18302
|
+
"entityName",
|
|
18303
|
+
"entityVersionId",
|
|
18304
|
+
"parentEntityVersionId",
|
|
18305
|
+
"rootEntityVersionId",
|
|
18306
|
+
"runId",
|
|
18307
|
+
"sessionId",
|
|
18308
|
+
"userId"
|
|
18309
|
+
];
|
|
18310
|
+
const identities = identityFields.map((field) => `"${field}"`).join(", ");
|
|
18311
|
+
const identityOrder = identityFields.map((field) => `"${field}" COLLATE "C" ASC NULLS LAST`).join(", ");
|
|
18312
|
+
function selectedKeys(rows, values) {
|
|
18313
|
+
return rows.map((row) => `(${identityFields.map((field) => {
|
|
18314
|
+
values.push(row[field]);
|
|
18315
|
+
return `"${field}" ${field === "traceId" || field === "spanId" ? "=" : "IS NOT DISTINCT FROM"} $${values.length}::text`;
|
|
18316
|
+
}).join(" AND ")})`).join(" OR ");
|
|
18317
|
+
}
|
|
18318
|
+
function afterCursor(plan, values) {
|
|
18319
|
+
if (!plan.cursor) return "TRUE";
|
|
18320
|
+
const cursor = plan.cursor;
|
|
18321
|
+
values.push(cursor.sortValue);
|
|
18322
|
+
const timestamp = `$${values.length}::timestamptz`;
|
|
18323
|
+
const field = `s."${plan.orderBy.field}"`;
|
|
18324
|
+
const terms = [`${field} ${plan.orderBy.direction === "asc" ? ">" : "<"} ${timestamp}`];
|
|
18325
|
+
const equal = [`${field} = ${timestamp}`];
|
|
18326
|
+
for (const key of identityFields) {
|
|
18327
|
+
const ref = `s."${key}" COLLATE "C"`;
|
|
18328
|
+
const value = cursor[key];
|
|
18329
|
+
if (value === null) equal.push(`${ref} IS NULL`);
|
|
18330
|
+
else {
|
|
18331
|
+
values.push(value);
|
|
18332
|
+
const parameter = `$${values.length}::text COLLATE "C"`;
|
|
18333
|
+
terms.push(`(${equal.join(" AND ")} AND (${ref} > ${parameter} OR ${ref} IS NULL))`);
|
|
18334
|
+
equal.push(`${ref} = ${parameter}`);
|
|
18335
|
+
}
|
|
18336
|
+
}
|
|
18337
|
+
return `(${terms.join(" OR ")})`;
|
|
18338
|
+
}
|
|
18339
|
+
function compilePostgresSpanQuery(schema, plan) {
|
|
18340
|
+
const values = [plan.timeRange.from, plan.timeRange.to];
|
|
18341
|
+
const scope = [];
|
|
18342
|
+
if (plan.scope) {
|
|
18343
|
+
values.push(plan.scope.organizationId);
|
|
18344
|
+
scope.push(`"organizationId" = $${values.length}`);
|
|
18345
|
+
if (plan.scope.resourceId !== void 0) {
|
|
18346
|
+
values.push(plan.scope.resourceId);
|
|
18347
|
+
scope.push(`"resourceId" = $${values.length}`);
|
|
18348
|
+
}
|
|
18349
|
+
}
|
|
18350
|
+
const predicate = plan.where ? compileSpanQueryPredicate(plan.where, values.length + 1) : {
|
|
18351
|
+
sql: "TRUE",
|
|
18352
|
+
values: []
|
|
18353
|
+
};
|
|
18354
|
+
values.push(...predicate.values);
|
|
18355
|
+
const after = afterCursor(plan, values);
|
|
18356
|
+
values.push(plan.limit + 1);
|
|
18357
|
+
const table = qualifiedTable(schema, TABLE_SPAN_EVENTS);
|
|
18358
|
+
return {
|
|
18359
|
+
text: `WITH candidate_ids AS MATERIALIZED (
|
|
18360
|
+
SELECT DISTINCT ${identities} FROM ${table}
|
|
18361
|
+
WHERE "startedAt" >= $1 AND "startedAt" < $2 AND "endedAt" >= $1 AND NOT "isPending"
|
|
18362
|
+
${scope.length ? `AND ${scope.join(" AND ")}` : ""}
|
|
18363
|
+
), current_spans AS MATERIALIZED (
|
|
18364
|
+
SELECT DISTINCT ON (${identities})
|
|
18365
|
+
${fields.map((field) => `"${field}"`).join(", ")}, "startedAt", "endedAt", "cursorId"::text AS version,
|
|
18366
|
+
CASE WHEN jsonb_typeof(attributes -> 'model') = 'string' THEN attributes ->> 'model' END AS model,
|
|
18367
|
+
CASE WHEN jsonb_typeof(attributes -> 'provider') = 'string' THEN attributes ->> 'provider' END AS provider,
|
|
18368
|
+
(EXTRACT(EPOCH FROM ("endedAt" - "startedAt")) * 1000)::float8 AS "durationMs",
|
|
18369
|
+
CASE WHEN error IS NULL THEN 'success' ELSE 'error' END AS status,
|
|
18370
|
+
error IS NOT NULL AS "hasError"
|
|
18371
|
+
FROM ${table} e
|
|
18372
|
+
WHERE NOT "isPending" AND "endedAt" >= $1 AND (
|
|
18373
|
+
"organizationId" IS NULL, COALESCE("organizationId", ''), "resourceId" IS NULL, COALESCE("resourceId", ''), "traceId", "spanId"
|
|
18374
|
+
) IN (
|
|
18375
|
+
SELECT "organizationId" IS NULL, COALESCE("organizationId", ''), "resourceId" IS NULL, COALESCE("resourceId", ''), "traceId", "spanId" FROM candidate_ids
|
|
18376
|
+
) ${scope.length ? `AND ${scope.join(" AND ")}` : ""}
|
|
18377
|
+
ORDER BY ${identities}, "endedAt" DESC, "cursorId" DESC
|
|
18378
|
+
), candidates AS (
|
|
18379
|
+
SELECT *, CASE WHEN "hasError" THEN 'error' ELSE NULL END AS error FROM current_spans
|
|
18380
|
+
)
|
|
18381
|
+
SELECT ${[
|
|
18382
|
+
...identityFields,
|
|
18383
|
+
"parentSpanId",
|
|
18384
|
+
"name",
|
|
18385
|
+
"spanType",
|
|
18386
|
+
"entityType",
|
|
18387
|
+
"entityId",
|
|
18388
|
+
"entityName",
|
|
18389
|
+
"model",
|
|
18390
|
+
"provider",
|
|
18391
|
+
"startedAt",
|
|
18392
|
+
"endedAt",
|
|
18393
|
+
"durationMs",
|
|
18394
|
+
"status",
|
|
18395
|
+
"version"
|
|
18396
|
+
].map((field) => `s."${field}"`).join(", ")}
|
|
18397
|
+
FROM candidates s WHERE s."startedAt" >= $1 AND s."startedAt" < $2 AND (${predicate.sql}) AND ${after}
|
|
18398
|
+
ORDER BY s."${plan.orderBy.field}" ${plan.orderBy.direction === "asc" ? "ASC" : "DESC"}, ${identityOrder}
|
|
18399
|
+
LIMIT $${values.length}`,
|
|
18400
|
+
values
|
|
18401
|
+
};
|
|
18402
|
+
}
|
|
18403
|
+
async function querySpans(client, schema, plan, timeoutMs) {
|
|
18404
|
+
const deadline = performance.now() + _mastra_core_storage.resolveTraceQueryTimeoutMs(timeoutMs);
|
|
18405
|
+
return runWithPostgresTraceQueryTimeout(client, timeoutMs, async (tx) => {
|
|
18406
|
+
const query = compilePostgresSpanQuery(schema, plan);
|
|
18407
|
+
const rows = await tx.any(query.text, query.values);
|
|
18408
|
+
const selected = rows.map(({ version: _version, startedAt, endedAt, ...row }) => ({
|
|
18409
|
+
...row,
|
|
18410
|
+
startedAt: startedAt.toISOString(),
|
|
18411
|
+
endedAt: endedAt.toISOString()
|
|
18412
|
+
}));
|
|
18413
|
+
const page = rows.slice(0, plan.limit);
|
|
18414
|
+
if (!page.length) return _mastra_core_storage.buildSpanQueryResponse(plan, selected, [], []);
|
|
18415
|
+
const remaining = async () => {
|
|
18416
|
+
const ms = Math.floor(deadline - performance.now());
|
|
18417
|
+
if (ms <= 0) throw new _mastra_core_storage.TraceQueryExecutionError();
|
|
18418
|
+
await tx.query(`SELECT set_config('statement_timeout', $1, true)`, [`${ms}ms`]);
|
|
18419
|
+
};
|
|
18420
|
+
await remaining();
|
|
18421
|
+
const payloadValues = [];
|
|
18422
|
+
const payloadWhere = page.map((row) => {
|
|
18423
|
+
const key = selectedKeys([row], payloadValues);
|
|
18424
|
+
payloadValues.push(row.version);
|
|
18425
|
+
return `(${key} AND "cursorId" = $${payloadValues.length}::bigint)`;
|
|
18426
|
+
}).join(" OR ");
|
|
18427
|
+
const payloads = await tx.any(`SELECT ${identities},
|
|
18428
|
+
left(input::text, ${_mastra_core_storage.SPAN_QUERY_MAX_PREVIEW_CHARACTERS + 1}) AS "inputPreview", left(output::text, ${_mastra_core_storage.SPAN_QUERY_MAX_PREVIEW_CHARACTERS + 1}) AS "outputPreview"
|
|
18429
|
+
FROM ${qualifiedTable(schema, TABLE_SPAN_EVENTS)} WHERE ${payloadWhere}`, payloadValues);
|
|
18430
|
+
await remaining();
|
|
18431
|
+
const metricValues = [];
|
|
18432
|
+
const metricWhere = selectedKeys(page, metricValues);
|
|
18433
|
+
const metrics = await tx.any(`SELECT ${identities}, name, "estimatedCost", "costUnit",
|
|
18434
|
+
"costMetadata" ->> 'allocation' AS allocation, COALESCE("costMetadata" ? 'error', false) AS "costError"
|
|
18435
|
+
FROM (SELECT DISTINCT ON (${identities}, "metricId") ${identities}, name, "estimatedCost", "costUnit", "costMetadata" FROM ${qualifiedTable(schema, TABLE_METRIC_EVENTS)}
|
|
18436
|
+
WHERE (${metricWhere}) AND name LIKE 'mastra_model_%'
|
|
18437
|
+
ORDER BY ${identities}, "metricId", "cursorId" DESC) m
|
|
18438
|
+
LIMIT ${_mastra_core_storage.SPAN_QUERY_MAX_COST_METRICS + 1}`, metricValues);
|
|
18439
|
+
if (metrics.length > _mastra_core_storage.SPAN_QUERY_MAX_COST_METRICS) throw new _mastra_core_storage.TraceQueryResourceLimitError();
|
|
18440
|
+
return _mastra_core_storage.buildSpanQueryResponse(plan, selected, payloads, metrics);
|
|
18441
|
+
}, { repeatableRead: true });
|
|
18442
|
+
}
|
|
18283
18443
|
//#endregion
|
|
18284
18444
|
//#region src/storage/domains/observability/v-next/trace-aggregate.ts
|
|
18285
18445
|
/** Trace-root column expressions (alias `r`) for each groupable dimension; same values `where` sees. */
|
|
@@ -19175,6 +19335,7 @@ async function dangerouslyClearTracing(client, schema) {
|
|
|
19175
19335
|
* application database — observability writes will degrade app performance.
|
|
19176
19336
|
* Use it through `MastraCompositeStore` with a dedicated Postgres connection.
|
|
19177
19337
|
*/
|
|
19338
|
+
const spanQueryFeatures = typeof _mastra_core_storage.planSpanQuery === "function" ? ["span-query"] : [];
|
|
19178
19339
|
function wrapError(op, error, details) {
|
|
19179
19340
|
if (error instanceof _mastra_core_error.MastraError || error instanceof _mastra_core_storage.TraceQueryCursorError || error instanceof _mastra_core_storage.TraceQueryExecutionError || error instanceof _mastra_core_storage.TraceQueryResourceLimitError) throw error;
|
|
19180
19341
|
throw new _mastra_core_error.MastraError({
|
|
@@ -19364,6 +19525,7 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
19364
19525
|
"metric-discovery",
|
|
19365
19526
|
"trace-query",
|
|
19366
19527
|
"trace-aggregate",
|
|
19528
|
+
...spanQueryFeatures,
|
|
19367
19529
|
"trace-query-root-duration",
|
|
19368
19530
|
"trace-query-discovery",
|
|
19369
19531
|
"thread-query",
|
|
@@ -19383,6 +19545,7 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
19383
19545
|
"delta-polling",
|
|
19384
19546
|
"trace-query",
|
|
19385
19547
|
"trace-aggregate",
|
|
19548
|
+
...spanQueryFeatures,
|
|
19386
19549
|
"trace-query-root-duration",
|
|
19387
19550
|
"trace-query-discovery",
|
|
19388
19551
|
"thread-query",
|
|
@@ -19431,6 +19594,9 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
19431
19594
|
async listTraces(args) {
|
|
19432
19595
|
return this.#run("LIST_TRACES", () => listTraces(this.#readClient, this.#schema, args));
|
|
19433
19596
|
}
|
|
19597
|
+
async querySpans(plan) {
|
|
19598
|
+
return this.#run("QUERY_SPANS", () => querySpans(this.#readClient, this.#schema, plan, this.#traceQueryTimeoutMs));
|
|
19599
|
+
}
|
|
19434
19600
|
async queryTraces(plan) {
|
|
19435
19601
|
return this.#run("QUERY_TRACES", () => queryTraces(this.#readClient, this.#schema, plan, this.#traceQueryTimeoutMs));
|
|
19436
19602
|
}
|
|
@@ -20448,9 +20614,9 @@ var SchedulesPG = class SchedulesPG extends _mastra_core_storage.SchedulesStorag
|
|
|
20448
20614
|
if (!updated) throw new Error(`Schedule ${id} not found`);
|
|
20449
20615
|
return updated;
|
|
20450
20616
|
}
|
|
20451
|
-
async updateScheduleNextFire(id, expectedNextFireAt, newNextFireAt, lastFireAt, lastRunId) {
|
|
20617
|
+
async updateScheduleNextFire(id, expectedNextFireAt, newNextFireAt, lastFireAt, lastRunId, newStatus) {
|
|
20452
20618
|
return ((await this.#client.query(`UPDATE ${this.#table(_mastra_core_storage.TABLE_SCHEDULES)}
|
|
20453
|
-
SET next_fire_at = $1, last_fire_at = $2, last_run_id = $3, updated_at = $4
|
|
20619
|
+
SET next_fire_at = $1, last_fire_at = $2, last_run_id = $3, updated_at = $4, status = COALESCE($8, status)
|
|
20454
20620
|
WHERE id = $5 AND next_fire_at = $6 AND status = $7`, [
|
|
20455
20621
|
newNextFireAt,
|
|
20456
20622
|
lastFireAt,
|
|
@@ -20458,7 +20624,8 @@ var SchedulesPG = class SchedulesPG extends _mastra_core_storage.SchedulesStorag
|
|
|
20458
20624
|
Date.now(),
|
|
20459
20625
|
id,
|
|
20460
20626
|
expectedNextFireAt,
|
|
20461
|
-
"active"
|
|
20627
|
+
"active",
|
|
20628
|
+
newStatus ?? null
|
|
20462
20629
|
])).rowCount ?? 0) > 0;
|
|
20463
20630
|
}
|
|
20464
20631
|
async deleteSchedule(id) {
|