@mastra/mssql 1.10.6-alpha.0 → 1.10.6-alpha.1

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-mssql
3
3
  description: Documentation for @mastra/mssql. Use when working with @mastra/mssql APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/mssql"
6
- version: "1.10.6-alpha.0"
6
+ version: "1.10.6-alpha.1"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.10.6-alpha.0",
2
+ "version": "1.10.6-alpha.1",
3
3
  "package": "@mastra/mssql",
4
4
  "exports": {},
5
5
  "modules": {}
package/dist/index.cjs CHANGED
@@ -2185,9 +2185,17 @@ function withRunFence(pool, claimsTable, fence, operation, write) {
2185
2185
  * duplicate key if they don't. On retry the row exists and the claim
2186
2186
  * serializes behind its row lock.
2187
2187
  */
2188
- async function claimTransaction(pool, fn) {
2188
+ function claimTransaction(pool, fn) {
2189
+ return retryWriteRace(() => inTransaction(pool, fn));
2190
+ }
2191
+ /**
2192
+ * Runs `write` again when it lost a race to insert the same row: a deadlock
2193
+ * victim or a duplicate key. `write` must be a whole statement or
2194
+ * transaction, since a deadlock victim's transaction has already ended.
2195
+ */
2196
+ async function retryWriteRace(write) {
2189
2197
  for (let attempt = 1;; attempt++) try {
2190
- return await inTransaction(pool, fn);
2198
+ return await write();
2191
2199
  } catch (error) {
2192
2200
  const number = error.number;
2193
2201
  if (attempt >= MAX_CLAIM_ATTEMPTS || !(number === ERR_DEADLOCK_VICTIM || number === ERR_PRIMARY_KEY || number === ERR_UNIQUE_INDEX)) throw error;
@@ -4659,6 +4667,9 @@ var WorkflowsMSSQL = class WorkflowsMSSQL extends _mastra_core_storage.Workflows
4659
4667
  this.skipDefaultIndexes = skipDefaultIndexes;
4660
4668
  this.indexes = indexes?.filter((idx) => WorkflowsMSSQL.MANAGED_TABLES.includes(idx.table));
4661
4669
  }
4670
+ supportsGuardedSnapshotWrites() {
4671
+ return true;
4672
+ }
4662
4673
  supportsConcurrentUpdates() {
4663
4674
  return true;
4664
4675
  }
@@ -4968,14 +4979,16 @@ var WorkflowsMSSQL = class WorkflowsMSSQL extends _mastra_core_storage.Workflows
4968
4979
  }, error);
4969
4980
  }
4970
4981
  }
4971
- async persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot, fence }) {
4982
+ async persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot, fence, expectedStatus }) {
4972
4983
  const table = getTableName({
4973
4984
  indexName: _mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT,
4974
4985
  schemaName: getSchemaName(this.schema)
4975
4986
  });
4976
4987
  const now = (/* @__PURE__ */ new Date()).toISOString();
4988
+ const expectedStatuses = expectedStatus === void 0 ? void 0 : Array.isArray(expectedStatus) ? expectedStatus : [expectedStatus];
4989
+ const guard = expectedStatuses === void 0 ? "" : expectedStatuses.length === 0 ? " AND 1 = 0" : ` AND JSON_VALUE(target.[snapshot], '$.status') IN (${expectedStatuses.map((_, i) => `@expectedStatus${i}`).join(", ")})`;
4977
4990
  try {
4978
- await withRunFence(this.pool, this.#runOwnersTable, (0, _mastra_core_storage.resolveRunFence)(this, fence, runId), "persistWorkflowSnapshot", async (q) => {
4991
+ return await retryWriteRace(() => withRunFence(this.pool, this.#runOwnersTable, (0, _mastra_core_storage.resolveRunFence)(this, fence, runId), "persistWorkflowSnapshot", async (q) => {
4979
4992
  const request = q.request();
4980
4993
  request.input("workflow_name", workflowName);
4981
4994
  request.input("run_id", runId);
@@ -4983,17 +4996,18 @@ var WorkflowsMSSQL = class WorkflowsMSSQL extends _mastra_core_storage.Workflows
4983
4996
  request.input("snapshot", JSON.stringify(snapshot));
4984
4997
  request.input("createdAt", mssql.default.DateTime2, new Date(now));
4985
4998
  request.input("updatedAt", mssql.default.DateTime2, new Date(now));
4999
+ expectedStatuses?.forEach((status, i) => request.input(`expectedStatus${i}`, status));
4986
5000
  const mergeSql = `MERGE INTO ${table} AS target
4987
5001
  USING (SELECT @workflow_name AS workflow_name, @run_id AS run_id) AS src
4988
5002
  ON target.workflow_name = src.workflow_name AND target.run_id = src.run_id
4989
- WHEN MATCHED THEN UPDATE SET
5003
+ WHEN MATCHED${guard} THEN UPDATE SET
4990
5004
  resourceId = @resourceId,
4991
5005
  snapshot = @snapshot,
4992
5006
  [updatedAt] = @updatedAt
4993
5007
  WHEN NOT MATCHED THEN INSERT (workflow_name, run_id, resourceId, snapshot, [createdAt], [updatedAt])
4994
5008
  VALUES (@workflow_name, @run_id, @resourceId, @snapshot, @createdAt, @updatedAt);`;
4995
- await request.query(mergeSql);
4996
- });
5009
+ return ((await request.query(mergeSql)).rowsAffected[0] ?? 0) > 0;
5010
+ }));
4997
5011
  } catch (error) {
4998
5012
  if ((0, _mastra_core_storage.isRunFenceConflictError)(error)) throw error;
4999
5013
  throw new _mastra_core_error.MastraError({
@@ -5007,6 +5021,27 @@ var WorkflowsMSSQL = class WorkflowsMSSQL extends _mastra_core_storage.Workflows
5007
5021
  }, error);
5008
5022
  }
5009
5023
  }
5024
+ async loadWorkflowRunStatus({ workflowName, runId }) {
5025
+ try {
5026
+ const request = this.pool.request();
5027
+ request.input("workflow_name", workflowName);
5028
+ request.input("run_id", runId);
5029
+ return (await request.query(`SELECT TOP 1 JSON_VALUE([snapshot], '$.status') AS status FROM ${getTableName({
5030
+ indexName: _mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT,
5031
+ schemaName: getSchemaName(this.schema)
5032
+ })} WHERE workflow_name = @workflow_name AND run_id = @run_id`)).recordset?.[0]?.status ?? null;
5033
+ } catch (error) {
5034
+ throw new _mastra_core_error.MastraError({
5035
+ id: (0, _mastra_core_storage.createStorageErrorId)("MSSQL", "LOAD_WORKFLOW_RUN_STATUS", "FAILED"),
5036
+ domain: _mastra_core_error.ErrorDomain.STORAGE,
5037
+ category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
5038
+ details: {
5039
+ workflowName,
5040
+ runId
5041
+ }
5042
+ }, error);
5043
+ }
5044
+ }
5010
5045
  async loadWorkflowSnapshot({ workflowName, runId }) {
5011
5046
  try {
5012
5047
  const result = await this.db.load({