@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/dist/index.js CHANGED
@@ -125,16 +125,21 @@ var PoolAdapter = class {
125
125
  const client = await this.$pool.connect();
126
126
  try {
127
127
  await client.query("BEGIN");
128
- const result = await callback(new TransactionClient(client));
129
- await client.query("COMMIT");
130
- return result;
131
- } catch (error) {
128
+ const txClient = new TransactionClient(client);
132
129
  try {
133
- await client.query("ROLLBACK");
134
- } catch (rollbackError) {
135
- console.error("Transaction rollback failed:", rollbackError);
130
+ const result = await callback(txClient);
131
+ await txClient.drain();
132
+ await client.query("COMMIT");
133
+ return result;
134
+ } catch (error) {
135
+ await txClient.drain().catch(() => void 0);
136
+ try {
137
+ await client.query("ROLLBACK");
138
+ } catch (rollbackError) {
139
+ console.error("Transaction rollback failed:", rollbackError);
140
+ }
141
+ throw error;
136
142
  }
137
- throw error;
138
143
  } finally {
139
144
  client.release();
140
145
  }
@@ -142,41 +147,85 @@ var PoolAdapter = class {
142
147
  };
143
148
  /**
144
149
  * Transaction client that wraps a PoolClient for executing queries within a transaction.
150
+ *
151
+ * Query methods are serialized through a tail promise (same pattern as
152
+ * PinnedClientAdapter). Callers such as memory.updateMessages historically
153
+ * did `queries.push(t.none(...))` then `await t.batch(queries)` — each
154
+ * `t.none()` is async and starts `client.query` immediately, so by the time
155
+ * batch runs, N queries are already in flight on one PoolClient. pg@8 queues
156
+ * those internally and emits a DeprecationWarning; pg@9 will throw.
157
+ * (#20820)
145
158
  */
146
159
  var TransactionClient = class {
147
160
  client;
161
+ /**
162
+ * Serialization tail. Without this gate, concurrent t.none()/t.query()
163
+ * from Promise.all / batch land on the same PoolClient at once.
164
+ */
165
+ #tail = Promise.resolve();
166
+ #error;
148
167
  constructor(client) {
149
168
  this.client = client;
150
169
  }
151
- async none(query, values) {
152
- await this.client.query(query, values);
153
- return null;
170
+ #enqueue(fn) {
171
+ const next = this.#tail.then(fn);
172
+ this.#tail = next.then(() => void 0, (error) => {
173
+ this.#error ??= { value: error };
174
+ });
175
+ return next;
154
176
  }
155
- async one(query, values) {
156
- const result = await this.client.query(query, values);
157
- if (result.rows.length === 0) throw new Error(`No data returned from query: ${truncateQuery(query)}`);
158
- if (result.rows.length > 1) throw new Error(`Multiple rows returned when one was expected: ${truncateQuery(query)}`);
159
- return result.rows[0];
177
+ /**
178
+ * Wait until every enqueued query has settled and surface the first failure.
179
+ * PoolAdapter calls this before COMMIT/ROLLBACK so those control
180
+ * statements never overlap in-flight work on the same client.
181
+ */
182
+ async drain() {
183
+ await this.#tail;
184
+ if (this.#error) {
185
+ const { value } = this.#error;
186
+ this.#error = void 0;
187
+ throw value;
188
+ }
189
+ }
190
+ none(query, values) {
191
+ return this.#enqueue(async () => {
192
+ await this.client.query(query, values);
193
+ return null;
194
+ });
160
195
  }
161
- async oneOrNone(query, values) {
162
- const result = await this.client.query(query, values);
163
- if (result.rows.length === 0) return null;
164
- if (result.rows.length > 1) throw new Error(`Multiple rows returned when one or none was expected: ${truncateQuery(query)}`);
165
- return result.rows[0];
196
+ one(query, values) {
197
+ return this.#enqueue(async () => {
198
+ const result = await this.client.query(query, values);
199
+ if (result.rows.length === 0) throw new Error(`No data returned from query: ${truncateQuery(query)}`);
200
+ if (result.rows.length > 1) throw new Error(`Multiple rows returned when one was expected: ${truncateQuery(query)}`);
201
+ return result.rows[0];
202
+ });
166
203
  }
