@mastra/dsql 1.2.2 → 1.3.0-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.
- package/CHANGELOG.md +41 -0
- package/dist/index.cjs +103 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +103 -49
- package/dist/index.js.map +1 -1
- package/dist/storage/client.d.ts +5 -1
- package/dist/storage/client.d.ts.map +1 -1
- package/dist/storage/domains/memory/index.d.ts +7 -0
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/package.json +6 -6
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
|
|
129
|
-
await client.query("COMMIT");
|
|
130
|
-
return result;
|
|
131
|
-
} catch (error) {
|
|
128
|
+
const txClient = new TransactionClient(client);
|
|
132
129
|
try {
|
|
133
|
-
await
|
|
134
|
-
|
|
135
|
-
|
|
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
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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
|
-
|
|
168
|
-
return (
|
|
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
|
-
|
|
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
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 }) {
|
|
@@ -2128,7 +2172,14 @@ var MemoryDSQL = class MemoryDSQL extends MemoryStorage {
|
|
|
2128
2172
|
}, error);
|
|
2129
2173
|
});
|
|
2130
2174
|
}
|
|
2131
|
-
|
|
2175
|
+
/**
|
|
2176
|
+
* Fetches the messages named by `include` together with their surrounding context.
|
|
2177
|
+
*
|
|
2178
|
+
* @param include - Message ids to pin, each with an optional before/after window.
|
|
2179
|
+
* @param resourceId - When set, restricts both the pinned messages and their context
|
|
2180
|
+
* to that resource so an id from another resource returns nothing.
|
|
2181
|
+
*/
|
|
2182
|
+
async _getIncludedMessages({ include, resourceId }) {
|
|
2132
2183
|
if (!include || include.length === 0) return null;
|
|
2133
2184
|
const unionQueries = [];
|
|
2134
2185
|
const params = [];
|
|
@@ -2139,17 +2190,18 @@ var MemoryDSQL = class MemoryDSQL extends MemoryStorage {
|
|
|
2139
2190
|
});
|
|
2140
2191
|
for (const inc of include) {
|
|
2141
2192
|
const { id, withPreviousMessages = 0, withNextMessages = 0 } = inc;
|
|
2193
|
+
const resourceCondition = resourceId ? ` AND "resourceId" = $${paramIdx + 3}` : "";
|
|
2142
2194
|
unionQueries.push(`
|
|
2143
2195
|
SELECT * FROM (
|
|
2144
2196
|
WITH target_thread AS (
|
|
2145
|
-
SELECT thread_id FROM ${tableName} WHERE id = $${paramIdx}
|
|
2197
|
+
SELECT thread_id FROM ${tableName} WHERE id = $${paramIdx}${resourceCondition}
|
|
2146
2198
|
),
|
|
2147
2199
|
ordered_messages AS (
|
|
2148
2200
|
SELECT
|
|
2149
2201
|
*,
|
|
2150
2202
|
ROW_NUMBER() OVER (ORDER BY "createdAt" ASC) as row_num
|
|
2151
2203
|
FROM ${tableName}
|
|
2152
|
-
WHERE thread_id = (SELECT thread_id FROM target_thread)
|
|
2204
|
+
WHERE thread_id = (SELECT thread_id FROM target_thread)${resourceCondition}
|
|
2153
2205
|
)
|
|
2154
2206
|
SELECT
|
|
2155
2207
|
m.id,
|
|
@@ -2175,6 +2227,10 @@ var MemoryDSQL = class MemoryDSQL extends MemoryStorage {
|
|
|
2175
2227
|
`);
|
|
2176
2228
|
params.push(id, withPreviousMessages, withNextMessages);
|
|
2177
2229
|
paramIdx += 3;
|
|
2230
|
+
if (resourceId) {
|
|
2231
|
+
params.push(resourceId);
|
|
2232
|
+
paramIdx += 1;
|
|
2233
|
+
}
|
|
2178
2234
|
}
|
|
2179
2235
|
const finalQuery = unionQueries.join(" UNION ALL ") + " ORDER BY \"createdAt\" ASC";
|
|
2180
2236
|
const includedRows = await this.#db.client.manyOrNone(finalQuery, params);
|
|
@@ -2224,7 +2280,7 @@ var MemoryDSQL = class MemoryDSQL extends MemoryStorage {
|
|
|
2224
2280
|
}, error);
|
|
2225
2281
|
this.logger?.error?.(mastraError.toString());
|
|
2226
2282
|
this.logger?.trackException(mastraError);
|
|
2227
|
-
|
|
2283
|
+
throw mastraError;
|
|
2228
2284
|
}
|
|
2229
2285
|
}
|
|
2230
2286
|
async listMessages(args) {
|
|
@@ -2300,7 +2356,10 @@ var MemoryDSQL = class MemoryDSQL extends MemoryStorage {
|
|
|
2300
2356
|
};
|
|
2301
2357
|
const messageIds = new Set(messages.map((m) => m.id));
|
|
2302
2358
|
if (include && include.length > 0) {
|
|
2303
|
-
const includeMessages = await this._getIncludedMessages({
|
|
2359
|
+
const includeMessages = await this._getIncludedMessages({
|
|
2360
|
+
include,
|
|
2361
|
+
resourceId
|
|
2362
|
+
});
|
|
2304
2363
|
if (includeMessages) {
|
|
2305
2364
|
for (const includeMsg of includeMessages) if (!messageIds.has(includeMsg.id)) {
|
|
2306
2365
|
messages.push(includeMsg);
|
|
@@ -2331,6 +2390,7 @@ var MemoryDSQL = class MemoryDSQL extends MemoryStorage {
|
|
|
2331
2390
|
hasMore
|
|
2332
2391
|
};
|
|
2333
2392
|
} catch (error) {
|
|
2393
|
+
if (error instanceof MastraError && error.category === ErrorCategory.USER) throw error;
|
|
2334
2394
|
const mastraError = new MastraError({
|
|
2335
2395
|
id: createStorageErrorId("DSQL", "LIST_MESSAGES", "FAILED"),
|
|
2336
2396
|
domain: ErrorDomain.STORAGE,
|
|
@@ -2342,13 +2402,7 @@ var MemoryDSQL = class MemoryDSQL extends MemoryStorage {
|
|
|
2342
2402
|
}, error);
|
|
2343
2403
|
this.logger?.error?.(mastraError.toString());
|
|
2344
2404
|
this.logger?.trackException(mastraError);
|
|
2345
|
-
|
|
2346
|
-
messages: [],
|
|
2347
|
-
total: 0,
|
|
2348
|
-
page,
|
|
2349
|
-
perPage: perPageForResponse,
|
|
2350
|
-
hasMore: false
|
|
2351
|
-
};
|
|
2405
|
+
throw mastraError;
|
|
2352
2406
|
}
|
|
2353
2407
|
}
|
|
2354
2408
|
async saveMessages({ messages }) {
|