@mastra/mssql 0.0.0-fix-11329-windows-path-20251222155941 → 0.0.0-fix-local-pkg-cwd-20251224015404
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 +348 -3
- package/dist/index.cjs +705 -414
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +706 -415
- package/dist/index.js.map +1 -1
- package/dist/storage/db/index.d.ts +36 -23
- package/dist/storage/db/index.d.ts.map +1 -1
- package/dist/storage/db/utils.d.ts +1 -5
- package/dist/storage/db/utils.d.ts.map +1 -1
- package/dist/storage/domains/memory/index.d.ts +18 -1
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/index.d.ts +26 -23
- package/dist/storage/domains/observability/index.d.ts.map +1 -1
- package/dist/storage/domains/scores/index.d.ts +23 -18
- package/dist/storage/domains/scores/index.d.ts.map +1 -1
- package/dist/storage/domains/utils.d.ts +2 -2
- package/dist/storage/domains/utils.d.ts.map +1 -1
- package/dist/storage/domains/workflows/index.d.ts +19 -1
- package/dist/storage/domains/workflows/index.d.ts.map +1 -1
- package/dist/storage/index.d.ts +55 -176
- package/dist/storage/index.d.ts.map +1 -1
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
var error = require('@mastra/core/error');
|
|
4
4
|
var storage = require('@mastra/core/storage');
|
|
5
5
|
var sql = require('mssql');
|
|
6
|
+
var agent = require('@mastra/core/agent');
|
|
6
7
|
var base = require('@mastra/core/base');
|
|
7
8
|
var utils = require('@mastra/core/utils');
|
|
8
|
-
var agent = require('@mastra/core/agent');
|
|
9
9
|
var crypto = require('crypto');
|
|
10
10
|
var evals = require('@mastra/core/evals');
|
|
11
11
|
|
|
@@ -26,31 +26,89 @@ function getTableName({ indexName, schemaName }) {
|
|
|
26
26
|
|
|
27
27
|
// src/storage/db/index.ts
|
|
28
28
|
function resolveMssqlConfig(config) {
|
|
29
|
-
if ("pool" in config && "
|
|
30
|
-
return {
|
|
29
|
+
if ("pool" in config && !("server" in config)) {
|
|
30
|
+
return {
|
|
31
|
+
pool: config.pool,
|
|
32
|
+
schemaName: config.schemaName,
|
|
33
|
+
skipDefaultIndexes: config.skipDefaultIndexes,
|
|
34
|
+
indexes: config.indexes,
|
|
35
|
+
needsConnect: false
|
|
36
|
+
};
|
|
31
37
|
}
|
|
38
|
+
const restConfig = config;
|
|
32
39
|
const pool = new sql__default.default.ConnectionPool({
|
|
33
|
-
server:
|
|
34
|
-
database:
|
|
35
|
-
user:
|
|
36
|
-
password:
|
|
37
|
-
port:
|
|
38
|
-
options:
|
|
40
|
+
server: restConfig.server,
|
|
41
|
+
database: restConfig.database,
|
|
42
|
+
user: restConfig.user,
|
|
43
|
+
password: restConfig.password,
|
|
44
|
+
port: restConfig.port,
|
|
45
|
+
options: restConfig.options || { encrypt: true, trustServerCertificate: true }
|
|
39
46
|
});
|
|
40
|
-
|
|
41
|
-
|
|
47
|
+
return {
|
|
48
|
+
pool,
|
|
49
|
+
schemaName: restConfig.schemaName,
|
|
50
|
+
skipDefaultIndexes: restConfig.skipDefaultIndexes,
|
|
51
|
+
indexes: restConfig.indexes,
|
|
52
|
+
needsConnect: true
|
|
53
|
+
};
|
|
42
54
|
}
|
|
43
55
|
var MssqlDB = class extends base.MastraBase {
|
|
44
56
|
pool;
|
|
45
57
|
schemaName;
|
|
58
|
+
skipDefaultIndexes;
|
|
46
59
|
setupSchemaPromise = null;
|
|
47
60
|
schemaSetupComplete = void 0;
|
|
48
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Columns that participate in composite indexes need smaller sizes (NVARCHAR(100)).
|
|
63
|
+
* MSSQL has a 900-byte index key limit, so composite indexes with NVARCHAR(400) columns fail.
|
|
64
|
+
* These are typically ID/type fields that don't need 400 chars.
|
|
65
|
+
*/
|
|
66
|
+
COMPOSITE_INDEX_COLUMNS = [
|
|
67
|
+
"traceId",
|
|
68
|
+
// Used in: PRIMARY KEY (traceId, spanId), index (traceId, spanId, seq_id)
|
|
69
|
+
"spanId",
|
|
70
|
+
// Used in: PRIMARY KEY (traceId, spanId), index (traceId, spanId, seq_id)
|
|
71
|
+
"parentSpanId",
|
|
72
|
+
// Used in: index (parentSpanId, startedAt)
|
|
73
|
+
"entityType",
|
|
74
|
+
// Used in: (entityType, entityId), (entityType, entityName)
|
|
75
|
+
"entityId",
|
|
76
|
+
// Used in: (entityType, entityId)
|
|
77
|
+
"entityName",
|
|
78
|
+
// Used in: (entityType, entityName)
|
|
79
|
+
"organizationId",
|
|
80
|
+
// Used in: (organizationId, userId)
|
|
81
|
+
"userId"
|
|
82
|
+
// Used in: (organizationId, userId)
|
|
83
|
+
];
|
|
84
|
+
/**
|
|
85
|
+
* Columns that store large amounts of data and should use NVARCHAR(MAX).
|
|
86
|
+
* Avoid listing columns that participate in indexes (resourceId, thread_id, agent_name, name, etc.)
|
|
87
|
+
*/
|
|
88
|
+
LARGE_DATA_COLUMNS = [
|
|
89
|
+
"workingMemory",
|
|
90
|
+
"snapshot",
|
|
91
|
+
"metadata",
|
|
92
|
+
"content",
|
|
93
|
+
// messages.content - can be very long conversation content
|
|
94
|
+
"input",
|
|
95
|
+
// evals.input - test input data
|
|
96
|
+
"output",
|
|
97
|
+
// evals.output - test output data
|
|
98
|
+
"instructions",
|
|
99
|
+
// evals.instructions - evaluation instructions
|
|
100
|
+
"other"
|
|
101
|
+
// traces.other - additional trace data
|
|
102
|
+
];
|
|
103
|
+
getSqlType(type, isPrimaryKey = false, useLargeStorage = false, useSmallStorage = false) {
|
|
49
104
|
switch (type) {
|
|
50
105
|
case "text":
|
|
51
106
|
if (useLargeStorage) {
|
|
52
107
|
return "NVARCHAR(MAX)";
|
|
53
108
|
}
|
|
109
|
+
if (useSmallStorage) {
|
|
110
|
+
return "NVARCHAR(100)";
|
|
111
|
+
}
|
|
54
112
|
return isPrimaryKey ? "NVARCHAR(255)" : "NVARCHAR(400)";
|
|
55
113
|
case "timestamp":
|
|
56
114
|
return "DATETIME2(7)";
|
|
@@ -74,10 +132,15 @@ var MssqlDB = class extends base.MastraBase {
|
|
|
74
132
|
});
|
|
75
133
|
}
|
|
76
134
|
}
|
|
77
|
-
constructor({
|
|
135
|
+
constructor({
|
|
136
|
+
pool,
|
|
137
|
+
schemaName,
|
|
138
|
+
skipDefaultIndexes
|
|
139
|
+
}) {
|
|
78
140
|
super({ component: "STORAGE", name: "MssqlDB" });
|
|
79
141
|
this.pool = pool;
|
|
80
142
|
this.schemaName = schemaName;
|
|
143
|
+
this.skipDefaultIndexes = skipDefaultIndexes;
|
|
81
144
|
}
|
|
82
145
|
async hasColumn(table, column) {
|
|
83
146
|
const schema = this.schemaName || "dbo";
|
|
@@ -209,29 +272,15 @@ var MssqlDB = class extends base.MastraBase {
|
|
|
209
272
|
}) {
|
|
210
273
|
try {
|
|
211
274
|
const uniqueConstraintColumns = tableName === storage.TABLE_WORKFLOW_SNAPSHOT ? ["workflow_name", "run_id"] : [];
|
|
212
|
-
const largeDataColumns = [
|
|
213
|
-
"workingMemory",
|
|
214
|
-
"snapshot",
|
|
215
|
-
"metadata",
|
|
216
|
-
"content",
|
|
217
|
-
// messages.content - can be very long conversation content
|
|
218
|
-
"input",
|
|
219
|
-
// evals.input - test input data
|
|
220
|
-
"output",
|
|
221
|
-
// evals.output - test output data
|
|
222
|
-
"instructions",
|
|
223
|
-
// evals.instructions - evaluation instructions
|
|
224
|
-
"other"
|
|
225
|
-
// traces.other - additional trace data
|
|
226
|
-
];
|
|
227
275
|
const columns = Object.entries(schema).map(([name, def]) => {
|
|
228
276
|
const parsedName = utils.parseSqlIdentifier(name, "column name");
|
|
229
277
|
const constraints = [];
|
|
230
278
|
if (def.primaryKey) constraints.push("PRIMARY KEY");
|
|
231
279
|
if (!def.nullable) constraints.push("NOT NULL");
|
|
232
280
|
const isIndexed = !!def.primaryKey || uniqueConstraintColumns.includes(name);
|
|
233
|
-
const useLargeStorage =
|
|
234
|
-
|
|
281
|
+
const useLargeStorage = this.LARGE_DATA_COLUMNS.includes(name);
|
|
282
|
+
const useSmallStorage = this.COMPOSITE_INDEX_COLUMNS.includes(name);
|
|
283
|
+
return `[${parsedName}] ${this.getSqlType(def.type, isIndexed, useLargeStorage, useSmallStorage)} ${constraints.join(" ")}`.trim();
|
|
235
284
|
}).join(",\n");
|
|
236
285
|
if (this.schemaName) {
|
|
237
286
|
await this.setupSchema();
|
|
@@ -268,18 +317,37 @@ ${columns}
|
|
|
268
317
|
const alterSql = `ALTER TABLE ${getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) })} ADD seq_id BIGINT IDENTITY(1,1)`;
|
|
269
318
|
await this.pool.request().query(alterSql);
|
|
270
319
|
}
|
|
320
|
+
const schemaPrefix = this.schemaName ? `${this.schemaName}_` : "";
|
|
271
321
|
if (tableName === storage.TABLE_WORKFLOW_SNAPSHOT) {
|
|
272
|
-
const constraintName =
|
|
322
|
+
const constraintName = `${schemaPrefix}mastra_workflow_snapshot_workflow_name_run_id_key`;
|
|
273
323
|
const checkConstraintSql = `SELECT 1 AS found FROM sys.key_constraints WHERE name = @constraintName`;
|
|
274
324
|
const checkConstraintRequest = this.pool.request();
|
|
275
325
|
checkConstraintRequest.input("constraintName", constraintName);
|
|
276
326
|
const constraintResult = await checkConstraintRequest.query(checkConstraintSql);
|
|
277
327
|
const constraintExists = Array.isArray(constraintResult.recordset) && constraintResult.recordset.length > 0;
|
|
278
328
|
if (!constraintExists) {
|
|
279
|
-
const addConstraintSql = `ALTER TABLE ${getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) })} ADD CONSTRAINT ${constraintName} UNIQUE ([workflow_name], [run_id])`;
|
|
329
|
+
const addConstraintSql = `ALTER TABLE ${getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) })} ADD CONSTRAINT [${constraintName}] UNIQUE ([workflow_name], [run_id])`;
|
|
280
330
|
await this.pool.request().query(addConstraintSql);
|
|
281
331
|
}
|
|
282
332
|
}
|
|
333
|
+
if (tableName === storage.TABLE_SPANS) {
|
|
334
|
+
await this.migrateSpansTable();
|
|
335
|
+
const pkConstraintName = `${schemaPrefix}mastra_ai_spans_traceid_spanid_pk`;
|
|
336
|
+
const checkPkRequest = this.pool.request();
|
|
337
|
+
checkPkRequest.input("constraintName", pkConstraintName);
|
|
338
|
+
const pkResult = await checkPkRequest.query(
|
|
339
|
+
`SELECT 1 AS found FROM sys.key_constraints WHERE name = @constraintName`
|
|
340
|
+
);
|
|
341
|
+
const pkExists = Array.isArray(pkResult.recordset) && pkResult.recordset.length > 0;
|
|
342
|
+
if (!pkExists) {
|
|
343
|
+
try {
|
|
344
|
+
const addPkSql = `ALTER TABLE ${getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) })} ADD CONSTRAINT [${pkConstraintName}] PRIMARY KEY ([traceId], [spanId])`;
|
|
345
|
+
await this.pool.request().query(addPkSql);
|
|
346
|
+
} catch (pkError) {
|
|
347
|
+
this.logger?.warn?.(`Failed to add composite primary key to spans table:`, pkError);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
283
351
|
} catch (error$1) {
|
|
284
352
|
throw new error.MastraError(
|
|
285
353
|
{
|
|
@@ -294,6 +362,34 @@ ${columns}
|
|
|
294
362
|
);
|
|
295
363
|
}
|
|
296
364
|
}
|
|
365
|
+
/**
|
|
366
|
+
* Migrates the spans table schema from OLD_SPAN_SCHEMA to current SPAN_SCHEMA.
|
|
367
|
+
* This adds new columns that don't exist in old schema.
|
|
368
|
+
*/
|
|
369
|
+
async migrateSpansTable() {
|
|
370
|
+
const fullTableName = getTableName({ indexName: storage.TABLE_SPANS, schemaName: getSchemaName(this.schemaName) });
|
|
371
|
+
const schema = storage.TABLE_SCHEMAS[storage.TABLE_SPANS];
|
|
372
|
+
try {
|
|
373
|
+
for (const [columnName, columnDef] of Object.entries(schema)) {
|
|
374
|
+
const columnExists = await this.hasColumn(storage.TABLE_SPANS, columnName);
|
|
375
|
+
if (!columnExists) {
|
|
376
|
+
const parsedColumnName = utils.parseSqlIdentifier(columnName, "column name");
|
|
377
|
+
const useLargeStorage = this.LARGE_DATA_COLUMNS.includes(columnName);
|
|
378
|
+
const useSmallStorage = this.COMPOSITE_INDEX_COLUMNS.includes(columnName);
|
|
379
|
+
const isIndexed = !!columnDef.primaryKey;
|
|
380
|
+
const sqlType = this.getSqlType(columnDef.type, isIndexed, useLargeStorage, useSmallStorage);
|
|
381
|
+
const nullable = columnDef.nullable ? "" : "NOT NULL";
|
|
382
|
+
const defaultValue = !columnDef.nullable ? this.getDefaultValue(columnDef.type) : "";
|
|
383
|
+
const alterSql = `ALTER TABLE ${fullTableName} ADD [${parsedColumnName}] ${sqlType} ${nullable} ${defaultValue}`.trim();
|
|
384
|
+
await this.pool.request().query(alterSql);
|
|
385
|
+
this.logger?.debug?.(`Added column '${columnName}' to ${fullTableName}`);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
this.logger?.info?.(`Migration completed for ${fullTableName}`);
|
|
389
|
+
} catch (error) {
|
|
390
|
+
this.logger?.warn?.(`Failed to migrate spans table ${fullTableName}:`, error);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
297
393
|
/**
|
|
298
394
|
* Alters table schema to add columns if they don't exist
|
|
299
395
|
* @param tableName Name of the table
|
|
@@ -318,21 +414,12 @@ ${columns}
|
|
|
318
414
|
const columnExists = Array.isArray(checkResult.recordset) && checkResult.recordset.length > 0;
|
|
319
415
|
if (!columnExists) {
|
|
320
416
|
const columnDef = schema[columnName];
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
"snapshot",
|
|
324
|
-
"metadata",
|
|
325
|
-
"content",
|
|
326
|
-
"input",
|
|
327
|
-
"output",
|
|
328
|
-
"instructions",
|
|
329
|
-
"other"
|
|
330
|
-
];
|
|
331
|
-
const useLargeStorage = largeDataColumns.includes(columnName);
|
|
417
|
+
const useLargeStorage = this.LARGE_DATA_COLUMNS.includes(columnName);
|
|
418
|
+
const useSmallStorage = this.COMPOSITE_INDEX_COLUMNS.includes(columnName);
|
|
332
419
|
const isIndexed = !!columnDef.primaryKey;
|
|
333
|
-
const sqlType = this.getSqlType(columnDef.type, isIndexed, useLargeStorage);
|
|
334
|
-
const nullable = columnDef.nullable
|
|
335
|
-
const defaultValue = columnDef.nullable
|
|
420
|
+
const sqlType = this.getSqlType(columnDef.type, isIndexed, useLargeStorage, useSmallStorage);
|
|
421
|
+
const nullable = columnDef.nullable ? "" : "NOT NULL";
|
|
422
|
+
const defaultValue = !columnDef.nullable ? this.getDefaultValue(columnDef.type) : "";
|
|
336
423
|
const parsedColumnName = utils.parseSqlIdentifier(columnName, "column name");
|
|
337
424
|
const alterSql = `ALTER TABLE ${fullTableName} ADD [${parsedColumnName}] ${sqlType} ${nullable} ${defaultValue}`.trim();
|
|
338
425
|
await this.pool.request().query(alterSql);
|
|
@@ -916,84 +1003,6 @@ ${columns}
|
|
|
916
1003
|
);
|
|
917
1004
|
}
|
|
918
1005
|
}
|
|
919
|
-
/**
|
|
920
|
-
* Returns definitions for automatic performance indexes
|
|
921
|
-
* IMPORTANT: Uses seq_id DESC instead of createdAt DESC for MSSQL due to millisecond accuracy limitations
|
|
922
|
-
* NOTE: Using NVARCHAR(400) for text columns (800 bytes) leaves room for composite indexes
|
|
923
|
-
*/
|
|
924
|
-
getAutomaticIndexDefinitions() {
|
|
925
|
-
const schemaPrefix = this.schemaName ? `${this.schemaName}_` : "";
|
|
926
|
-
return [
|
|
927
|
-
// Composite indexes for optimal filtering + sorting performance
|
|
928
|
-
// NVARCHAR(400) = 800 bytes, plus BIGINT (8 bytes) = 808 bytes total (under 900-byte limit)
|
|
929
|
-
{
|
|
930
|
-
name: `${schemaPrefix}mastra_threads_resourceid_seqid_idx`,
|
|
931
|
-
table: storage.TABLE_THREADS,
|
|
932
|
-
columns: ["resourceId", "seq_id DESC"]
|
|
933
|
-
},
|
|
934
|
-
{
|
|
935
|
-
name: `${schemaPrefix}mastra_messages_thread_id_seqid_idx`,
|
|
936
|
-
table: storage.TABLE_MESSAGES,
|
|
937
|
-
columns: ["thread_id", "seq_id DESC"]
|
|
938
|
-
},
|
|
939
|
-
{
|
|
940
|
-
name: `${schemaPrefix}mastra_traces_name_seqid_idx`,
|
|
941
|
-
table: storage.TABLE_TRACES,
|
|
942
|
-
columns: ["name", "seq_id DESC"]
|
|
943
|
-
},
|
|
944
|
-
{
|
|
945
|
-
name: `${schemaPrefix}mastra_scores_trace_id_span_id_seqid_idx`,
|
|
946
|
-
table: storage.TABLE_SCORERS,
|
|
947
|
-
columns: ["traceId", "spanId", "seq_id DESC"]
|
|
948
|
-
},
|
|
949
|
-
// Spans indexes for optimal trace querying
|
|
950
|
-
{
|
|
951
|
-
name: `${schemaPrefix}mastra_ai_spans_traceid_startedat_idx`,
|
|
952
|
-
table: storage.TABLE_SPANS,
|
|
953
|
-
columns: ["traceId", "startedAt DESC"]
|
|
954
|
-
},
|
|
955
|
-
{
|
|
956
|
-
name: `${schemaPrefix}mastra_ai_spans_parentspanid_startedat_idx`,
|
|
957
|
-
table: storage.TABLE_SPANS,
|
|
958
|
-
columns: ["parentSpanId", "startedAt DESC"]
|
|
959
|
-
},
|
|
960
|
-
{
|
|
961
|
-
name: `${schemaPrefix}mastra_ai_spans_name_idx`,
|
|
962
|
-
table: storage.TABLE_SPANS,
|
|
963
|
-
columns: ["name"]
|
|
964
|
-
},
|
|
965
|
-
{
|
|
966
|
-
name: `${schemaPrefix}mastra_ai_spans_spantype_startedat_idx`,
|
|
967
|
-
table: storage.TABLE_SPANS,
|
|
968
|
-
columns: ["spanType", "startedAt DESC"]
|
|
969
|
-
}
|
|
970
|
-
];
|
|
971
|
-
}
|
|
972
|
-
/**
|
|
973
|
-
* Creates automatic indexes for optimal query performance
|
|
974
|
-
* Uses getAutomaticIndexDefinitions() to determine which indexes to create
|
|
975
|
-
*/
|
|
976
|
-
async createAutomaticIndexes() {
|
|
977
|
-
try {
|
|
978
|
-
const indexes = this.getAutomaticIndexDefinitions();
|
|
979
|
-
for (const indexOptions of indexes) {
|
|
980
|
-
try {
|
|
981
|
-
await this.createIndex(indexOptions);
|
|
982
|
-
} catch (error) {
|
|
983
|
-
this.logger?.warn?.(`Failed to create index ${indexOptions.name}:`, error);
|
|
984
|
-
}
|
|
985
|
-
}
|
|
986
|
-
} catch (error$1) {
|
|
987
|
-
throw new error.MastraError(
|
|
988
|
-
{
|
|
989
|
-
id: storage.createStorageErrorId("MSSQL", "CREATE_PERFORMANCE_INDEXES", "FAILED"),
|
|
990
|
-
domain: error.ErrorDomain.STORAGE,
|
|
991
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
992
|
-
},
|
|
993
|
-
error$1
|
|
994
|
-
);
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
1006
|
};
|
|
998
1007
|
function getSchemaName2(schema) {
|
|
999
1008
|
return schema ? `[${utils.parseSqlIdentifier(schema, "schema name")}]` : void 0;
|
|
@@ -1107,11 +1116,15 @@ function transformFromSqlRow({
|
|
|
1107
1116
|
}
|
|
1108
1117
|
|
|
1109
1118
|
// src/storage/domains/memory/index.ts
|
|
1110
|
-
var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
1119
|
+
var MemoryMSSQL = class _MemoryMSSQL extends storage.MemoryStorage {
|
|
1111
1120
|
pool;
|
|
1112
1121
|
schema;
|
|
1113
1122
|
db;
|
|
1114
1123
|
needsConnect;
|
|
1124
|
+
skipDefaultIndexes;
|
|
1125
|
+
indexes;
|
|
1126
|
+
/** Tables managed by this domain */
|
|
1127
|
+
static MANAGED_TABLES = [storage.TABLE_THREADS, storage.TABLE_MESSAGES, storage.TABLE_RESOURCES];
|
|
1115
1128
|
_parseAndFormatMessages(messages, format) {
|
|
1116
1129
|
const messagesWithParsedContent = messages.map((message) => {
|
|
1117
1130
|
if (typeof message.content === "string") {
|
|
@@ -1129,11 +1142,13 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
1129
1142
|
}
|
|
1130
1143
|
constructor(config) {
|
|
1131
1144
|
super();
|
|
1132
|
-
const { pool,
|
|
1145
|
+
const { pool, schemaName, skipDefaultIndexes, indexes, needsConnect } = resolveMssqlConfig(config);
|
|
1133
1146
|
this.pool = pool;
|
|
1134
|
-
this.schema =
|
|
1135
|
-
this.db =
|
|
1147
|
+
this.schema = schemaName;
|
|
1148
|
+
this.db = new MssqlDB({ pool, schemaName, skipDefaultIndexes });
|
|
1136
1149
|
this.needsConnect = needsConnect;
|
|
1150
|
+
this.skipDefaultIndexes = skipDefaultIndexes;
|
|
1151
|
+
this.indexes = indexes?.filter((idx) => _MemoryMSSQL.MANAGED_TABLES.includes(idx.table));
|
|
1137
1152
|
}
|
|
1138
1153
|
async init() {
|
|
1139
1154
|
if (this.needsConnect) {
|
|
@@ -1143,6 +1158,57 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
1143
1158
|
await this.db.createTable({ tableName: storage.TABLE_THREADS, schema: storage.TABLE_SCHEMAS[storage.TABLE_THREADS] });
|
|
1144
1159
|
await this.db.createTable({ tableName: storage.TABLE_MESSAGES, schema: storage.TABLE_SCHEMAS[storage.TABLE_MESSAGES] });
|
|
1145
1160
|
await this.db.createTable({ tableName: storage.TABLE_RESOURCES, schema: storage.TABLE_SCHEMAS[storage.TABLE_RESOURCES] });
|
|
1161
|
+
await this.createDefaultIndexes();
|
|
1162
|
+
await this.createCustomIndexes();
|
|
1163
|
+
}
|
|
1164
|
+
/**
|
|
1165
|
+
* Returns default index definitions for the memory domain tables.
|
|
1166
|
+
* IMPORTANT: Uses seq_id DESC instead of createdAt DESC for MSSQL due to millisecond accuracy limitations
|
|
1167
|
+
*/
|
|
1168
|
+
getDefaultIndexDefinitions() {
|
|
1169
|
+
const schemaPrefix = this.schema ? `${this.schema}_` : "";
|
|
1170
|
+
return [
|
|
1171
|
+
{
|
|
1172
|
+
name: `${schemaPrefix}mastra_threads_resourceid_seqid_idx`,
|
|
1173
|
+
table: storage.TABLE_THREADS,
|
|
1174
|
+
columns: ["resourceId", "seq_id DESC"]
|
|
1175
|
+
},
|
|
1176
|
+
{
|
|
1177
|
+
name: `${schemaPrefix}mastra_messages_thread_id_seqid_idx`,
|
|
1178
|
+
table: storage.TABLE_MESSAGES,
|
|
1179
|
+
columns: ["thread_id", "seq_id DESC"]
|
|
1180
|
+
}
|
|
1181
|
+
];
|
|
1182
|
+
}
|
|
1183
|
+
/**
|
|
1184
|
+
* Creates default indexes for optimal query performance.
|
|
1185
|
+
*/
|
|
1186
|
+
async createDefaultIndexes() {
|
|
1187
|
+
if (this.skipDefaultIndexes) {
|
|
1188
|
+
return;
|
|
1189
|
+
}
|
|
1190
|
+
for (const indexDef of this.getDefaultIndexDefinitions()) {
|
|
1191
|
+
try {
|
|
1192
|
+
await this.db.createIndex(indexDef);
|
|
1193
|
+
} catch (error) {
|
|
1194
|
+
this.logger?.warn?.(`Failed to create index ${indexDef.name}:`, error);
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
/**
|
|
1199
|
+
* Creates custom user-defined indexes for this domain's tables.
|
|
1200
|
+
*/
|
|
1201
|
+
async createCustomIndexes() {
|
|
1202
|
+
if (!this.indexes || this.indexes.length === 0) {
|
|
1203
|
+
return;
|
|
1204
|
+
}
|
|
1205
|
+
for (const indexDef of this.indexes) {
|
|
1206
|
+
try {
|
|
1207
|
+
await this.db.createIndex(indexDef);
|
|
1208
|
+
} catch (error) {
|
|
1209
|
+
this.logger?.warn?.(`Failed to create custom index ${indexDef.name}:`, error);
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1146
1212
|
}
|
|
1147
1213
|
async dangerouslyClearAll() {
|
|
1148
1214
|
await this.db.clearTable({ tableName: storage.TABLE_MESSAGES });
|
|
@@ -2021,18 +2087,24 @@ var MemoryMSSQL = class extends storage.MemoryStorage {
|
|
|
2021
2087
|
}
|
|
2022
2088
|
}
|
|
2023
2089
|
};
|
|
2024
|
-
var ObservabilityMSSQL = class extends storage.ObservabilityStorage {
|
|
2090
|
+
var ObservabilityMSSQL = class _ObservabilityMSSQL extends storage.ObservabilityStorage {
|
|
2025
2091
|
pool;
|
|
2026
2092
|
db;
|
|
2027
2093
|
schema;
|
|
2028
2094
|
needsConnect;
|
|
2095
|
+
skipDefaultIndexes;
|
|
2096
|
+
indexes;
|
|
2097
|
+
/** Tables managed by this domain */
|
|
2098
|
+
static MANAGED_TABLES = [storage.TABLE_SPANS];
|
|
2029
2099
|
constructor(config) {
|
|
2030
2100
|
super();
|
|
2031
|
-
const { pool,
|
|
2101
|
+
const { pool, schemaName, skipDefaultIndexes, indexes, needsConnect } = resolveMssqlConfig(config);
|
|
2032
2102
|
this.pool = pool;
|
|
2033
|
-
this.
|
|
2034
|
-
this.
|
|
2103
|
+
this.schema = schemaName;
|
|
2104
|
+
this.db = new MssqlDB({ pool, schemaName, skipDefaultIndexes });
|
|
2035
2105
|
this.needsConnect = needsConnect;
|
|
2106
|
+
this.skipDefaultIndexes = skipDefaultIndexes;
|
|
2107
|
+
this.indexes = indexes?.filter((idx) => _ObservabilityMSSQL.MANAGED_TABLES.includes(idx.table));
|
|
2036
2108
|
}
|
|
2037
2109
|
async init() {
|
|
2038
2110
|
if (this.needsConnect) {
|
|
@@ -2040,6 +2112,92 @@ var ObservabilityMSSQL = class extends storage.ObservabilityStorage {
|
|
|
2040
2112
|
this.needsConnect = false;
|
|
2041
2113
|
}
|
|
2042
2114
|
await this.db.createTable({ tableName: storage.TABLE_SPANS, schema: storage.SPAN_SCHEMA });
|
|
2115
|
+
await this.createDefaultIndexes();
|
|
2116
|
+
await this.createCustomIndexes();
|
|
2117
|
+
}
|
|
2118
|
+
/**
|
|
2119
|
+
* Returns default index definitions for the observability domain tables.
|
|
2120
|
+
*/
|
|
2121
|
+
getDefaultIndexDefinitions() {
|
|
2122
|
+
const schemaPrefix = this.schema ? `${this.schema}_` : "";
|
|
2123
|
+
return [
|
|
2124
|
+
{
|
|
2125
|
+
name: `${schemaPrefix}mastra_ai_spans_traceid_startedat_idx`,
|
|
2126
|
+
table: storage.TABLE_SPANS,
|
|
2127
|
+
columns: ["traceId", "startedAt DESC"]
|
|
2128
|
+
},
|
|
2129
|
+
{
|
|
2130
|
+
name: `${schemaPrefix}mastra_ai_spans_parentspanid_startedat_idx`,
|
|
2131
|
+
table: storage.TABLE_SPANS,
|
|
2132
|
+
columns: ["parentSpanId", "startedAt DESC"]
|
|
2133
|
+
},
|
|
2134
|
+
{
|
|
2135
|
+
name: `${schemaPrefix}mastra_ai_spans_name_idx`,
|
|
2136
|
+
table: storage.TABLE_SPANS,
|
|
2137
|
+
columns: ["name"]
|
|
2138
|
+
},
|
|
2139
|
+
{
|
|
2140
|
+
name: `${schemaPrefix}mastra_ai_spans_spantype_startedat_idx`,
|
|
2141
|
+
table: storage.TABLE_SPANS,
|
|
2142
|
+
columns: ["spanType", "startedAt DESC"]
|
|
2143
|
+
},
|
|
2144
|
+
// Root spans filtered index - every listTraces query filters parentSpanId IS NULL
|
|
2145
|
+
{
|
|
2146
|
+
name: `${schemaPrefix}mastra_ai_spans_root_spans_idx`,
|
|
2147
|
+
table: storage.TABLE_SPANS,
|
|
2148
|
+
columns: ["startedAt DESC"],
|
|
2149
|
+
where: "[parentSpanId] IS NULL"
|
|
2150
|
+
},
|
|
2151
|
+
// Entity identification indexes - common filtering patterns
|
|
2152
|
+
{
|
|
2153
|
+
name: `${schemaPrefix}mastra_ai_spans_entitytype_entityid_idx`,
|
|
2154
|
+
table: storage.TABLE_SPANS,
|
|
2155
|
+
columns: ["entityType", "entityId"]
|
|
2156
|
+
},
|
|
2157
|
+
{
|
|
2158
|
+
name: `${schemaPrefix}mastra_ai_spans_entitytype_entityname_idx`,
|
|
2159
|
+
table: storage.TABLE_SPANS,
|
|
2160
|
+
columns: ["entityType", "entityName"]
|
|
2161
|
+
},
|
|
2162
|
+
// Multi-tenant filtering - organizationId + userId
|
|
2163
|
+
{
|
|
2164
|
+
name: `${schemaPrefix}mastra_ai_spans_orgid_userid_idx`,
|
|
2165
|
+
table: storage.TABLE_SPANS,
|
|
2166
|
+
columns: ["organizationId", "userId"]
|
|
2167
|
+
}
|
|
2168
|
+
// Note: MSSQL doesn't support GIN indexes for JSONB/array containment queries
|
|
2169
|
+
// Metadata and tags filtering will use full table scans on NVARCHAR(MAX) columns
|
|
2170
|
+
];
|
|
2171
|
+
}
|
|
2172
|
+
/**
|
|
2173
|
+
* Creates default indexes for optimal query performance.
|
|
2174
|
+
*/
|
|
2175
|
+
async createDefaultIndexes() {
|
|
2176
|
+
if (this.skipDefaultIndexes) {
|
|
2177
|
+
return;
|
|
2178
|
+
}
|
|
2179
|
+
for (const indexDef of this.getDefaultIndexDefinitions()) {
|
|
2180
|
+
try {
|
|
2181
|
+
await this.db.createIndex(indexDef);
|
|
2182
|
+
} catch (error) {
|
|
2183
|
+
this.logger?.warn?.(`Failed to create index ${indexDef.name}:`, error);
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2186
|
+
}
|
|
2187
|
+
/**
|
|
2188
|
+
* Creates custom user-defined indexes for this domain's tables.
|
|
2189
|
+
*/
|
|
2190
|
+
async createCustomIndexes() {
|
|
2191
|
+
if (!this.indexes || this.indexes.length === 0) {
|
|
2192
|
+
return;
|
|
2193
|
+
}
|
|
2194
|
+
for (const indexDef of this.indexes) {
|
|
2195
|
+
try {
|
|
2196
|
+
await this.db.createIndex(indexDef);
|
|
2197
|
+
} catch (error) {
|
|
2198
|
+
this.logger?.warn?.(`Failed to create custom index ${indexDef.name}:`, error);
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
2043
2201
|
}
|
|
2044
2202
|
async dangerouslyClearAll() {
|
|
2045
2203
|
await this.db.clearTable({ tableName: storage.TABLE_SPANS });
|
|
@@ -2050,15 +2208,18 @@ var ObservabilityMSSQL = class extends storage.ObservabilityStorage {
|
|
|
2050
2208
|
supported: ["batch-with-updates", "insert-only"]
|
|
2051
2209
|
};
|
|
2052
2210
|
}
|
|
2053
|
-
async createSpan(
|
|
2211
|
+
async createSpan(args) {
|
|
2212
|
+
const { span } = args;
|
|
2054
2213
|
try {
|
|
2055
2214
|
const startedAt = span.startedAt instanceof Date ? span.startedAt.toISOString() : span.startedAt;
|
|
2056
2215
|
const endedAt = span.endedAt instanceof Date ? span.endedAt.toISOString() : span.endedAt;
|
|
2216
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2057
2217
|
const record = {
|
|
2058
2218
|
...span,
|
|
2059
2219
|
startedAt,
|
|
2060
|
-
endedAt
|
|
2061
|
-
|
|
2220
|
+
endedAt,
|
|
2221
|
+
createdAt: now,
|
|
2222
|
+
updatedAt: now
|
|
2062
2223
|
};
|
|
2063
2224
|
return this.db.insert({ tableName: storage.TABLE_SPANS, record });
|
|
2064
2225
|
} catch (error$1) {
|
|
@@ -2071,14 +2232,15 @@ var ObservabilityMSSQL = class extends storage.ObservabilityStorage {
|
|
|
2071
2232
|
spanId: span.spanId,
|
|
2072
2233
|
traceId: span.traceId,
|
|
2073
2234
|
spanType: span.spanType,
|
|
2074
|
-
|
|
2235
|
+
name: span.name
|
|
2075
2236
|
}
|
|
2076
2237
|
},
|
|
2077
2238
|
error$1
|
|
2078
2239
|
);
|
|
2079
2240
|
}
|
|
2080
2241
|
}
|
|
2081
|
-
async getTrace(
|
|
2242
|
+
async getTrace(args) {
|
|
2243
|
+
const { traceId } = args;
|
|
2082
2244
|
try {
|
|
2083
2245
|
const tableName = getTableName2({
|
|
2084
2246
|
indexName: storage.TABLE_SPANS,
|
|
@@ -2088,12 +2250,17 @@ var ObservabilityMSSQL = class extends storage.ObservabilityStorage {
|
|
|
2088
2250
|
request.input("traceId", traceId);
|
|
2089
2251
|
const result = await request.query(
|
|
2090
2252
|
`SELECT
|
|
2091
|
-
[traceId], [spanId], [parentSpanId], [name],
|
|
2092
|
-
[
|
|
2253
|
+
[traceId], [spanId], [parentSpanId], [name],
|
|
2254
|
+
[entityType], [entityId], [entityName],
|
|
2255
|
+
[userId], [organizationId], [resourceId],
|
|
2256
|
+
[runId], [sessionId], [threadId], [requestId],
|
|
2257
|
+
[environment], [source], [serviceName], [scope],
|
|
2258
|
+
[spanType], [attributes], [metadata], [tags], [links],
|
|
2259
|
+
[input], [output], [error], [isEvent],
|
|
2093
2260
|
[startedAt], [endedAt], [createdAt], [updatedAt]
|
|
2094
2261
|
FROM ${tableName}
|
|
2095
2262
|
WHERE [traceId] = @traceId
|
|
2096
|
-
ORDER BY [startedAt]
|
|
2263
|
+
ORDER BY [startedAt] ASC`
|
|
2097
2264
|
);
|
|
2098
2265
|
if (!result.recordset || result.recordset.length === 0) {
|
|
2099
2266
|
return null;
|
|
@@ -2121,11 +2288,95 @@ var ObservabilityMSSQL = class extends storage.ObservabilityStorage {
|
|
|
2121
2288
|
);
|
|
2122
2289
|
}
|
|
2123
2290
|
}
|
|
2124
|
-
async
|
|
2125
|
-
spanId
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2291
|
+
async getSpan(args) {
|
|
2292
|
+
const { traceId, spanId } = args;
|
|
2293
|
+
try {
|
|
2294
|
+
const tableName = getTableName2({
|
|
2295
|
+
indexName: storage.TABLE_SPANS,
|
|
2296
|
+
schemaName: getSchemaName2(this.schema)
|
|
2297
|
+
});
|
|
2298
|
+
const request = this.pool.request();
|
|
2299
|
+
request.input("traceId", traceId);
|
|
2300
|
+
request.input("spanId", spanId);
|
|
2301
|
+
const result = await request.query(
|
|
2302
|
+
`SELECT
|
|
2303
|
+
[traceId], [spanId], [parentSpanId], [name],
|
|
2304
|
+
[entityType], [entityId], [entityName],
|
|
2305
|
+
[userId], [organizationId], [resourceId],
|
|
2306
|
+
[runId], [sessionId], [threadId], [requestId],
|
|
2307
|
+
[environment], [source], [serviceName], [scope],
|
|
2308
|
+
[spanType], [attributes], [metadata], [tags], [links],
|
|
2309
|
+
[input], [output], [error], [isEvent],
|
|
2310
|
+
[startedAt], [endedAt], [createdAt], [updatedAt]
|
|
2311
|
+
FROM ${tableName}
|
|
2312
|
+
WHERE [traceId] = @traceId AND [spanId] = @spanId`
|
|
2313
|
+
);
|
|
2314
|
+
if (!result.recordset || result.recordset.length === 0) {
|
|
2315
|
+
return null;
|
|
2316
|
+
}
|
|
2317
|
+
return {
|
|
2318
|
+
span: transformFromSqlRow({
|
|
2319
|
+
tableName: storage.TABLE_SPANS,
|
|
2320
|
+
sqlRow: result.recordset[0]
|
|
2321
|
+
})
|
|
2322
|
+
};
|
|
2323
|
+
} catch (error$1) {
|
|
2324
|
+
throw new error.MastraError(
|
|
2325
|
+
{
|
|
2326
|
+
id: storage.createStorageErrorId("MSSQL", "GET_SPAN", "FAILED"),
|
|
2327
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2328
|
+
category: error.ErrorCategory.USER,
|
|
2329
|
+
details: { traceId, spanId }
|
|
2330
|
+
},
|
|
2331
|
+
error$1
|
|
2332
|
+
);
|
|
2333
|
+
}
|
|
2334
|
+
}
|
|
2335
|
+
async getRootSpan(args) {
|
|
2336
|
+
const { traceId } = args;
|
|
2337
|
+
try {
|
|
2338
|
+
const tableName = getTableName2({
|
|
2339
|
+
indexName: storage.TABLE_SPANS,
|
|
2340
|
+
schemaName: getSchemaName2(this.schema)
|
|
2341
|
+
});
|
|
2342
|
+
const request = this.pool.request();
|
|
2343
|
+
request.input("traceId", traceId);
|
|
2344
|
+
const result = await request.query(
|
|
2345
|
+
`SELECT
|
|
2346
|
+
[traceId], [spanId], [parentSpanId], [name],
|
|
2347
|
+
[entityType], [entityId], [entityName],
|
|
2348
|
+
[userId], [organizationId], [resourceId],
|
|
2349
|
+
[runId], [sessionId], [threadId], [requestId],
|
|
2350
|
+
[environment], [source], [serviceName], [scope],
|
|
2351
|
+
[spanType], [attributes], [metadata], [tags], [links],
|
|
2352
|
+
[input], [output], [error], [isEvent],
|
|
2353
|
+
[startedAt], [endedAt], [createdAt], [updatedAt]
|
|
2354
|
+
FROM ${tableName}
|
|
2355
|
+
WHERE [traceId] = @traceId AND [parentSpanId] IS NULL`
|
|
2356
|
+
);
|
|
2357
|
+
if (!result.recordset || result.recordset.length === 0) {
|
|
2358
|
+
return null;
|
|
2359
|
+
}
|
|
2360
|
+
return {
|
|
2361
|
+
span: transformFromSqlRow({
|
|
2362
|
+
tableName: storage.TABLE_SPANS,
|
|
2363
|
+
sqlRow: result.recordset[0]
|
|
2364
|
+
})
|
|
2365
|
+
};
|
|
2366
|
+
} catch (error$1) {
|
|
2367
|
+
throw new error.MastraError(
|
|
2368
|
+
{
|
|
2369
|
+
id: storage.createStorageErrorId("MSSQL", "GET_ROOT_SPAN", "FAILED"),
|
|
2370
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2371
|
+
category: error.ErrorCategory.USER,
|
|
2372
|
+
details: { traceId }
|
|
2373
|
+
},
|
|
2374
|
+
error$1
|
|
2375
|
+
);
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
async updateSpan(args) {
|
|
2379
|
+
const { traceId, spanId, updates } = args;
|
|
2129
2380
|
try {
|
|
2130
2381
|
const data = { ...updates };
|
|
2131
2382
|
if (data.endedAt instanceof Date) {
|
|
@@ -2134,6 +2385,7 @@ var ObservabilityMSSQL = class extends storage.ObservabilityStorage {
|
|
|
2134
2385
|
if (data.startedAt instanceof Date) {
|
|
2135
2386
|
data.startedAt = data.startedAt.toISOString();
|
|
2136
2387
|
}
|
|
2388
|
+
data.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2137
2389
|
await this.db.update({
|
|
2138
2390
|
tableName: storage.TABLE_SPANS,
|
|
2139
2391
|
keys: { spanId, traceId },
|
|
@@ -2154,63 +2406,184 @@ var ObservabilityMSSQL = class extends storage.ObservabilityStorage {
|
|
|
2154
2406
|
);
|
|
2155
2407
|
}
|
|
2156
2408
|
}
|
|
2157
|
-
async
|
|
2158
|
-
filters,
|
|
2159
|
-
pagination
|
|
2160
|
-
}) {
|
|
2161
|
-
const page = pagination?.page ?? 0;
|
|
2162
|
-
const perPage = pagination?.perPage ?? 10;
|
|
2163
|
-
const { entityId, entityType, ...actualFilters } = filters || {};
|
|
2164
|
-
const filtersWithDateRange = {
|
|
2165
|
-
...actualFilters,
|
|
2166
|
-
...buildDateRangeFilter(pagination?.dateRange, "startedAt"),
|
|
2167
|
-
parentSpanId: null
|
|
2168
|
-
// Only get root spans for traces
|
|
2169
|
-
};
|
|
2170
|
-
const whereClause = prepareWhereClause(filtersWithDateRange);
|
|
2171
|
-
let actualWhereClause = whereClause.sql;
|
|
2172
|
-
const params = { ...whereClause.params };
|
|
2173
|
-
let currentParamIndex = Object.keys(params).length + 1;
|
|
2174
|
-
if (entityId && entityType) {
|
|
2175
|
-
let name = "";
|
|
2176
|
-
if (entityType === "workflow") {
|
|
2177
|
-
name = `workflow run: '${entityId}'`;
|
|
2178
|
-
} else if (entityType === "agent") {
|
|
2179
|
-
name = `agent run: '${entityId}'`;
|
|
2180
|
-
} else {
|
|
2181
|
-
const error$1 = new error.MastraError({
|
|
2182
|
-
id: storage.createStorageErrorId("MSSQL", "GET_TRACES_PAGINATED", "INVALID_ENTITY_TYPE"),
|
|
2183
|
-
domain: error.ErrorDomain.STORAGE,
|
|
2184
|
-
category: error.ErrorCategory.USER,
|
|
2185
|
-
details: {
|
|
2186
|
-
entityType
|
|
2187
|
-
},
|
|
2188
|
-
text: `Cannot filter by entity type: ${entityType}`
|
|
2189
|
-
});
|
|
2190
|
-
throw error$1;
|
|
2191
|
-
}
|
|
2192
|
-
const entityParam = `p${currentParamIndex++}`;
|
|
2193
|
-
if (actualWhereClause) {
|
|
2194
|
-
actualWhereClause += ` AND [name] = @${entityParam}`;
|
|
2195
|
-
} else {
|
|
2196
|
-
actualWhereClause = ` WHERE [name] = @${entityParam}`;
|
|
2197
|
-
}
|
|
2198
|
-
params[entityParam] = name;
|
|
2199
|
-
}
|
|
2409
|
+
async listTraces(args) {
|
|
2410
|
+
const { filters, pagination, orderBy } = storage.listTracesArgsSchema.parse(args);
|
|
2411
|
+
const { page, perPage } = pagination;
|
|
2200
2412
|
const tableName = getTableName2({
|
|
2201
2413
|
indexName: storage.TABLE_SPANS,
|
|
2202
2414
|
schemaName: getSchemaName2(this.schema)
|
|
2203
2415
|
});
|
|
2204
2416
|
try {
|
|
2417
|
+
const conditions = ["r.[parentSpanId] IS NULL"];
|
|
2418
|
+
const params = {};
|
|
2419
|
+
let paramIndex = 1;
|
|
2420
|
+
if (filters) {
|
|
2421
|
+
if (filters.startedAt?.start) {
|
|
2422
|
+
const param = `p${paramIndex++}`;
|
|
2423
|
+
conditions.push(`r.[startedAt] >= @${param}`);
|
|
2424
|
+
params[param] = filters.startedAt.start.toISOString();
|
|
2425
|
+
}
|
|
2426
|
+
if (filters.startedAt?.end) {
|
|
2427
|
+
const param = `p${paramIndex++}`;
|
|
2428
|
+
conditions.push(`r.[startedAt] <= @${param}`);
|
|
2429
|
+
params[param] = filters.startedAt.end.toISOString();
|
|
2430
|
+
}
|
|
2431
|
+
if (filters.endedAt?.start) {
|
|
2432
|
+
const param = `p${paramIndex++}`;
|
|
2433
|
+
conditions.push(`r.[endedAt] >= @${param}`);
|
|
2434
|
+
params[param] = filters.endedAt.start.toISOString();
|
|
2435
|
+
}
|
|
2436
|
+
if (filters.endedAt?.end) {
|
|
2437
|
+
const param = `p${paramIndex++}`;
|
|
2438
|
+
conditions.push(`r.[endedAt] <= @${param}`);
|
|
2439
|
+
params[param] = filters.endedAt.end.toISOString();
|
|
2440
|
+
}
|
|
2441
|
+
if (filters.spanType !== void 0) {
|
|
2442
|
+
const param = `p${paramIndex++}`;
|
|
2443
|
+
conditions.push(`r.[spanType] = @${param}`);
|
|
2444
|
+
params[param] = filters.spanType;
|
|
2445
|
+
}
|
|
2446
|
+
if (filters.entityType !== void 0) {
|
|
2447
|
+
const param = `p${paramIndex++}`;
|
|
2448
|
+
conditions.push(`r.[entityType] = @${param}`);
|
|
2449
|
+
params[param] = filters.entityType;
|
|
2450
|
+
}
|
|
2451
|
+
if (filters.entityId !== void 0) {
|
|
2452
|
+
const param = `p${paramIndex++}`;
|
|
2453
|
+
conditions.push(`r.[entityId] = @${param}`);
|
|
2454
|
+
params[param] = filters.entityId;
|
|
2455
|
+
}
|
|
2456
|
+
if (filters.entityName !== void 0) {
|
|
2457
|
+
const param = `p${paramIndex++}`;
|
|
2458
|
+
conditions.push(`r.[entityName] = @${param}`);
|
|
2459
|
+
params[param] = filters.entityName;
|
|
2460
|
+
}
|
|
2461
|
+
if (filters.userId !== void 0) {
|
|
2462
|
+
const param = `p${paramIndex++}`;
|
|
2463
|
+
conditions.push(`r.[userId] = @${param}`);
|
|
2464
|
+
params[param] = filters.userId;
|
|
2465
|
+
}
|
|
2466
|
+
if (filters.organizationId !== void 0) {
|
|
2467
|
+
const param = `p${paramIndex++}`;
|
|
2468
|
+
conditions.push(`r.[organizationId] = @${param}`);
|
|
2469
|
+
params[param] = filters.organizationId;
|
|
2470
|
+
}
|
|
2471
|
+
if (filters.resourceId !== void 0) {
|
|
2472
|
+
const param = `p${paramIndex++}`;
|
|
2473
|
+
conditions.push(`r.[resourceId] = @${param}`);
|
|
2474
|
+
params[param] = filters.resourceId;
|
|
2475
|
+
}
|
|
2476
|
+
if (filters.runId !== void 0) {
|
|
2477
|
+
const param = `p${paramIndex++}`;
|
|
2478
|
+
conditions.push(`r.[runId] = @${param}`);
|
|
2479
|
+
params[param] = filters.runId;
|
|
2480
|
+
}
|
|
2481
|
+
if (filters.sessionId !== void 0) {
|
|
2482
|
+
const param = `p${paramIndex++}`;
|
|
2483
|
+
conditions.push(`r.[sessionId] = @${param}`);
|
|
2484
|
+
params[param] = filters.sessionId;
|
|
2485
|
+
}
|
|
2486
|
+
if (filters.threadId !== void 0) {
|
|
2487
|
+
const param = `p${paramIndex++}`;
|
|
2488
|
+
conditions.push(`r.[threadId] = @${param}`);
|
|
2489
|
+
params[param] = filters.threadId;
|
|
2490
|
+
}
|
|
2491
|
+
if (filters.requestId !== void 0) {
|
|
2492
|
+
const param = `p${paramIndex++}`;
|
|
2493
|
+
conditions.push(`r.[requestId] = @${param}`);
|
|
2494
|
+
params[param] = filters.requestId;
|
|
2495
|
+
}
|
|
2496
|
+
if (filters.environment !== void 0) {
|
|
2497
|
+
const param = `p${paramIndex++}`;
|
|
2498
|
+
conditions.push(`r.[environment] = @${param}`);
|
|
2499
|
+
params[param] = filters.environment;
|
|
2500
|
+
}
|
|
2501
|
+
if (filters.source !== void 0) {
|
|
2502
|
+
const param = `p${paramIndex++}`;
|
|
2503
|
+
conditions.push(`r.[source] = @${param}`);
|
|
2504
|
+
params[param] = filters.source;
|
|
2505
|
+
}
|
|
2506
|
+
if (filters.serviceName !== void 0) {
|
|
2507
|
+
const param = `p${paramIndex++}`;
|
|
2508
|
+
conditions.push(`r.[serviceName] = @${param}`);
|
|
2509
|
+
params[param] = filters.serviceName;
|
|
2510
|
+
}
|
|
2511
|
+
if (filters.scope != null) {
|
|
2512
|
+
for (const [key, value] of Object.entries(filters.scope)) {
|
|
2513
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)) {
|
|
2514
|
+
throw new error.MastraError({
|
|
2515
|
+
id: storage.createStorageErrorId("MSSQL", "LIST_TRACES", "INVALID_FILTER_KEY"),
|
|
2516
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2517
|
+
category: error.ErrorCategory.USER,
|
|
2518
|
+
details: { key }
|
|
2519
|
+
});
|
|
2520
|
+
}
|
|
2521
|
+
const param = `p${paramIndex++}`;
|
|
2522
|
+
conditions.push(`JSON_VALUE(r.[scope], '$.${key}') = @${param}`);
|
|
2523
|
+
params[param] = typeof value === "string" ? value : JSON.stringify(value);
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2526
|
+
if (filters.metadata != null) {
|
|
2527
|
+
for (const [key, value] of Object.entries(filters.metadata)) {
|
|
2528
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)) {
|
|
2529
|
+
throw new error.MastraError({
|
|
2530
|
+
id: storage.createStorageErrorId("MSSQL", "LIST_TRACES", "INVALID_FILTER_KEY"),
|
|
2531
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2532
|
+
category: error.ErrorCategory.USER,
|
|
2533
|
+
details: { key }
|
|
2534
|
+
});
|
|
2535
|
+
}
|
|
2536
|
+
const param = `p${paramIndex++}`;
|
|
2537
|
+
conditions.push(`JSON_VALUE(r.[metadata], '$.${key}') = @${param}`);
|
|
2538
|
+
params[param] = typeof value === "string" ? value : JSON.stringify(value);
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
if (filters.tags != null && filters.tags.length > 0) {
|
|
2542
|
+
for (const tag of filters.tags) {
|
|
2543
|
+
const param = `p${paramIndex++}`;
|
|
2544
|
+
conditions.push(`EXISTS (SELECT 1 FROM OPENJSON(r.[tags]) WHERE [value] = @${param})`);
|
|
2545
|
+
params[param] = tag;
|
|
2546
|
+
}
|
|
2547
|
+
}
|
|
2548
|
+
if (filters.status !== void 0) {
|
|
2549
|
+
switch (filters.status) {
|
|
2550
|
+
case storage.TraceStatus.ERROR:
|
|
2551
|
+
conditions.push(`r.[error] IS NOT NULL`);
|
|
2552
|
+
break;
|
|
2553
|
+
case storage.TraceStatus.RUNNING:
|
|
2554
|
+
conditions.push(`r.[endedAt] IS NULL AND r.[error] IS NULL`);
|
|
2555
|
+
break;
|
|
2556
|
+
case storage.TraceStatus.SUCCESS:
|
|
2557
|
+
conditions.push(`r.[endedAt] IS NOT NULL AND r.[error] IS NULL`);
|
|
2558
|
+
break;
|
|
2559
|
+
}
|
|
2560
|
+
}
|
|
2561
|
+
if (filters.hasChildError !== void 0) {
|
|
2562
|
+
if (filters.hasChildError) {
|
|
2563
|
+
conditions.push(`EXISTS (
|
|
2564
|
+
SELECT 1 FROM ${tableName} c
|
|
2565
|
+
WHERE c.[traceId] = r.[traceId] AND c.[error] IS NOT NULL
|
|
2566
|
+
)`);
|
|
2567
|
+
} else {
|
|
2568
|
+
conditions.push(`NOT EXISTS (
|
|
2569
|
+
SELECT 1 FROM ${tableName} c
|
|
2570
|
+
WHERE c.[traceId] = r.[traceId] AND c.[error] IS NOT NULL
|
|
2571
|
+
)`);
|
|
2572
|
+
}
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2575
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
2576
|
+
const sortField = orderBy.field;
|
|
2577
|
+
const sortDirection = orderBy.direction;
|
|
2205
2578
|
const countRequest = this.pool.request();
|
|
2206
2579
|
Object.entries(params).forEach(([key, value]) => {
|
|
2207
2580
|
countRequest.input(key, value);
|
|
2208
2581
|
});
|
|
2209
2582
|
const countResult = await countRequest.query(
|
|
2210
|
-
`SELECT COUNT(*) as count FROM ${tableName}${
|
|
2583
|
+
`SELECT COUNT(*) as count FROM ${tableName} r ${whereClause}`
|
|
2211
2584
|
);
|
|
2212
|
-
const
|
|
2213
|
-
if (
|
|
2585
|
+
const count = countResult.recordset[0]?.count ?? 0;
|
|
2586
|
+
if (count === 0) {
|
|
2214
2587
|
return {
|
|
2215
2588
|
pagination: {
|
|
2216
2589
|
total: 0,
|
|
@@ -2227,28 +2600,39 @@ var ObservabilityMSSQL = class extends storage.ObservabilityStorage {
|
|
|
2227
2600
|
});
|
|
2228
2601
|
dataRequest.input("offset", page * perPage);
|
|
2229
2602
|
dataRequest.input("limit", perPage);
|
|
2230
|
-
const
|
|
2231
|
-
`SELECT
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2603
|
+
const result = await dataRequest.query(
|
|
2604
|
+
`SELECT
|
|
2605
|
+
r.[traceId], r.[spanId], r.[parentSpanId], r.[name],
|
|
2606
|
+
r.[entityType], r.[entityId], r.[entityName],
|
|
2607
|
+
r.[userId], r.[organizationId], r.[resourceId],
|
|
2608
|
+
r.[runId], r.[sessionId], r.[threadId], r.[requestId],
|
|
2609
|
+
r.[environment], r.[source], r.[serviceName], r.[scope],
|
|
2610
|
+
r.[spanType], r.[attributes], r.[metadata], r.[tags], r.[links],
|
|
2611
|
+
r.[input], r.[output], r.[error], r.[isEvent],
|
|
2612
|
+
r.[startedAt], r.[endedAt], r.[createdAt], r.[updatedAt]
|
|
2613
|
+
FROM ${tableName} r
|
|
2614
|
+
${whereClause}
|
|
2615
|
+
ORDER BY r.[${sortField}] ${sortDirection}
|
|
2616
|
+
OFFSET @offset ROWS FETCH NEXT @limit ROWS ONLY`
|
|
2238
2617
|
);
|
|
2239
2618
|
return {
|
|
2240
2619
|
pagination: {
|
|
2241
|
-
total,
|
|
2620
|
+
total: count,
|
|
2242
2621
|
page,
|
|
2243
2622
|
perPage,
|
|
2244
|
-
hasMore: (page + 1) * perPage <
|
|
2623
|
+
hasMore: (page + 1) * perPage < count
|
|
2245
2624
|
},
|
|
2246
|
-
spans
|
|
2625
|
+
spans: result.recordset.map(
|
|
2626
|
+
(span) => transformFromSqlRow({
|
|
2627
|
+
tableName: storage.TABLE_SPANS,
|
|
2628
|
+
sqlRow: span
|
|
2629
|
+
})
|
|
2630
|
+
)
|
|
2247
2631
|
};
|
|
2248
2632
|
} catch (error$1) {
|
|
2249
2633
|
throw new error.MastraError(
|
|
2250
2634
|
{
|
|
2251
|
-
id: storage.createStorageErrorId("MSSQL", "
|
|
2635
|
+
id: storage.createStorageErrorId("MSSQL", "LIST_TRACES", "FAILED"),
|
|
2252
2636
|
domain: error.ErrorDomain.STORAGE,
|
|
2253
2637
|
category: error.ErrorCategory.USER
|
|
2254
2638
|
},
|
|
@@ -2261,12 +2645,15 @@ var ObservabilityMSSQL = class extends storage.ObservabilityStorage {
|
|
|
2261
2645
|
return;
|
|
2262
2646
|
}
|
|
2263
2647
|
try {
|
|
2648
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2264
2649
|
await this.db.batchInsert({
|
|
2265
2650
|
tableName: storage.TABLE_SPANS,
|
|
2266
2651
|
records: args.records.map((span) => ({
|
|
2267
2652
|
...span,
|
|
2268
2653
|
startedAt: span.startedAt instanceof Date ? span.startedAt.toISOString() : span.startedAt,
|
|
2269
|
-
endedAt: span.endedAt instanceof Date ? span.endedAt.toISOString() : span.endedAt
|
|
2654
|
+
endedAt: span.endedAt instanceof Date ? span.endedAt.toISOString() : span.endedAt,
|
|
2655
|
+
createdAt: now,
|
|
2656
|
+
updatedAt: now
|
|
2270
2657
|
}))
|
|
2271
2658
|
});
|
|
2272
2659
|
} catch (error$1) {
|
|
@@ -2287,6 +2674,7 @@ var ObservabilityMSSQL = class extends storage.ObservabilityStorage {
|
|
|
2287
2674
|
if (!args.records || args.records.length === 0) {
|
|
2288
2675
|
return;
|
|
2289
2676
|
}
|
|
2677
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2290
2678
|
try {
|
|
2291
2679
|
const updates = args.records.map(({ traceId, spanId, updates: data }) => {
|
|
2292
2680
|
const processedData = { ...data };
|
|
@@ -2296,6 +2684,7 @@ var ObservabilityMSSQL = class extends storage.ObservabilityStorage {
|
|
|
2296
2684
|
if (processedData.startedAt instanceof Date) {
|
|
2297
2685
|
processedData.startedAt = processedData.startedAt.toISOString();
|
|
2298
2686
|
}
|
|
2687
|
+
processedData.updatedAt = now;
|
|
2299
2688
|
return {
|
|
2300
2689
|
keys: { spanId, traceId },
|
|
2301
2690
|
data: processedData
|
|
@@ -2349,18 +2738,24 @@ function transformScoreRow(row) {
|
|
|
2349
2738
|
convertTimestamps: true
|
|
2350
2739
|
});
|
|
2351
2740
|
}
|
|
2352
|
-
var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
2741
|
+
var ScoresMSSQL = class _ScoresMSSQL extends storage.ScoresStorage {
|
|
2353
2742
|
pool;
|
|
2354
2743
|
db;
|
|
2355
2744
|
schema;
|
|
2356
2745
|
needsConnect;
|
|
2746
|
+
skipDefaultIndexes;
|
|
2747
|
+
indexes;
|
|
2748
|
+
/** Tables managed by this domain */
|
|
2749
|
+
static MANAGED_TABLES = [storage.TABLE_SCORERS];
|
|
2357
2750
|
constructor(config) {
|
|
2358
2751
|
super();
|
|
2359
|
-
const { pool,
|
|
2752
|
+
const { pool, schemaName, skipDefaultIndexes, indexes, needsConnect } = resolveMssqlConfig(config);
|
|
2360
2753
|
this.pool = pool;
|
|
2361
|
-
this.
|
|
2362
|
-
this.
|
|
2754
|
+
this.schema = schemaName;
|
|
2755
|
+
this.db = new MssqlDB({ pool, schemaName, skipDefaultIndexes });
|
|
2363
2756
|
this.needsConnect = needsConnect;
|
|
2757
|
+
this.skipDefaultIndexes = skipDefaultIndexes;
|
|
2758
|
+
this.indexes = indexes?.filter((idx) => _ScoresMSSQL.MANAGED_TABLES.includes(idx.table));
|
|
2364
2759
|
}
|
|
2365
2760
|
async init() {
|
|
2366
2761
|
if (this.needsConnect) {
|
|
@@ -2368,6 +2763,52 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
2368
2763
|
this.needsConnect = false;
|
|
2369
2764
|
}
|
|
2370
2765
|
await this.db.createTable({ tableName: storage.TABLE_SCORERS, schema: storage.TABLE_SCHEMAS[storage.TABLE_SCORERS] });
|
|
2766
|
+
await this.createDefaultIndexes();
|
|
2767
|
+
await this.createCustomIndexes();
|
|
2768
|
+
}
|
|
2769
|
+
/**
|
|
2770
|
+
* Returns default index definitions for the scores domain tables.
|
|
2771
|
+
* IMPORTANT: Uses seq_id DESC instead of createdAt DESC for MSSQL due to millisecond accuracy limitations
|
|
2772
|
+
*/
|
|
2773
|
+
getDefaultIndexDefinitions() {
|
|
2774
|
+
const schemaPrefix = this.schema ? `${this.schema}_` : "";
|
|
2775
|
+
return [
|
|
2776
|
+
{
|
|
2777
|
+
name: `${schemaPrefix}mastra_scores_trace_id_span_id_seqid_idx`,
|
|
2778
|
+
table: storage.TABLE_SCORERS,
|
|
2779
|
+
columns: ["traceId", "spanId", "seq_id DESC"]
|
|
2780
|
+
}
|
|
2781
|
+
];
|
|
2782
|
+
}
|
|
2783
|
+
/**
|
|
2784
|
+
* Creates default indexes for optimal query performance.
|
|
2785
|
+
*/
|
|
2786
|
+
async createDefaultIndexes() {
|
|
2787
|
+
if (this.skipDefaultIndexes) {
|
|
2788
|
+
return;
|
|
2789
|
+
}
|
|
2790
|
+
for (const indexDef of this.getDefaultIndexDefinitions()) {
|
|
2791
|
+
try {
|
|
2792
|
+
await this.db.createIndex(indexDef);
|
|
2793
|
+
} catch (error) {
|
|
2794
|
+
this.logger?.warn?.(`Failed to create index ${indexDef.name}:`, error);
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2798
|
+
/**
|
|
2799
|
+
* Creates custom user-defined indexes for this domain's tables.
|
|
2800
|
+
*/
|
|
2801
|
+
async createCustomIndexes() {
|
|
2802
|
+
if (!this.indexes || this.indexes.length === 0) {
|
|
2803
|
+
return;
|
|
2804
|
+
}
|
|
2805
|
+
for (const indexDef of this.indexes) {
|
|
2806
|
+
try {
|
|
2807
|
+
await this.db.createIndex(indexDef);
|
|
2808
|
+
} catch (error) {
|
|
2809
|
+
this.logger?.warn?.(`Failed to create custom index ${indexDef.name}:`, error);
|
|
2810
|
+
}
|
|
2811
|
+
}
|
|
2371
2812
|
}
|
|
2372
2813
|
async dangerouslyClearAll() {
|
|
2373
2814
|
await this.db.clearTable({ tableName: storage.TABLE_SCORERS });
|
|
@@ -2406,7 +2847,7 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
2406
2847
|
domain: error.ErrorDomain.STORAGE,
|
|
2407
2848
|
category: error.ErrorCategory.USER,
|
|
2408
2849
|
details: {
|
|
2409
|
-
scorer: score.scorer?.id ?? "unknown",
|
|
2850
|
+
scorer: typeof score.scorer?.id === "string" ? score.scorer.id : String(score.scorer?.id ?? "unknown"),
|
|
2410
2851
|
entityId: score.entityId ?? "unknown",
|
|
2411
2852
|
entityType: score.entityType ?? "unknown",
|
|
2412
2853
|
traceId: score.traceId ?? "",
|
|
@@ -2712,18 +3153,40 @@ var ScoresMSSQL = class extends storage.ScoresStorage {
|
|
|
2712
3153
|
}
|
|
2713
3154
|
}
|
|
2714
3155
|
};
|
|
2715
|
-
var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
3156
|
+
var WorkflowsMSSQL = class _WorkflowsMSSQL extends storage.WorkflowsStorage {
|
|
2716
3157
|
pool;
|
|
2717
3158
|
db;
|
|
2718
3159
|
schema;
|
|
2719
3160
|
needsConnect;
|
|
3161
|
+
skipDefaultIndexes;
|
|
3162
|
+
indexes;
|
|
3163
|
+
/** Tables managed by this domain */
|
|
3164
|
+
static MANAGED_TABLES = [storage.TABLE_WORKFLOW_SNAPSHOT];
|
|
2720
3165
|
constructor(config) {
|
|
2721
3166
|
super();
|
|
2722
|
-
const { pool,
|
|
3167
|
+
const { pool, schemaName, skipDefaultIndexes, indexes, needsConnect } = resolveMssqlConfig(config);
|
|
2723
3168
|
this.pool = pool;
|
|
2724
|
-
this.
|
|
2725
|
-
this.
|
|
3169
|
+
this.schema = schemaName;
|
|
3170
|
+
this.db = new MssqlDB({ pool, schemaName, skipDefaultIndexes });
|
|
2726
3171
|
this.needsConnect = needsConnect;
|
|
3172
|
+
this.skipDefaultIndexes = skipDefaultIndexes;
|
|
3173
|
+
this.indexes = indexes?.filter((idx) => _WorkflowsMSSQL.MANAGED_TABLES.includes(idx.table));
|
|
3174
|
+
}
|
|
3175
|
+
/**
|
|
3176
|
+
* Returns default index definitions for the workflows domain tables.
|
|
3177
|
+
* Currently no default indexes are defined for workflows.
|
|
3178
|
+
*/
|
|
3179
|
+
getDefaultIndexDefinitions() {
|
|
3180
|
+
return [];
|
|
3181
|
+
}
|
|
3182
|
+
/**
|
|
3183
|
+
* Creates default indexes for optimal query performance.
|
|
3184
|
+
* Currently no default indexes are defined for workflows.
|
|
3185
|
+
*/
|
|
3186
|
+
async createDefaultIndexes() {
|
|
3187
|
+
if (this.skipDefaultIndexes) {
|
|
3188
|
+
return;
|
|
3189
|
+
}
|
|
2727
3190
|
}
|
|
2728
3191
|
async init() {
|
|
2729
3192
|
if (this.needsConnect) {
|
|
@@ -2731,6 +3194,23 @@ var WorkflowsMSSQL = class extends storage.WorkflowsStorage {
|
|
|
2731
3194
|
this.needsConnect = false;
|
|
2732
3195
|
}
|
|
2733
3196
|
await this.db.createTable({ tableName: storage.TABLE_WORKFLOW_SNAPSHOT, schema: storage.TABLE_SCHEMAS[storage.TABLE_WORKFLOW_SNAPSHOT] });
|
|
3197
|
+
await this.createDefaultIndexes();
|
|
3198
|
+
await this.createCustomIndexes();
|
|
3199
|
+
}
|
|
3200
|
+
/**
|
|
3201
|
+
* Creates custom user-defined indexes for this domain's tables.
|
|
3202
|
+
*/
|
|
3203
|
+
async createCustomIndexes() {
|
|
3204
|
+
if (!this.indexes || this.indexes.length === 0) {
|
|
3205
|
+
return;
|
|
3206
|
+
}
|
|
3207
|
+
for (const indexDef of this.indexes) {
|
|
3208
|
+
try {
|
|
3209
|
+
await this.db.createIndex(indexDef);
|
|
3210
|
+
} catch (error) {
|
|
3211
|
+
this.logger?.warn?.(`Failed to create custom index ${indexDef.name}:`, error);
|
|
3212
|
+
}
|
|
3213
|
+
}
|
|
2734
3214
|
}
|
|
2735
3215
|
async dangerouslyClearAll() {
|
|
2736
3216
|
await this.db.clearTable({ tableName: storage.TABLE_WORKFLOW_SNAPSHOT });
|
|
@@ -3125,7 +3605,6 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
3125
3605
|
pool;
|
|
3126
3606
|
schema;
|
|
3127
3607
|
isConnected = null;
|
|
3128
|
-
#db;
|
|
3129
3608
|
stores;
|
|
3130
3609
|
constructor(config) {
|
|
3131
3610
|
if (!config.id || typeof config.id !== "string" || config.id.trim() === "") {
|
|
@@ -3157,8 +3636,12 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
3157
3636
|
options: config.options || { encrypt: true, trustServerCertificate: true }
|
|
3158
3637
|
});
|
|
3159
3638
|
}
|
|
3160
|
-
|
|
3161
|
-
|
|
3639
|
+
const domainConfig = {
|
|
3640
|
+
pool: this.pool,
|
|
3641
|
+
schemaName: this.schema,
|
|
3642
|
+
skipDefaultIndexes: config.skipDefaultIndexes,
|
|
3643
|
+
indexes: config.indexes
|
|
3644
|
+
};
|
|
3162
3645
|
const scores = new ScoresMSSQL(domainConfig);
|
|
3163
3646
|
const workflows = new WorkflowsMSSQL(domainConfig);
|
|
3164
3647
|
const memory = new MemoryMSSQL(domainConfig);
|
|
@@ -3187,11 +3670,6 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
3187
3670
|
try {
|
|
3188
3671
|
await this.isConnected;
|
|
3189
3672
|
await super.init();
|
|
3190
|
-
try {
|
|
3191
|
-
await this.#db.createAutomaticIndexes();
|
|
3192
|
-
} catch (indexError) {
|
|
3193
|
-
this.logger?.warn?.("Failed to create indexes:", indexError);
|
|
3194
|
-
}
|
|
3195
3673
|
} catch (error$1) {
|
|
3196
3674
|
this.isConnected = null;
|
|
3197
3675
|
throw new error.MastraError(
|
|
@@ -3219,207 +3697,20 @@ var MSSQLStore = class extends storage.MastraStorage {
|
|
|
3219
3697
|
hasColumn: true,
|
|
3220
3698
|
createTable: true,
|
|
3221
3699
|
deleteMessages: true,
|
|
3700
|
+
observability: true,
|
|
3701
|
+
indexManagement: true,
|
|
3222
3702
|
listScoresBySpan: true,
|
|
3223
|
-
|
|
3224
|
-
indexManagement: true
|
|
3703
|
+
agents: false
|
|
3225
3704
|
};
|
|
3226
3705
|
}
|
|
3227
3706
|
/**
|
|
3228
|
-
*
|
|
3707
|
+
* Closes the MSSQL connection pool.
|
|
3708
|
+
*
|
|
3709
|
+
* This will close the connection pool, including pre-configured pools.
|
|
3229
3710
|
*/
|
|
3230
|
-
async getThreadById({ threadId }) {
|
|
3231
|
-
return this.stores.memory.getThreadById({ threadId });
|
|
3232
|
-
}
|
|
3233
|
-
async saveThread({ thread }) {
|
|
3234
|
-
return this.stores.memory.saveThread({ thread });
|
|
3235
|
-
}
|
|
3236
|
-
async updateThread({
|
|
3237
|
-
id,
|
|
3238
|
-
title,
|
|
3239
|
-
metadata
|
|
3240
|
-
}) {
|
|
3241
|
-
return this.stores.memory.updateThread({ id, title, metadata });
|
|
3242
|
-
}
|
|
3243
|
-
async deleteThread({ threadId }) {
|
|
3244
|
-
return this.stores.memory.deleteThread({ threadId });
|
|
3245
|
-
}
|
|
3246
|
-
async listMessagesById({ messageIds }) {
|
|
3247
|
-
return this.stores.memory.listMessagesById({ messageIds });
|
|
3248
|
-
}
|
|
3249
|
-
async saveMessages(args) {
|
|
3250
|
-
return this.stores.memory.saveMessages(args);
|
|
3251
|
-
}
|
|
3252
|
-
async updateMessages({
|
|
3253
|
-
messages
|
|
3254
|
-
}) {
|
|
3255
|
-
return this.stores.memory.updateMessages({ messages });
|
|
3256
|
-
}
|
|
3257
|
-
async deleteMessages(messageIds) {
|
|
3258
|
-
return this.stores.memory.deleteMessages(messageIds);
|
|
3259
|
-
}
|
|
3260
|
-
async getResourceById({ resourceId }) {
|
|
3261
|
-
return this.stores.memory.getResourceById({ resourceId });
|
|
3262
|
-
}
|
|
3263
|
-
async saveResource({ resource }) {
|
|
3264
|
-
return this.stores.memory.saveResource({ resource });
|
|
3265
|
-
}
|
|
3266
|
-
async updateResource({
|
|
3267
|
-
resourceId,
|
|
3268
|
-
workingMemory,
|
|
3269
|
-
metadata
|
|
3270
|
-
}) {
|
|
3271
|
-
return this.stores.memory.updateResource({ resourceId, workingMemory, metadata });
|
|
3272
|
-
}
|
|
3273
|
-
/**
|
|
3274
|
-
* Workflows
|
|
3275
|
-
*/
|
|
3276
|
-
async updateWorkflowResults({
|
|
3277
|
-
workflowName,
|
|
3278
|
-
runId,
|
|
3279
|
-
stepId,
|
|
3280
|
-
result,
|
|
3281
|
-
requestContext
|
|
3282
|
-
}) {
|
|
3283
|
-
return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result, requestContext });
|
|
3284
|
-
}
|
|
3285
|
-
async updateWorkflowState({
|
|
3286
|
-
workflowName,
|
|
3287
|
-
runId,
|
|
3288
|
-
opts
|
|
3289
|
-
}) {
|
|
3290
|
-
return this.stores.workflows.updateWorkflowState({ workflowName, runId, opts });
|
|
3291
|
-
}
|
|
3292
|
-
async persistWorkflowSnapshot({
|
|
3293
|
-
workflowName,
|
|
3294
|
-
runId,
|
|
3295
|
-
resourceId,
|
|
3296
|
-
snapshot
|
|
3297
|
-
}) {
|
|
3298
|
-
return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot });
|
|
3299
|
-
}
|
|
3300
|
-
async loadWorkflowSnapshot({
|
|
3301
|
-
workflowName,
|
|
3302
|
-
runId
|
|
3303
|
-
}) {
|
|
3304
|
-
return this.stores.workflows.loadWorkflowSnapshot({ workflowName, runId });
|
|
3305
|
-
}
|
|
3306
|
-
async listWorkflowRuns(args = {}) {
|
|
3307
|
-
return this.stores.workflows.listWorkflowRuns(args);
|
|
3308
|
-
}
|
|
3309
|
-
async getWorkflowRunById({
|
|
3310
|
-
runId,
|
|
3311
|
-
workflowName
|
|
3312
|
-
}) {
|
|
3313
|
-
return this.stores.workflows.getWorkflowRunById({ runId, workflowName });
|
|
3314
|
-
}
|
|
3315
|
-
async deleteWorkflowRunById({ runId, workflowName }) {
|
|
3316
|
-
return this.stores.workflows.deleteWorkflowRunById({ runId, workflowName });
|
|
3317
|
-
}
|
|
3318
3711
|
async close() {
|
|
3319
3712
|
await this.pool.close();
|
|
3320
3713
|
}
|
|
3321
|
-
/**
|
|
3322
|
-
* Index Management
|
|
3323
|
-
*/
|
|
3324
|
-
async createIndex(options) {
|
|
3325
|
-
return this.#db.createIndex(options);
|
|
3326
|
-
}
|
|
3327
|
-
async listIndexes(tableName) {
|
|
3328
|
-
return this.#db.listIndexes(tableName);
|
|
3329
|
-
}
|
|
3330
|
-
async describeIndex(indexName) {
|
|
3331
|
-
return this.#db.describeIndex(indexName);
|
|
3332
|
-
}
|
|
3333
|
-
async dropIndex(indexName) {
|
|
3334
|
-
return this.#db.dropIndex(indexName);
|
|
3335
|
-
}
|
|
3336
|
-
/**
|
|
3337
|
-
* Tracing / Observability
|
|
3338
|
-
*/
|
|
3339
|
-
getObservabilityStore() {
|
|
3340
|
-
if (!this.stores.observability) {
|
|
3341
|
-
throw new error.MastraError({
|
|
3342
|
-
id: storage.createStorageErrorId("MSSQL", "OBSERVABILITY", "NOT_INITIALIZED"),
|
|
3343
|
-
domain: error.ErrorDomain.STORAGE,
|
|
3344
|
-
category: error.ErrorCategory.SYSTEM,
|
|
3345
|
-
text: "Observability storage is not initialized"
|
|
3346
|
-
});
|
|
3347
|
-
}
|
|
3348
|
-
return this.stores.observability;
|
|
3349
|
-
}
|
|
3350
|
-
async createSpan(span) {
|
|
3351
|
-
return this.getObservabilityStore().createSpan(span);
|
|
3352
|
-
}
|
|
3353
|
-
async updateSpan({
|
|
3354
|
-
spanId,
|
|
3355
|
-
traceId,
|
|
3356
|
-
updates
|
|
3357
|
-
}) {
|
|
3358
|
-
return this.getObservabilityStore().updateSpan({ spanId, traceId, updates });
|
|
3359
|
-
}
|
|
3360
|
-
async getTrace(traceId) {
|
|
3361
|
-
return this.getObservabilityStore().getTrace(traceId);
|
|
3362
|
-
}
|
|
3363
|
-
async getTracesPaginated(args) {
|
|
3364
|
-
return this.getObservabilityStore().getTracesPaginated(args);
|
|
3365
|
-
}
|
|
3366
|
-
async batchCreateSpans(args) {
|
|
3367
|
-
return this.getObservabilityStore().batchCreateSpans(args);
|
|
3368
|
-
}
|
|
3369
|
-
async batchUpdateSpans(args) {
|
|
3370
|
-
return this.getObservabilityStore().batchUpdateSpans(args);
|
|
3371
|
-
}
|
|
3372
|
-
async batchDeleteTraces(args) {
|
|
3373
|
-
return this.getObservabilityStore().batchDeleteTraces(args);
|
|
3374
|
-
}
|
|
3375
|
-
/**
|
|
3376
|
-
* Scorers
|
|
3377
|
-
*/
|
|
3378
|
-
async getScoreById({ id: _id }) {
|
|
3379
|
-
return this.stores.scores.getScoreById({ id: _id });
|
|
3380
|
-
}
|
|
3381
|
-
async listScoresByScorerId({
|
|
3382
|
-
scorerId: _scorerId,
|
|
3383
|
-
pagination: _pagination,
|
|
3384
|
-
entityId: _entityId,
|
|
3385
|
-
entityType: _entityType,
|
|
3386
|
-
source: _source
|
|
3387
|
-
}) {
|
|
3388
|
-
return this.stores.scores.listScoresByScorerId({
|
|
3389
|
-
scorerId: _scorerId,
|
|
3390
|
-
pagination: _pagination,
|
|
3391
|
-
entityId: _entityId,
|
|
3392
|
-
entityType: _entityType,
|
|
3393
|
-
source: _source
|
|
3394
|
-
});
|
|
3395
|
-
}
|
|
3396
|
-
async saveScore(score) {
|
|
3397
|
-
return this.stores.scores.saveScore(score);
|
|
3398
|
-
}
|
|
3399
|
-
async listScoresByRunId({
|
|
3400
|
-
runId: _runId,
|
|
3401
|
-
pagination: _pagination
|
|
3402
|
-
}) {
|
|
3403
|
-
return this.stores.scores.listScoresByRunId({ runId: _runId, pagination: _pagination });
|
|
3404
|
-
}
|
|
3405
|
-
async listScoresByEntityId({
|
|
3406
|
-
entityId: _entityId,
|
|
3407
|
-
entityType: _entityType,
|
|
3408
|
-
pagination: _pagination
|
|
3409
|
-
}) {
|
|
3410
|
-
return this.stores.scores.listScoresByEntityId({
|
|
3411
|
-
entityId: _entityId,
|
|
3412
|
-
entityType: _entityType,
|
|
3413
|
-
pagination: _pagination
|
|
3414
|
-
});
|
|
3415
|
-
}
|
|
3416
|
-
async listScoresBySpan({
|
|
3417
|
-
traceId,
|
|
3418
|
-
spanId,
|
|
3419
|
-
pagination: _pagination
|
|
3420
|
-
}) {
|
|
3421
|
-
return this.stores.scores.listScoresBySpan({ traceId, spanId, pagination: _pagination });
|
|
3422
|
-
}
|
|
3423
3714
|
};
|
|
3424
3715
|
|
|
3425
3716
|
exports.MSSQLStore = MSSQLStore;
|