@mastra/mysql 0.8.6-alpha.1 → 0.8.6
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 +270 -113
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +270 -113
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/datasets/index.d.ts +2 -1
- package/dist/storage/domains/datasets/index.d.ts.map +1 -1
- package/dist/storage/domains/experiments/index.d.ts.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -1863,17 +1863,17 @@ var ChannelsMySQL = class ChannelsMySQL extends ChannelsStorage {
|
|
|
1863
1863
|
//#region src/storage/domains/datasets/index.ts
|
|
1864
1864
|
function parseJSON$3(value) {
|
|
1865
1865
|
if (value === null || value === void 0) return void 0;
|
|
1866
|
-
if (typeof value === "string") {
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
} catch {
|
|
1871
|
-
return value;
|
|
1872
|
-
}
|
|
1866
|
+
if (typeof value === "string") try {
|
|
1867
|
+
return JSON.parse(value);
|
|
1868
|
+
} catch {
|
|
1869
|
+
return value;
|
|
1873
1870
|
}
|
|
1874
1871
|
if (typeof value === "object") return value;
|
|
1875
1872
|
return value;
|
|
1876
1873
|
}
|
|
1874
|
+
function parseOptionalJSON(value, emptyValue) {
|
|
1875
|
+
return value === null || value === void 0 ? emptyValue : parseJSON$3(value);
|
|
1876
|
+
}
|
|
1877
1877
|
function jsonArg(value) {
|
|
1878
1878
|
return value === void 0 || value === null ? null : JSON.stringify(value);
|
|
1879
1879
|
}
|
|
@@ -2016,14 +2016,10 @@ var DatasetsMySQL = class DatasetsMySQL extends DatasetsStorage {
|
|
|
2016
2016
|
await this.pool.execute(`DELETE FROM ${formatTableName(TABLE_DATASETS)}`);
|
|
2017
2017
|
}
|
|
2018
2018
|
async experimentTablesExist() {
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
return Number(row?.c ?? 0) === 2;
|
|
2024
|
-
} catch {
|
|
2025
|
-
return false;
|
|
2026
|
-
}
|
|
2019
|
+
const [rows] = await this.pool.execute(`SELECT COUNT(*) AS c FROM information_schema.tables
|
|
2020
|
+
WHERE table_schema = DATABASE() AND table_name IN (?, ?)`, [TABLE_EXPERIMENTS, TABLE_EXPERIMENT_RESULTS]);
|
|
2021
|
+
const row = Array.isArray(rows) ? rows[0] : void 0;
|
|
2022
|
+
return Number(row?.c ?? 0) === 2;
|
|
2027
2023
|
}
|
|
2028
2024
|
mapDataset(row) {
|
|
2029
2025
|
return {
|
|
@@ -2048,6 +2044,8 @@ var DatasetsMySQL = class DatasetsMySQL extends DatasetsStorage {
|
|
|
2048
2044
|
};
|
|
2049
2045
|
}
|
|
2050
2046
|
mapItem(row) {
|
|
2047
|
+
const metadata = row.metadata ? parseJSON$3(row.metadata) : void 0;
|
|
2048
|
+
const emptyValue = metadata?.__purged === true ? null : void 0;
|
|
2051
2049
|
return {
|
|
2052
2050
|
id: row.id,
|
|
2053
2051
|
datasetId: row.datasetId,
|
|
@@ -2055,20 +2053,22 @@ var DatasetsMySQL = class DatasetsMySQL extends DatasetsStorage {
|
|
|
2055
2053
|
externalId: row.externalId ?? null,
|
|
2056
2054
|
organizationId: row.organizationId ?? null,
|
|
2057
2055
|
projectId: row.projectId ?? null,
|
|
2058
|
-
input: parseJSON$3(row.input),
|
|
2059
|
-
groundTruth: row.groundTruth
|
|
2060
|
-
expectedTrajectory: row.expectedTrajectory
|
|
2061
|
-
toolMocks: row.toolMocks
|
|
2062
|
-
unmockedToolPolicy: row.unmockedToolPolicy ??
|
|
2063
|
-
scorerIds: row.scorerIds
|
|
2064
|
-
requestContext: row.requestContext
|
|
2065
|
-
metadata
|
|
2066
|
-
source: row.source
|
|
2056
|
+
input: row.input === null ? null : parseJSON$3(row.input),
|
|
2057
|
+
groundTruth: parseOptionalJSON(row.groundTruth, emptyValue),
|
|
2058
|
+
expectedTrajectory: parseOptionalJSON(row.expectedTrajectory, emptyValue),
|
|
2059
|
+
toolMocks: parseOptionalJSON(row.toolMocks, emptyValue),
|
|
2060
|
+
unmockedToolPolicy: row.unmockedToolPolicy ?? emptyValue,
|
|
2061
|
+
scorerIds: parseOptionalJSON(row.scorerIds, emptyValue),
|
|
2062
|
+
requestContext: parseOptionalJSON(row.requestContext, emptyValue),
|
|
2063
|
+
metadata,
|
|
2064
|
+
source: parseOptionalJSON(row.source, emptyValue),
|
|
2067
2065
|
createdAt: parseDateTime(row.createdAt) ?? /* @__PURE__ */ new Date(),
|
|
2068
2066
|
updatedAt: parseDateTime(row.updatedAt) ?? /* @__PURE__ */ new Date()
|
|
2069
2067
|
};
|
|
2070
2068
|
}
|
|
2071
2069
|
mapItemFull(row) {
|
|
2070
|
+
const metadata = row.metadata ? parseJSON$3(row.metadata) : void 0;
|
|
2071
|
+
const emptyValue = metadata?.__purged === true ? null : void 0;
|
|
2072
2072
|
return {
|
|
2073
2073
|
id: row.id,
|
|
2074
2074
|
datasetId: row.datasetId,
|
|
@@ -2078,15 +2078,15 @@ var DatasetsMySQL = class DatasetsMySQL extends DatasetsStorage {
|
|
|
2078
2078
|
projectId: row.projectId ?? null,
|
|
2079
2079
|
validTo: row.validTo,
|
|
2080
2080
|
isDeleted: Boolean(row.isDeleted),
|
|
2081
|
-
input: parseJSON$3(row.input),
|
|
2082
|
-
groundTruth: row.groundTruth
|
|
2083
|
-
expectedTrajectory: row.expectedTrajectory
|
|
2084
|
-
toolMocks: row.toolMocks
|
|
2085
|
-
unmockedToolPolicy: row.unmockedToolPolicy ??
|
|
2086
|
-
scorerIds: row.scorerIds
|
|
2087
|
-
requestContext: row.requestContext
|
|
2088
|
-
metadata
|
|
2089
|
-
source: row.source
|
|
2081
|
+
input: row.input === null ? null : parseJSON$3(row.input),
|
|
2082
|
+
groundTruth: parseOptionalJSON(row.groundTruth, emptyValue),
|
|
2083
|
+
expectedTrajectory: parseOptionalJSON(row.expectedTrajectory, emptyValue),
|
|
2084
|
+
toolMocks: parseOptionalJSON(row.toolMocks, emptyValue),
|
|
2085
|
+
unmockedToolPolicy: row.unmockedToolPolicy ?? emptyValue,
|
|
2086
|
+
scorerIds: parseOptionalJSON(row.scorerIds, emptyValue),
|
|
2087
|
+
requestContext: parseOptionalJSON(row.requestContext, emptyValue),
|
|
2088
|
+
metadata,
|
|
2089
|
+
source: parseOptionalJSON(row.source, emptyValue),
|
|
2090
2090
|
createdAt: parseDateTime(row.createdAt) ?? /* @__PURE__ */ new Date(),
|
|
2091
2091
|
updatedAt: parseDateTime(row.updatedAt) ?? /* @__PURE__ */ new Date()
|
|
2092
2092
|
};
|
|
@@ -2575,6 +2575,53 @@ var DatasetsMySQL = class DatasetsMySQL extends DatasetsStorage {
|
|
|
2575
2575
|
connection.release();
|
|
2576
2576
|
}
|
|
2577
2577
|
}
|
|
2578
|
+
async _doPurgeItem({ id, datasetId }) {
|
|
2579
|
+
const experimentTablesExist = await this.experimentTablesExist();
|
|
2580
|
+
const connection = await this.pool.getConnection();
|
|
2581
|
+
try {
|
|
2582
|
+
await connection.beginTransaction();
|
|
2583
|
+
await connection.execute(`SELECT ${quoteIdentifier("id", "column name")} FROM ${formatTableName(TABLE_DATASETS)} WHERE ${quoteIdentifier("id", "column name")} = ? FOR UPDATE`, [datasetId]);
|
|
2584
|
+
const itemsTable = formatTableName(TABLE_DATASET_ITEMS);
|
|
2585
|
+
const [rows] = await connection.execute(`SELECT ${quoteIdentifier("id", "column name")} FROM ${itemsTable} WHERE ${quoteIdentifier("id", "column name")} = ? AND ${quoteIdentifier("datasetId", "column name")} = ? LIMIT 1 FOR UPDATE`, [id, datasetId]);
|
|
2586
|
+
if (rows.length === 0) {
|
|
2587
|
+
await connection.commit();
|
|
2588
|
+
return;
|
|
2589
|
+
}
|
|
2590
|
+
const purgedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2591
|
+
const purgedMetadata = JSON.stringify({
|
|
2592
|
+
__purged: true,
|
|
2593
|
+
purgedAt
|
|
2594
|
+
});
|
|
2595
|
+
await connection.execute(`UPDATE ${itemsTable} SET ${quoteIdentifier("input", "column name")} = ?, ${quoteIdentifier("groundTruth", "column name")} = NULL, ${quoteIdentifier("expectedTrajectory", "column name")} = NULL, ${quoteIdentifier("toolMocks", "column name")} = NULL, ${quoteIdentifier("unmockedToolPolicy", "column name")} = NULL, ${quoteIdentifier("scorerIds", "column name")} = NULL, ${quoteIdentifier("requestContext", "column name")} = NULL, ${quoteIdentifier("metadata", "column name")} = ?, ${quoteIdentifier("source", "column name")} = NULL WHERE ${quoteIdentifier("id", "column name")} = ? AND ${quoteIdentifier("datasetId", "column name")} = ?`, [
|
|
2596
|
+
"null",
|
|
2597
|
+
purgedMetadata,
|
|
2598
|
+
id,
|
|
2599
|
+
datasetId
|
|
2600
|
+
]);
|
|
2601
|
+
if (experimentTablesExist) await connection.execute(`UPDATE ${formatTableName(TABLE_EXPERIMENT_RESULTS)} SET ${quoteIdentifier("input", "column name")} = ?, ${quoteIdentifier("output", "column name")} = NULL, ${quoteIdentifier("groundTruth", "column name")} = NULL, ${quoteIdentifier("error", "column name")} = NULL, ${quoteIdentifier("toolMockReport", "column name")} = NULL, ${quoteIdentifier("tags", "column name")} = NULL, ${quoteIdentifier("comment", "column name")} = NULL, ${quoteIdentifier("metadata", "column name")} = ? WHERE ${quoteIdentifier("itemId", "column name")} = ? AND ${quoteIdentifier("experimentId", "column name")} IN (SELECT id FROM ${formatTableName(TABLE_EXPERIMENTS)} WHERE ${quoteIdentifier("datasetId", "column name")} = ?)`, [
|
|
2602
|
+
"null",
|
|
2603
|
+
purgedMetadata,
|
|
2604
|
+
id,
|
|
2605
|
+
datasetId
|
|
2606
|
+
]);
|
|
2607
|
+
await connection.commit();
|
|
2608
|
+
} catch (error) {
|
|
2609
|
+
let transactionError = error;
|
|
2610
|
+
try {
|
|
2611
|
+
await connection.rollback();
|
|
2612
|
+
} catch (rollbackError) {
|
|
2613
|
+
transactionError = new AggregateError([error, rollbackError], "Transaction and rollback both failed");
|
|
2614
|
+
}
|
|
2615
|
+
if (transactionError instanceof MastraError) throw transactionError;
|
|
2616
|
+
throw new MastraError({
|
|
2617
|
+
id: "MYSQL_PURGE_ITEM_FAILED",
|
|
2618
|
+
domain: ErrorDomain.STORAGE,
|
|
2619
|
+
category: ErrorCategory.THIRD_PARTY
|
|
2620
|
+
}, transactionError);
|
|
2621
|
+
} finally {
|
|
2622
|
+
connection.release();
|
|
2623
|
+
}
|
|
2624
|
+
}
|
|
2578
2625
|
async getItemById(args) {
|
|
2579
2626
|
try {
|
|
2580
2627
|
const tableItemsName = formatTableName(TABLE_DATASET_ITEMS);
|
|
@@ -2979,6 +3026,56 @@ var ExperimentsMySQL = class ExperimentsMySQL extends ExperimentsStorage {
|
|
|
2979
3026
|
this.#skipDefaultIndexes = skipDefaultIndexes;
|
|
2980
3027
|
this.#indexes = indexes?.filter((idx) => ExperimentsMySQL.MANAGED_TABLES.includes(idx.table));
|
|
2981
3028
|
}
|
|
3029
|
+
async #withPurgeBarrier(experimentId, itemId, fn) {
|
|
3030
|
+
const connection = await this.pool.getConnection();
|
|
3031
|
+
try {
|
|
3032
|
+
await connection.beginTransaction();
|
|
3033
|
+
const [experimentRows] = await connection.execute(`SELECT ${quoteIdentifier("datasetId", "column name")} FROM ${formatTableName(TABLE_EXPERIMENTS)} WHERE ${quoteIdentifier("id", "column name")} = ?`, [experimentId]);
|
|
3034
|
+
const datasetId = Array.isArray(experimentRows) ? experimentRows[0]?.datasetId ?? null : null;
|
|
3035
|
+
let purgeMetadata = null;
|
|
3036
|
+
if (datasetId) {
|
|
3037
|
+
await connection.execute(`SELECT ${quoteIdentifier("id", "column name")} FROM ${formatTableName(TABLE_DATASETS)} WHERE ${quoteIdentifier("id", "column name")} = ? FOR UPDATE`, [datasetId]);
|
|
3038
|
+
const [itemRows] = await connection.execute(`SELECT ${quoteIdentifier("metadata", "column name")} FROM ${formatTableName(TABLE_DATASET_ITEMS)} WHERE ${quoteIdentifier("id", "column name")} = ? AND ${quoteIdentifier("datasetId", "column name")} = ?`, [itemId, datasetId]);
|
|
3039
|
+
if (Array.isArray(itemRows)) {
|
|
3040
|
+
const purgedRow = itemRows.find((row) => parseJSON$2(row.metadata)?.__purged === true);
|
|
3041
|
+
purgeMetadata = purgedRow ? parseJSON$2(purgedRow.metadata) ?? null : null;
|
|
3042
|
+
}
|
|
3043
|
+
}
|
|
3044
|
+
const result = await fn(connection, purgeMetadata);
|
|
3045
|
+
await connection.commit();
|
|
3046
|
+
return result;
|
|
3047
|
+
} catch (error) {
|
|
3048
|
+
let transactionError = error;
|
|
3049
|
+
try {
|
|
3050
|
+
await connection.rollback();
|
|
3051
|
+
} catch (rollbackError) {
|
|
3052
|
+
transactionError = new AggregateError([error, rollbackError], "Transaction and rollback both failed");
|
|
3053
|
+
}
|
|
3054
|
+
throw transactionError;
|
|
3055
|
+
} finally {
|
|
3056
|
+
connection.release();
|
|
3057
|
+
}
|
|
3058
|
+
}
|
|
3059
|
+
async #ensureExperimentResultNaturalKey() {
|
|
3060
|
+
const tableName = formatTableName(TABLE_EXPERIMENT_RESULTS);
|
|
3061
|
+
const indexName = "idx_experiment_results_exp_item_attempt";
|
|
3062
|
+
const [indexRows] = await this.pool.execute(`SELECT 1 FROM information_schema.STATISTICS
|
|
3063
|
+
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND INDEX_NAME = ?
|
|
3064
|
+
LIMIT 1`, [TABLE_EXPERIMENT_RESULTS, indexName]);
|
|
3065
|
+
if (Array.isArray(indexRows) && indexRows.length > 0) return;
|
|
3066
|
+
try {
|
|
3067
|
+
await this.pool.execute(`CREATE UNIQUE INDEX ${quoteIdentifier(indexName, "index name")} ON ${tableName} (${quoteIdentifier("experimentId", "column name")}(191), ${quoteIdentifier("itemId", "column name")}(191), ((COALESCE(${quoteIdentifier("attempt", "column name")}, 0))))`);
|
|
3068
|
+
} catch (error) {
|
|
3069
|
+
if (hasErrorCode(error, /* @__PURE__ */ new Set([1061, "ER_DUP_KEYNAME"]))) return;
|
|
3070
|
+
if (!hasErrorCode(error, /* @__PURE__ */ new Set([1062, "ER_DUP_ENTRY"]))) throw error;
|
|
3071
|
+
throw new MastraError({
|
|
3072
|
+
id: "MYSQL_EXPERIMENT_RESULT_NATURAL_KEY_MIGRATION_REQUIRED",
|
|
3073
|
+
domain: ErrorDomain.STORAGE,
|
|
3074
|
+
category: ErrorCategory.USER,
|
|
3075
|
+
text: "Could not enforce experiment-result uniqueness. Resolve duplicate experiment, item, and attempt combinations before restarting the MySQL store."
|
|
3076
|
+
}, error);
|
|
3077
|
+
}
|
|
3078
|
+
}
|
|
2982
3079
|
/**
|
|
2983
3080
|
* Returns default index definitions for the experiments domain tables.
|
|
2984
3081
|
*/
|
|
@@ -3035,6 +3132,7 @@ var ExperimentsMySQL = class ExperimentsMySQL extends ExperimentsStorage {
|
|
|
3035
3132
|
"attempt"
|
|
3036
3133
|
]
|
|
3037
3134
|
});
|
|
3135
|
+
await this.#ensureExperimentResultNaturalKey();
|
|
3038
3136
|
await this.createDefaultIndexes();
|
|
3039
3137
|
await this.createCustomIndexes();
|
|
3040
3138
|
}
|
|
@@ -3081,7 +3179,7 @@ var ExperimentsMySQL = class ExperimentsMySQL extends ExperimentsStorage {
|
|
|
3081
3179
|
itemDatasetVersion: row.itemDatasetVersion ?? null,
|
|
3082
3180
|
organizationId: row.organizationId ?? null,
|
|
3083
3181
|
projectId: row.projectId ?? null,
|
|
3084
|
-
input: parseJSON$2(row.input),
|
|
3182
|
+
input: row.input === null ? null : parseJSON$2(row.input),
|
|
3085
3183
|
output: row.output ? parseJSON$2(row.output) : null,
|
|
3086
3184
|
groundTruth: row.groundTruth ? parseJSON$2(row.groundTruth) : null,
|
|
3087
3185
|
metadata: row.metadata ? parseJSON$2(row.metadata) ?? null : null,
|
|
@@ -3376,29 +3474,51 @@ var ExperimentsMySQL = class ExperimentsMySQL extends ExperimentsStorage {
|
|
|
3376
3474
|
try {
|
|
3377
3475
|
const id = input.id ?? randomUUID();
|
|
3378
3476
|
const now = /* @__PURE__ */ new Date();
|
|
3379
|
-
await this.
|
|
3380
|
-
|
|
3381
|
-
|
|
3477
|
+
const purgeMetadata = await this.#withPurgeBarrier(input.experimentId, input.itemId, async (connection, marker) => {
|
|
3478
|
+
await connection.execute(`INSERT INTO ${formatTableName(TABLE_EXPERIMENT_RESULTS)} (
|
|
3479
|
+
${[
|
|
3480
|
+
"id",
|
|
3481
|
+
"experimentId",
|
|
3482
|
+
"itemId",
|
|
3483
|
+
"itemDatasetVersion",
|
|
3484
|
+
"organizationId",
|
|
3485
|
+
"projectId",
|
|
3486
|
+
"input",
|
|
3487
|
+
"output",
|
|
3488
|
+
"groundTruth",
|
|
3489
|
+
"metadata",
|
|
3490
|
+
"error",
|
|
3491
|
+
"startedAt",
|
|
3492
|
+
"completedAt",
|
|
3493
|
+
"retryCount",
|
|
3494
|
+
"attempt",
|
|
3495
|
+
"traceId",
|
|
3496
|
+
"status",
|
|
3497
|
+
"tags",
|
|
3498
|
+
"createdAt"
|
|
3499
|
+
].map((column) => quoteIdentifier(column, "column name")).join(", ")}
|
|
3500
|
+
) VALUES (${Array.from({ length: 19 }, () => "?").join(", ")})`, [
|
|
3382
3501
|
id,
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3502
|
+
input.experimentId,
|
|
3503
|
+
input.itemId,
|
|
3504
|
+
input.itemDatasetVersion ?? null,
|
|
3505
|
+
input.organizationId ?? null,
|
|
3506
|
+
input.projectId ?? null,
|
|
3507
|
+
JSON.stringify(marker ? null : input.input),
|
|
3508
|
+
marker || input.output == null ? null : JSON.stringify(input.output),
|
|
3509
|
+
marker || input.groundTruth == null ? null : JSON.stringify(input.groundTruth),
|
|
3510
|
+
JSON.stringify(marker ?? input.metadata ?? null),
|
|
3511
|
+
marker || input.error == null ? null : JSON.stringify(input.error),
|
|
3512
|
+
input.startedAt,
|
|
3513
|
+
input.completedAt,
|
|
3514
|
+
input.retryCount,
|
|
3515
|
+
input.attempt ?? 0,
|
|
3516
|
+
input.traceId ?? null,
|
|
3517
|
+
input.status ?? null,
|
|
3518
|
+
marker || input.tags == null ? null : JSON.stringify(input.tags),
|
|
3519
|
+
now
|
|
3520
|
+
]);
|
|
3521
|
+
return marker;
|
|
3402
3522
|
});
|
|
3403
3523
|
return {
|
|
3404
3524
|
id,
|
|
@@ -3407,18 +3527,18 @@ var ExperimentsMySQL = class ExperimentsMySQL extends ExperimentsStorage {
|
|
|
3407
3527
|
itemDatasetVersion: input.itemDatasetVersion,
|
|
3408
3528
|
organizationId: input.organizationId ?? null,
|
|
3409
3529
|
projectId: input.projectId ?? null,
|
|
3410
|
-
input: input.input,
|
|
3411
|
-
output: input.output,
|
|
3412
|
-
groundTruth: input.groundTruth,
|
|
3413
|
-
metadata: input.metadata ?? null,
|
|
3414
|
-
error: input.error,
|
|
3530
|
+
input: purgeMetadata ? null : input.input,
|
|
3531
|
+
output: purgeMetadata ? null : input.output,
|
|
3532
|
+
groundTruth: purgeMetadata ? null : input.groundTruth,
|
|
3533
|
+
metadata: purgeMetadata ?? input.metadata ?? null,
|
|
3534
|
+
error: purgeMetadata ? null : input.error,
|
|
3415
3535
|
startedAt: input.startedAt,
|
|
3416
3536
|
completedAt: input.completedAt,
|
|
3417
3537
|
retryCount: input.retryCount,
|
|
3418
3538
|
attempt: input.attempt ?? 0,
|
|
3419
3539
|
traceId: input.traceId ?? null,
|
|
3420
3540
|
status: input.status ?? null,
|
|
3421
|
-
tags: input.tags ?? null,
|
|
3541
|
+
tags: purgeMetadata ? null : input.tags ?? null,
|
|
3422
3542
|
createdAt: now
|
|
3423
3543
|
};
|
|
3424
3544
|
} catch (error) {
|
|
@@ -3457,49 +3577,77 @@ var ExperimentsMySQL = class ExperimentsMySQL extends ExperimentsStorage {
|
|
|
3457
3577
|
});
|
|
3458
3578
|
try {
|
|
3459
3579
|
const attempt = input.attempt ?? 0;
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3580
|
+
return await this.#withPurgeBarrier(input.experimentId, input.itemId, async (connection, marker) => {
|
|
3581
|
+
const tableName = formatTableName(TABLE_EXPERIMENT_RESULTS);
|
|
3582
|
+
const updateColumns = [
|
|
3583
|
+
"itemDatasetVersion",
|
|
3584
|
+
"organizationId",
|
|
3585
|
+
"projectId",
|
|
3586
|
+
"input",
|
|
3587
|
+
"output",
|
|
3588
|
+
"groundTruth",
|
|
3589
|
+
"metadata",
|
|
3590
|
+
"error",
|
|
3591
|
+
"startedAt",
|
|
3592
|
+
"completedAt",
|
|
3593
|
+
"retryCount",
|
|
3594
|
+
"attempt",
|
|
3595
|
+
"traceId",
|
|
3596
|
+
"status",
|
|
3597
|
+
"tags"
|
|
3598
|
+
];
|
|
3599
|
+
const updateValues = [
|
|
3600
|
+
input.itemDatasetVersion ?? null,
|
|
3601
|
+
input.organizationId ?? null,
|
|
3602
|
+
input.projectId ?? null,
|
|
3603
|
+
JSON.stringify(marker ? null : input.input),
|
|
3604
|
+
marker || input.output == null ? null : JSON.stringify(input.output),
|
|
3605
|
+
marker || input.groundTruth == null ? null : JSON.stringify(input.groundTruth),
|
|
3606
|
+
JSON.stringify(marker ?? input.metadata ?? null),
|
|
3607
|
+
marker || input.error == null ? null : JSON.stringify(input.error),
|
|
3608
|
+
input.startedAt,
|
|
3609
|
+
input.completedAt,
|
|
3610
|
+
input.retryCount,
|
|
3484
3611
|
attempt,
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3612
|
+
input.traceId ?? null,
|
|
3613
|
+
input.status ?? null,
|
|
3614
|
+
marker || input.tags == null ? null : JSON.stringify(input.tags)
|
|
3615
|
+
];
|
|
3616
|
+
const columns = [
|
|
3617
|
+
"id",
|
|
3618
|
+
"experimentId",
|
|
3619
|
+
"itemId",
|
|
3620
|
+
...updateColumns,
|
|
3621
|
+
"createdAt"
|
|
3622
|
+
];
|
|
3623
|
+
await connection.execute(`INSERT INTO ${tableName} (${columns.map((column) => quoteIdentifier(column, "column name")).join(", ")})
|
|
3624
|
+
VALUES (${Array.from({ length: columns.length }, () => "?").join(", ")})
|
|
3625
|
+
ON DUPLICATE KEY UPDATE ${updateColumns.map((column) => `${quoteIdentifier(column, "column name")} = VALUES(${quoteIdentifier(column, "column name")})`).join(", ")}`, [
|
|
3626
|
+
randomUUID(),
|
|
3627
|
+
input.experimentId,
|
|
3628
|
+
input.itemId,
|
|
3629
|
+
...updateValues,
|
|
3630
|
+
/* @__PURE__ */ new Date()
|
|
3631
|
+
]);
|
|
3632
|
+
const [rows] = await connection.execute(`SELECT * FROM ${tableName} WHERE ${quoteIdentifier("experimentId", "column name")} = ? AND ${quoteIdentifier("itemId", "column name")} = ? AND ${quoteIdentifier("attempt", "column name")} = ?`, [
|
|
3633
|
+
input.experimentId,
|
|
3634
|
+
input.itemId,
|
|
3499
3635
|
attempt
|
|
3500
|
-
|
|
3636
|
+
]);
|
|
3637
|
+
const row = Array.isArray(rows) ? rows[0] : void 0;
|
|
3638
|
+
if (!row) throw new MastraError({
|
|
3639
|
+
id: "MYSQL_UPSERT_EXPERIMENT_RESULT_NOT_FOUND",
|
|
3640
|
+
domain: ErrorDomain.STORAGE,
|
|
3641
|
+
category: ErrorCategory.USER,
|
|
3642
|
+
text: `Experiment result not found after upsert`,
|
|
3643
|
+
details: {
|
|
3644
|
+
experimentId: input.experimentId,
|
|
3645
|
+
itemId: input.itemId,
|
|
3646
|
+
attempt
|
|
3647
|
+
}
|
|
3648
|
+
});
|
|
3649
|
+
return this.mapExperimentResult(row);
|
|
3501
3650
|
});
|
|
3502
|
-
return updated;
|
|
3503
3651
|
} catch (error) {
|
|
3504
3652
|
if (error instanceof MastraError) throw error;
|
|
3505
3653
|
throw new MastraError({
|
|
@@ -3517,18 +3665,27 @@ var ExperimentsMySQL = class ExperimentsMySQL extends ExperimentsStorage {
|
|
|
3517
3665
|
});
|
|
3518
3666
|
if (!existing) throw new Error(`Experiment result not found: ${input.id}`);
|
|
3519
3667
|
if (input.experimentId && existing.experimentId !== input.experimentId) throw new Error(`Experiment result ${input.id} does not belong to experiment ${input.experimentId}`);
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3668
|
+
return await this.#withPurgeBarrier(existing.experimentId, existing.itemId, async (connection, marker) => {
|
|
3669
|
+
await connection.execute(`UPDATE ${formatTableName(TABLE_EXPERIMENT_RESULTS)}
|
|
3670
|
+
SET ${quoteIdentifier("status", "column name")} = CASE WHEN ? THEN ? ELSE ${quoteIdentifier("status", "column name")} END,
|
|
3671
|
+
${quoteIdentifier("tags", "column name")} = CASE WHEN ? THEN NULL WHEN ? THEN ? ELSE ${quoteIdentifier("tags", "column name")} END,
|
|
3672
|
+
${quoteIdentifier("comment", "column name")} = CASE WHEN ? THEN NULL WHEN ? THEN ? ELSE ${quoteIdentifier("comment", "column name")} END
|
|
3673
|
+
WHERE ${quoteIdentifier("id", "column name")} = ?`, [
|
|
3674
|
+
input.status !== void 0,
|
|
3675
|
+
input.status ?? null,
|
|
3676
|
+
Boolean(marker),
|
|
3677
|
+
input.tags !== void 0,
|
|
3678
|
+
input.tags === void 0 ? null : JSON.stringify(input.tags),
|
|
3679
|
+
Boolean(marker),
|
|
3680
|
+
input.comment !== void 0,
|
|
3681
|
+
input.comment ?? null,
|
|
3682
|
+
input.id
|
|
3683
|
+
]);
|
|
3684
|
+
const [rows] = await connection.execute(`SELECT * FROM ${formatTableName(TABLE_EXPERIMENT_RESULTS)} WHERE ${quoteIdentifier("id", "column name")} = ?`, [input.id]);
|
|
3685
|
+
const row = Array.isArray(rows) ? rows[0] : void 0;
|
|
3686
|
+
if (!row) throw new Error(`Experiment result ${input.id} not found after update`);
|
|
3687
|
+
return this.mapExperimentResult(row);
|
|
3528
3688
|
});
|
|
3529
|
-
const updated = await this.getExperimentResultById({ id: input.id });
|
|
3530
|
-
if (!updated) throw new Error(`Experiment result ${input.id} not found after update`);
|
|
3531
|
-
return updated;
|
|
3532
3689
|
} catch (error) {
|
|
3533
3690
|
if (error instanceof MastraError) throw error;
|
|
3534
3691
|
throw new MastraError({
|