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