167
- async any(query, values) {
168
- return (await this.client.query(query, values)).rows;
204
+ oneOrNone(query, values) {
205
+ return this.#enqueue(async () => {
206
+ const result = await this.client.query(query, values);
207
+ if (result.rows.length === 0) return null;
208
+ if (result.rows.length > 1) throw new Error(`Multiple rows returned when one or none was expected: ${truncateQuery(query)}`);
209
+ return result.rows[0];
210
+ });
169
211
  }
170
- async manyOrNone(query, values) {
212
+ any(query, values) {
213
+ return this.#enqueue(async () => {
214
+ return (await this.client.query(query, values)).rows;
215
+ });
216
+ }
217
+ manyOrNone(query, values) {
171
218
  return this.any(query, values);
172
219
  }
173
- async many(query, values) {
174
- const result = await this.client.query(query, values);
175
- if (result.rows.length === 0) throw new Error(`No data returned from query: ${truncateQuery(query)}`);
176
- return result.rows;
220
+ many(query, values) {
221
+ return this.#enqueue(async () => {
222
+ const result = await this.client.query(query, values);
223
+ if (result.rows.length === 0) throw new Error(`No data returned from query: ${truncateQuery(query)}`);
224
+ return result.rows;
225
+ });
177
226
  }
178
- async query(query, values) {
179
- return this.client.query(query, values);
227
+ query(query, values) {
228
+ return this.#enqueue(() => this.client.query(query, values));
180
229
  }
181
230
  async batch(promises) {
182
231
  return Promise.all(promises);
@@ -1976,6 +2025,7 @@ var MemoryDSQL = class MemoryDSQL extends MemoryStorage {
1976
2025
  hasMore: perPageInput === false ? false : offset + perPage < total
1977
2026
  };
1978
2027
  } catch (error) {
2028
+ if (error instanceof MastraError && error.category === ErrorCategory.USER) throw error;
1979
2029
  const mastraError = new MastraError({
1980
2030
  id: createStorageErrorId("DSQL", "LIST_THREADS", "FAILED"),
1981
2031
  domain: ErrorDomain.STORAGE,
@@ -1988,13 +2038,7 @@ var MemoryDSQL = class MemoryDSQL extends MemoryStorage {
1988
2038
  }, error);
1989
2039
  this.logger?.error?.(mastraError.toString());
1990
2040
  this.logger?.trackException(mastraError);
1991
- return {
1992
- threads: [],
1993
- total: 0,
1994
- page,
1995
- perPage: perPageForResponse,
1996
- hasMore: false
1997
- };
2041
+ throw mastraError;
1998
2042
  }
1999
2043
  }
2000
2044
  async saveThread({ thread }) {
@@ -2224,7 +2268,7 @@ var MemoryDSQL = class MemoryDSQL extends MemoryStorage {
2224
2268
  }, error);
2225
2269
  this.logger?.error?.(mastraError.toString());
2226
2270
  this.logger?.trackException(mastraError);
2227
- return { messages: [] };
2271
+ throw mastraError;
2228
2272
  }
2229
2273
  }
2230
2274
  async listMessages(args) {
@@ -2331,6 +2375,7 @@ var MemoryDSQL = class MemoryDSQL extends MemoryStorage {
2331
2375
  hasMore
2332
2376
  };
2333
2377
  } catch (error) {
2378
+ if (error instanceof MastraError && error.category === ErrorCategory.USER) throw error;
2334
2379
  const mastraError = new MastraError({
2335
2380
  id: createStorageErrorId("DSQL", "LIST_MESSAGES", "FAILED"),
2336
2381
  domain: ErrorDomain.STORAGE,
@@ -2342,13 +2387,7 @@ var MemoryDSQL = class MemoryDSQL extends MemoryStorage {
2342
2387
  }, error);
2343
2388
  this.logger?.error?.(mastraError.toString());
2344
2389
  this.logger?.trackException(mastraError);
2345
- return {
2346
- messages: [],
2347
- total: 0,
2348
- page,
2349
- perPage: perPageForResponse,
2350
- hasMore: false
2351
- };
2390
+ throw mastraError;
2352
2391
  }
2353
2392
  }
2354
2393
  async saveMessages({ messages }) {