@mastra/libsql 1.27.1-alpha.0 → 1.27.1-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-libsql
3
3
  description: Documentation for @mastra/libsql. Use when working with @mastra/libsql APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/libsql"
6
- version: "1.27.1-alpha.0"
6
+ version: "1.27.1-alpha.1"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.27.1-alpha.0",
2
+ "version": "1.27.1-alpha.1",
3
3
  "package": "@mastra/libsql",
4
4
  "exports": {},
5
5
  "modules": {}
package/dist/index.cjs CHANGED
@@ -2059,6 +2059,41 @@ var LibSQLDB = class extends _mastra_core_base.MastraBase {
2059
2059
  });
2060
2060
  }
2061
2061
  /**
2062
+ * Updates multiple records in one write batch, with the same retry behavior as
2063
+ * {@link batchUpdate}. Returns, in input order, whether each update changed a row,
2064
+ * so callers can put extra conditions in `keys` (for example `{ endedAt: null }`).
2065
+ */
2066
+ async batchUpdateReportingChanges({ tableName, updates }) {
2067
+ return this.executeWriteOperationWithRetry(async () => {
2068
+ const changed = updates.map(() => false);
2069
+ const statements = [];
2070
+ const statementIndexes = [];
2071
+ for (const [index, { keys, data }] of updates.entries()) {
2072
+ const filteredData = await this.filterRecordToKnownColumns(tableName, data);
2073
+ if (Object.keys(filteredData).length === 0) continue;
2074
+ statements.push(prepareUpdateStatement({
2075
+ tableName,
2076
+ updates: filteredData,
2077
+ keys
2078
+ }));
2079
+ statementIndexes.push(index);
2080
+ }
2081
+ if (statements.length === 0) return changed;
2082
+ (await withClientWriteLock(this.client, () => this.client.batch(statements, "write"))).forEach((result, i) => {
2083
+ const index = statementIndexes[i];
2084
+ if (index !== void 0) changed[index] = result.rowsAffected > 0;
2085
+ });
2086
+ return changed;
2087
+ }, `batch update in table ${tableName}`).catch((error) => {
2088
+ throw new _mastra_core_error.MastraError({
2089
+ id: (0, _mastra_core_storage.createStorageErrorId)("LIBSQL", "BATCH_UPDATE_REPORTING_CHANGES", "FAILED"),
2090
+ domain: _mastra_core_error.ErrorDomain.STORAGE,
2091
+ category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
2092
+ details: { tableName }
2093
+ }, error);
2094
+ });
2095
+ }
2096
+ /**
2062
2097
  * Internal batch delete implementation without retry logic.
2063
2098
  * Each record can be deleted based on single or composite keys.
2064
2099
  */
@@ -2191,7 +2226,7 @@ var LibSQLDB = class extends _mastra_core_base.MastraBase {
2191
2226
  * @returns The total count of matching records
2192
2227
  */
2193
2228
  async selectTotalCount({ tableName, whereClause }) {
2194
- const statement = `SELECT COUNT(*) as count FROM ${(0, _mastra_core_utils.parseSqlIdentifier)(tableName, "table name")} ${whereClause ? `${whereClause.sql}` : ""}`;
2229
+ const statement = `SELECT COUNT(*) as count FROM ${(0, _mastra_core_utils.parseSqlIdentifier)(tableName, "table name")} ${whereClause ? whereClause.sql : ""}`;
2195
2230
  const result = await this.client.execute({
2196
2231
  sql: statement,
2197
2232
  args: whereClause?.args ?? []
@@ -12563,24 +12598,27 @@ var ObservabilityLibSQL = class ObservabilityLibSQL extends _mastra_core_storage
12563
12598
  }, error);
12564
12599
  }
12565
12600
  }
12566
- async batchUpdateSpans(args) {
12601
+ #toSpanUpdates(records) {
12567
12602
  const now = (/* @__PURE__ */ new Date()).toISOString();
12603
+ return records.map((record) => {
12604
+ const data = { ...record.updates };
12605
+ if (data.endedAt instanceof Date) data.endedAt = data.endedAt.toISOString();
12606
+ if (data.startedAt instanceof Date) data.startedAt = data.startedAt.toISOString();
12607
+ data.updatedAt = now;
12608
+ return {
12609
+ keys: {
12610
+ spanId: record.spanId,
12611
+ traceId: record.traceId
12612
+ },
12613
+ data
12614
+ };
12615
+ });
12616
+ }
12617
+ async batchUpdateSpans(args) {
12568
12618
  try {
12569
12619
  return this.#db.batchUpdate({
12570
12620
  tableName: _mastra_core_storage.TABLE_SPANS,
12571
- updates: args.records.map((record) => {
12572
- const data = { ...record.updates };
12573
- if (data.endedAt instanceof Date) data.endedAt = data.endedAt.toISOString();
12574
- if (data.startedAt instanceof Date) data.startedAt = data.startedAt.toISOString();
12575
- data.updatedAt = now;
12576
- return {
12577
- keys: {
12578
- spanId: record.spanId,
12579
- traceId: record.traceId
12580
- },
12581
- data
12582
- };
12583
- })
12621
+ updates: this.#toSpanUpdates(args.records)
12584
12622
  });
