@mastra/dsql 1.2.2 → 1.3.0-alpha.0

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 CHANGED
@@ -1,5 +1,37 @@
1
1
  # @mastra/dsql
2
2
 
3
+ ## 1.3.0-alpha.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Memory list reads now surface database errors instead of silently returning empty results. ([#17910](https://github.com/mastra-ai/mastra/pull/17910))
8
+
9
+ Previously, the paginated memory reads (`listThreads`, `listMessages`, `listMessagesByResourceId`, and `listMessagesById`) caught backend failures, logged them, and returned an empty payload like `{ threads: [], total: 0, hasMore: false }`. A transient outage (locked table, dropped connection) was therefore indistinguishable from a genuinely empty result, so an agent reading conversation history during a brief failure would treat it as "no history" and could overwrite real state. These methods now re-throw the failure as a `MastraError`. Validation (USER) errors and genuinely empty results are unchanged.
10
+
11
+ **Behavior change**
12
+
13
+ Callers that previously received an empty result on a backend failure will now receive a thrown `MastraError`. If you call these read methods directly (rather than through an agent, which already surfaces errors), wrap them so a transient outage doesn't crash the caller:
14
+
15
+ ```ts
16
+ try {
17
+ const { threads } = await storage.listThreads({ resourceId });
18
+ // ...use threads
19
+ } catch (error) {
20
+ // a real backend failure. Decide whether to retry, surface, or degrade.
21
+ // An empty thread list no longer hides here; it only means "no threads".
22
+ }
23
+ ```
24
+
25
+ ### Patch Changes
26
+
27
+ - dependencies updates: ([#20406](https://github.com/mastra-ai/mastra/pull/20406))
28
+ - Updated dependency [`@aws-sdk/types@^3.974.2` ↗︎](https://www.npmjs.com/package/@aws-sdk/types/v/3.974.2) (from `^3.973.9`, in `dependencies`)
29
+
30
+ - Fixed transaction completion when applications start several database operations at the same time. Pending operations now finish before the transaction completes or is cancelled, preventing query conflicts after batch failures and operations that application code does not await. ([#20869](https://github.com/mastra-ai/mastra/pull/20869))
31
+
32
+ - Updated dependencies [[`e7109ee`](https://github.com/mastra-ai/mastra/commit/e7109ee6f731bacc79c885906f3c7dca8d8f013a), [`772c0c8`](https://github.com/mastra-ai/mastra/commit/772c0c897cec383258de2e6178147f8014767c7b), [`578bf2e`](https://github.com/mastra-ai/mastra/commit/578bf2e6a88e9d5b8bf502204e15a95dfbb679ae), [`06b2d87`](https://github.com/mastra-ai/mastra/commit/06b2d87e63bcdd0ed59215c6789692b9b12de376), [`ac01d63`](https://github.com/mastra-ai/mastra/commit/ac01d6355974aec73fdb8781449ed12bac582094), [`a810a05`](https://github.com/mastra-ai/mastra/commit/a810a058f62ad407cfc1701e0be36ae91145d7cf), [`f8da216`](https://github.com/mastra-ai/mastra/commit/f8da21633e7eb0e31c9ce0fc30567870d19416d3), [`6104347`](https://github.com/mastra-ai/mastra/commit/61043473ba6bfd0a25156824e853e13165562e6c), [`45bfb88`](https://github.com/mastra-ai/mastra/commit/45bfb88fd52f1dd3be20e2a38905777c96499c90), [`e3b9307`](https://github.com/mastra-ai/mastra/commit/e3b9307098daefbfae2a52ae2ef51bc9fc701190), [`d6834c5`](https://github.com/mastra-ai/mastra/commit/d6834c5a7866b16734d23900163c2414ed70d791), [`c52d346`](https://github.com/mastra-ai/mastra/commit/c52d3462ec831a5d95926ecd3d3373f5928ad2e5), [`0023e79`](https://github.com/mastra-ai/mastra/commit/0023e7919431078280abd11c89d1edeae35fcc69), [`c2ad51e`](https://github.com/mastra-ai/mastra/commit/c2ad51e2467f901eecba8c9f4a45e22a50bd7c18), [`3dc97ea`](https://github.com/mastra-ai/mastra/commit/3dc97ea415fad353b48a13095fad1835933cc12a), [`3d01cd3`](https://github.com/mastra-ai/mastra/commit/3d01cd387321b6f9c5cac31d487c84bf51b19c78), [`7bf3086`](https://github.com/mastra-ai/mastra/commit/7bf308663f0115ca74ad20554ade740f06640859), [`a8dd139`](https://github.com/mastra-ai/mastra/commit/a8dd1391a9fe9a6632c25809ef236980afa9a020), [`e5786be`](https://github.com/mastra-ai/mastra/commit/e5786be02bb903073082bd9d6da880ebaacc343f), [`2093fbd`](https://github.com/mastra-ai/mastra/commit/2093fbd53bb744bae19ec89f6d73db9a66fbe8a7), [`e7a5da4`](https://github.com/mastra-ai/mastra/commit/e7a5da4ef8e4dd452d2f232961b4e682a85ffe43), [`7b4393d`](https://github.com/mastra-ai/mastra/commit/7b4393d557411fdcf07b0e30e5acaf7cc85154ae)]:
33
+ - @mastra/core@1.58.0-alpha.1
34
+
3
35
  ## 1.2.2
4
36
 
5
37
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -126,16 +126,21 @@ var PoolAdapter = class {
126
126
  const client = await this.$pool.connect();
127
127
  try {
128
128
  await client.query("BEGIN");
129
- const result = await callback(new TransactionClient(client));
130
- await client.query("COMMIT");
131
- return result;
132
- } catch (error) {
129
+ const txClient = new TransactionClient(client);
133
130
  try {
134
- await client.query("ROLLBACK");
135
- } catch (rollbackError) {
136
- console.error("Transaction rollback failed:", rollbackError);
131
+ const result = await callback(txClient);
132
+ await txClient.drain();
133
+ await client.query("COMMIT");
134
+ return result;
135
+ } catch (error) {
136
+ await txClient.drain().catch(() => void 0);
137
+ try {
138
+ await client.query("ROLLBACK");
139
+ } catch (rollbackError) {
140
+ console.error("Transaction rollback failed:", rollbackError);
141
+ }
142
+ throw error;
137
143
  }
138
- throw error;
139
144
  } finally {
140
145
  client.release();
141
146
  }
@@ -143,41 +148,85 @@ var PoolAdapter = class {
143
148
  };
144
149
  /**
145
150
  * Transaction client that wraps a PoolClient for executing queries within a transaction.
151
+ *
152
+ * Query methods are serialized through a tail promise (same pattern as
153
+ * PinnedClientAdapter). Callers such as memory.updateMessages historically
154
+ * did `queries.push(t.none(...))` then `await t.batch(queries)` — each
155
+ * `t.none()` is async and starts `client.query` immediately, so by the time
156
+ * batch runs, N queries are already in flight on one PoolClient. pg@8 queues
157
+ * those internally and emits a DeprecationWarning; pg@9 will throw.
158
+ * (#20820)
146
159
  */
147
160
  var TransactionClient = class {
148
161
  client;
162
+ /**
163
+ * Serialization tail. Without this gate, concurrent t.none()/t.query()
164
+ * from Promise.all / batch land on the same PoolClient at once.
165
+ */
166
+ #tail = Promise.resolve();
167
+ #error;
149
168
  constructor(client) {
150
169
  this.client = client;
151
170
  }
152
- async none(query, values) {
153
- await this.client.query(query, values);
154
- return null;
171
+ #enqueue(fn) {
172
+ const next = this.#tail.then(fn);
173
+ this.#tail = next.then(() => void 0, (error) => {
174
+ this.#error ??= { value: error };
175
+ });
176
+ return next;
155
177
  }
156
- async one(query, values) {
157
- const result = await this.client.query(query, values);
158
- if (result.rows.length === 0) throw new Error(`No data returned from query: ${truncateQuery(query)}`);
159
- if (result.rows.length > 1) throw new Error(`Multiple rows returned when one was expected: ${truncateQuery(query)}`);
160
- return result.rows[0];
178
+ /**
179
+ * Wait until every enqueued query has settled and surface the first failure.
180
+ * PoolAdapter calls this before COMMIT/ROLLBACK so those control
181
+ * statements never overlap in-flight work on the same client.
182
+ */
183
+ async drain() {
184
+ await this.#tail;
185
+ if (this.#error) {
186
+ const { value } = this.#error;
187
+ this.#error = void 0;
188
+ throw value;
189
+ }
190
+ }
191
+ none(query, values) {
192
+ return this.#enqueue(async () => {
193
+ await this.client.query(query, values);
194
+ return null;
195
+ });
161
196
  }
162
- async oneOrNone(query, values) {
163
- const result = await this.client.query(query, values);
164
- if (result.rows.length === 0) return null;
165
- if (result.rows.length > 1) throw new Error(`Multiple rows returned when one or none was expected: ${truncateQuery(query)}`);
166
- return result.rows[0];
197
+ one(query, values) {
198
+ return this.#enqueue(async () => {
199
+ const result = await this.client.query(query, values);
200
+ if (result.rows.length === 0) throw new Error(`No data returned from query: ${truncateQuery(query)}`);
201
+ if (result.rows.length > 1) throw new Error(`Multiple rows returned when one was expected: ${truncateQuery(query)}`);
202
+ return result.rows[0];
203
+ });
167
204
  }
168
- async any(query, values) {
169
- return (await this.client.query(query, values)).rows;
205
+ oneOrNone(query, values) {
206
+ return this.#enqueue(async () => {
207
+ const result = await this.client.query(query, values);
208
+ if (result.rows.length === 0) return null;
209
+ if (result.rows.length > 1) throw new Error(`Multiple rows returned when one or none was expected: ${truncateQuery(query)}`);
210
+ return result.rows[0];
211
+ });
170
212
  }
171
- async manyOrNone(query, values) {
213
+ any(query, values) {
214
+ return this.#enqueue(async () => {
215
+ return (await this.client.query(query, values)).rows;
216
+ });
217
+ }
218
+ manyOrNone(query, values) {
172
219
  return this.any(query, values);
173
220
  }
174
- async many(query, values) {
175
- const result = await this.client.query(query, values);
176
- if (result.rows.length === 0) throw new Error(`No data returned from query: ${truncateQuery(query)}`);
177
- return result.rows;
221
+ many(query, values) {
222
+ return this.#enqueue(async () => {
223
+ const result = await this.client.query(query, values);
224
+ if (result.rows.length === 0) throw new Error(`No data returned from query: ${truncateQuery(query)}`);
225
+ return result.rows;
226
+ });
178
227
  }
179
- async query(query, values) {
180
- return this.client.query(query, values);
228
+ query(query, values) {
229
+ return this.#enqueue(() => this.client.query(query, values));
181
230
  }
182
231
  async batch(promises) {
183
232
  return Promise.all(promises);
@@ -1977,6 +2026,7 @@ var MemoryDSQL = class MemoryDSQL extends _mastra_core_storage.MemoryStorage {
1977
2026
  hasMore: perPageInput === false ? false : offset + perPage < total
1978
2027
  };
1979
2028
  } catch (error) {
2029
+ if (error instanceof _mastra_core_error.MastraError && error.category === _mastra_core_error.ErrorCategory.USER) throw error;
1980
2030
  const mastraError = new _mastra_core_error.MastraError({
1981
2031
  id: (0, _mastra_core_storage.createStorageErrorId)("DSQL", "LIST_THREADS", "FAILED"),
1982
2032
  domain: _mastra_core_error.ErrorDomain.STORAGE,
@@ -1989,13 +2039,7 @@ var MemoryDSQL = class MemoryDSQL extends _mastra_core_storage.MemoryStorage {
1989
2039
  }, error);
1990
2040
  this.logger?.error?.(mastraError.toString());
1991
2041
  this.logger?.trackException(mastraError);
1992
- return {
1993
- threads: [],
1994
- total: 0,
1995
- page,
1996
- perPage: perPageForResponse,
1997
- hasMore: false
1998
- };
2042
+ throw mastraError;
1999
2043
  }
2000
2044
  }
2001
2045
  async saveThread({ thread }) {
@@ -2225,7 +2269,7 @@ var MemoryDSQL = class MemoryDSQL extends _mastra_core_storage.MemoryStorage {
2225
2269
  }, error);
2226
2270
  this.logger?.error?.(mastraError.toString());
2227
2271
  this.logger?.trackException(mastraError);
2228
- return { messages: [] };
2272
+ throw mastraError;
2229
2273
  }
2230
2274
  }
2231
2275
  async listMessages(args) {
@@ -2332,6 +2376,7 @@ var MemoryDSQL = class MemoryDSQL extends _mastra_core_storage.MemoryStorage {
2332
2376
  hasMore
2333
2377
  };
2334
2378
  } catch (error) {
2379
+ if (error instanceof _mastra_core_error.MastraError && error.category === _mastra_core_error.ErrorCategory.USER) throw error;
2335
2380
  const mastraError = new _mastra_core_error.MastraError({
2336
2381
  id: (0, _mastra_core_storage.createStorageErrorId)("DSQL", "LIST_MESSAGES", "FAILED"),
2337
2382
  domain: _mastra_core_error.ErrorDomain.STORAGE,
@@ -2343,13 +2388,7 @@ var MemoryDSQL = class MemoryDSQL extends _mastra_core_storage.MemoryStorage {
2343
2388
  }, error);
2344
2389
  this.logger?.error?.(mastraError.toString());
2345
2390
  this.logger?.trackException(mastraError);
2346
- return {
2347
- messages: [],
2348
- total: 0,
2349
- page,
2350
- perPage: perPageForResponse,
2351
- hasMore: false
2352
- };
2391
+ throw mastraError;
2353
2392
  }
2354
2393
  }
2355
2394
  async saveMessages({ messages }) {