12585
12623
  } catch (error) {
12586
12624
  throw new _mastra_core_error.MastraError({
@@ -12590,6 +12628,30 @@ var ObservabilityLibSQL = class ObservabilityLibSQL extends _mastra_core_storage
12590
12628
  }, error);
12591
12629
  }
12592
12630
  }
12631
+ async batchUpdateUnendedSpans(args) {
12632
+ try {
12633
+ const changed = await this.#db.batchUpdateReportingChanges({
12634
+ tableName: _mastra_core_storage.TABLE_SPANS,
12635
+ updates: this.#toSpanUpdates(args.records).map((update) => ({
12636
+ ...update,
12637
+ keys: {
12638
+ ...update.keys,
12639
+ endedAt: null
12640
+ }
12641
+ }))
12642
+ });
12643
+ return { updated: args.records.filter((_, index) => changed[index]).map(({ traceId, spanId }) => ({
12644
+ traceId,
12645
+ spanId
12646
+ })) };
12647
+ } catch (error) {
12648
+ throw new _mastra_core_error.MastraError({
12649
+ id: (0, _mastra_core_storage.createStorageErrorId)("LIBSQL", "BATCH_UPDATE_UNENDED_SPANS", "FAILED"),
12650
+ domain: _mastra_core_error.ErrorDomain.STORAGE,
12651
+ category: _mastra_core_error.ErrorCategory.USER
12652
+ }, error);
12653
+ }
12654
+ }
12593
12655
  async batchDeleteTraces(args) {
12594
12656
  this.assertUnscopedBatchDeleteTraces(args);
12595
12657
  try {
@@ -15278,6 +15340,9 @@ var WorkflowsLibSQL = class WorkflowsLibSQL extends _mastra_core_storage.Workflo
15278
15340
  supportsConcurrentUpdates() {
15279
15341
  return true;
15280
15342
  }
15343
+ supportsGuardedSnapshotWrites() {
15344
+ return true;
15345
+ }
15281
15346
  parseWorkflowRun(row) {
15282
15347
  let parsedSnapshot = row.snapshot;
15283
15348
  if (typeof parsedSnapshot === "string") try {
@@ -15551,7 +15616,7 @@ var WorkflowsLibSQL = class WorkflowsLibSQL extends _mastra_core_storage.Workflo
15551
15616
  }
15552
15617
  }), "updateWorkflowState");
15553
15618
  }
15554
- async persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot, createdAt, updatedAt, fence }) {
15619
+ async persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot, createdAt, updatedAt, fence, expectedStatus }) {
15555
15620
  const now = /* @__PURE__ */ new Date();
15556
15621
  const createdAtValue = (createdAt ?? now).toISOString();
15557
15622
  const updatedAtValue = (updatedAt ?? now).toISOString();
@@ -15559,21 +15624,30 @@ var WorkflowsLibSQL = class WorkflowsLibSQL extends _mastra_core_storage.Workflo
15559
15624
  workflowName,
15560
15625
  runId
15561
15626
  });
15627
+ const expected = expectedStatus === void 0 ? [] : Array.isArray(expectedStatus) ? expectedStatus : [expectedStatus];
15628
+ const guard = expectedStatus === void 0 ? "" : expected.length ? ` WHERE json_extract(${_mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT}.snapshot, '$.status') IN (${expected.map(() => "?").join(", ")})` : " WHERE 0";
15562
15629
  const check = this.#runFenceCheck(fence, runId, "persistWorkflowSnapshot");
15563
- await this.executeWithRetry(() => withRunFence(this.#client, check, (writer) => writer.execute({
15630
+ return (await this.executeWithRetry(() => withRunFence(this.#client, check, (writer) => writer.execute({
15564
15631
  sql: `INSERT INTO ${_mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT} (workflow_name, run_id, resourceId, snapshot, createdAt, updatedAt)
15565
15632
  VALUES (?, ?, ?, jsonb(?), ?, ?)
15566
15633
  ON CONFLICT(workflow_name, run_id)
15567
- DO UPDATE SET resourceId = COALESCE(excluded.resourceId, ${_mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT}.resourceId), snapshot = excluded.snapshot, updatedAt = excluded.updatedAt`,
15634
+ DO UPDATE SET resourceId = COALESCE(excluded.resourceId, ${_mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT}.resourceId), snapshot = excluded.snapshot, updatedAt = excluded.updatedAt${guard}`,
15568
15635
  args: [
15569
15636
  workflowName,
15570
15637
  runId,
15571
15638
  resourceId ?? null,
15572
15639
  safeStringify(snapshot),
15573
15640
  createdAtValue,
15574
- updatedAtValue
15641
+ updatedAtValue,
15642
+ ...expected
15575
15643
  ]
15576
- })), "persistWorkflowSnapshot");
15644
+ })), "persistWorkflowSnapshot")).rowsAffected > 0;
15645
+ }
15646
+ async loadWorkflowRunStatus({ workflowName, runId }) {
15647
+ return (await this.#client.execute({
15648
+ sql: `SELECT json_extract(snapshot, '$.status') AS status FROM ${_mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT} WHERE workflow_name = ? AND run_id = ?`,
15649
+ args: [workflowName, runId]
15650
+ })).rows?.[0]?.status ?? null;
15577
15651
  }
15578
15652
  async loadWorkflowSnapshot({ workflowName, runId }) {
15579
15653
  this.logger.debug("Loading workflow snapshot", {