@mastra/pg 1.20.0-alpha.0 → 1.20.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 CHANGED
@@ -1,5 +1,14 @@
1
1
  # @mastra/pg
2
2
 
3
+ ## 1.20.0-alpha.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Improved chat response time with PostgresStore. Message history now reads a page of messages and its total count in one query instead of two. When semantic recall is on, the recall read also starts at the same time as the page read. Each agent turn therefore makes fewer database round-trips, which is most noticeable on remote Postgres. ([#20979](https://github.com/mastra-ai/mastra/pull/20979))
8
+
9
+ - Updated dependencies [[`cdd5c33`](https://github.com/mastra-ai/mastra/commit/cdd5c33ac6c7118a9f139e6dc0e14e6a8ae31658), [`d7cf7fa`](https://github.com/mastra-ai/mastra/commit/d7cf7fafc1ae1b50bd8462dd0e6c671a8606db93), [`0f9a448`](https://github.com/mastra-ai/mastra/commit/0f9a448502157e59f7b76f24360ad497168f5ef8), [`289f4ce`](https://github.com/mastra-ai/mastra/commit/289f4ce16e3293370440172132c52ee787cbc09f), [`4f16ff8`](https://github.com/mastra-ai/mastra/commit/4f16ff824bf2f9b0ddc93f210477c10c8a4fb1ab), [`1c67d85`](https://github.com/mastra-ai/mastra/commit/1c67d85e9da8285662f4dbbf47e0378c3fee0747), [`ba24be6`](https://github.com/mastra-ai/mastra/commit/ba24be662439c331ab23a600041f93803c89eca8), [`842b5fe`](https://github.com/mastra-ai/mastra/commit/842b5fe22b6a7fa811bd14e48eb9af523ac989f2), [`80bdf3a`](https://github.com/mastra-ai/mastra/commit/80bdf3ae16ade6ff63bde0cb16fa2df8ab7dd4dd), [`9ba1247`](https://github.com/mastra-ai/mastra/commit/9ba12470c77f1c03642d720ce67e517e878f666e), [`fd96298`](https://github.com/mastra-ai/mastra/commit/fd96298a8367622f4ebfcaa97b5b6c1fbbd14564), [`6a84954`](https://github.com/mastra-ai/mastra/commit/6a84954a2667f85b6d59da652dab1bbff007ccb0), [`52d8ef0`](https://github.com/mastra-ai/mastra/commit/52d8ef03801f1deb7ee48532fc4190dd4a33916c), [`cdd5c33`](https://github.com/mastra-ai/mastra/commit/cdd5c33ac6c7118a9f139e6dc0e14e6a8ae31658), [`efd5c81`](https://github.com/mastra-ai/mastra/commit/efd5c81cc25fde3c2ddd86fc1178deb4ec176e19), [`0976933`](https://github.com/mastra-ai/mastra/commit/0976933142333ec78451feef265b68bcb45aa5e7), [`242b945`](https://github.com/mastra-ai/mastra/commit/242b94558777bfbdeb42cbfea84afff0b6ad0633), [`fea5cae`](https://github.com/mastra-ai/mastra/commit/fea5caedc7e2cfea51784a15e015952692027abf), [`4b59f78`](https://github.com/mastra-ai/mastra/commit/4b59f786cbc9a7d1ef07a07517dbd4b96865e99d), [`7010c5d`](https://github.com/mastra-ai/mastra/commit/7010c5d15728bf9c5dfe4fb6b1bf80ce23bf143a)]:
10
+ - @mastra/core@1.58.0-alpha.3
11
+
3
12
  ## 1.20.0-alpha.0
4
13
 
5
14
  ### Minor Changes
@@ -3,7 +3,7 @@ name: mastra-pg
3
3
  description: Documentation for @mastra/pg. Use when working with @mastra/pg APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/pg"
6
- version: "1.20.0-alpha.0"
6
+ version: "1.20.0-alpha.1"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.20.0-alpha.0",
2
+ "version": "1.20.0-alpha.1",
3
3
  "package": "@mastra/pg",
4
4
  "exports": {},
5
5
  "modules": {}
@@ -251,6 +251,64 @@ const memoryStore = await storage.getStore('memory')
251
251
  const thread = await memoryStore?.getThreadById({ threadId: '...' })
252
252
  ```
253
253
 
254
+ ## Closing connections
255
+
256
+ `close()` releases the connections of the stores a composite was built from: the `default` and `editor` stores, plus any domain that owns its own client. Each store is closed once, even when it backs several domains. When passed to the Mastra class, `close()` is called by `shutdown()`:
257
+
258
+ ```typescript
259
+ import { MastraCompositeStore } from '@mastra/core/storage'
260
+ import { PostgresStore } from '@mastra/pg'
261
+ import { Mastra } from '@mastra/core'
262
+
263
+ const pgStore = new PostgresStore({
264
+ id: 'pg-storage',
265
+ connectionString: process.env.DATABASE_URL,
266
+ })
267
+
268
+ export const mastra = new Mastra({
269
+ storage: new MastraCompositeStore({ id: 'composite', default: pgStore }),
270
+ })
271
+
272
+ process.on('SIGTERM', async () => {
273
+ // Releases the Postgres pool, so the process can exit
274
+ await mastra.shutdown()
275
+ })
276
+ ```
277
+
278
+ A store you construct only to supply a domain isn't reachable through the composite. Keep a reference to it and close it yourself:
279
+
280
+ ```typescript
281
+ import { MastraCompositeStore } from '@mastra/core/storage'
282
+ import { ClickhouseStore } from '@mastra/clickhouse'
283
+ import { PostgresStore } from '@mastra/pg'
284
+ import { Mastra } from '@mastra/core'
285
+
286
+ const pgStore = new PostgresStore({
287
+ id: 'pg-storage',
288
+ connectionString: process.env.DATABASE_URL,
289
+ })
290
+
291
+ const clickhouseStore = new ClickhouseStore({
292
+ id: 'clickhouse-storage',
293
+ url: process.env.CLICKHOUSE_URL,
294
+ username: process.env.CLICKHOUSE_USERNAME,
295
+ password: process.env.CLICKHOUSE_PASSWORD,
296
+ })
297
+
298
+ export const mastra = new Mastra({
299
+ storage: new MastraCompositeStore({
300
+ id: 'composite',
301
+ default: pgStore,
302
+ domains: { observability: clickhouseStore.stores?.observability },
303
+ }),
304
+ })
305
+
306
+ process.on('SIGTERM', async () => {
307
+ await mastra.shutdown()
308
+ await clickhouseStore.close()
309
+ })
310
+ ```
311
+
254
312
  ## Use cases
255
313
 
256
314
  ### Separate databases for different workloads
package/dist/index.cjs CHANGED
@@ -9413,6 +9413,38 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
9413
9413
  throw mastraError;
9414
9414
  }
9415
9415
  }
9416
+ /**
9417
+ * Reads one page of messages together with the total row count.
9418
+ *
9419
+ * `COUNT(*) OVER ()` reports the count over the whole WHERE result on the same
9420
+ * statement as the page, so the page costs one database round-trip instead of
9421
+ * two. The page and the count also come from one snapshot, so the count always
9422
+ * describes the returned rows. A separate `COUNT(*)` runs only when the page is
9423
+ * empty and the caller asked for a page after the last row, because a window
9424
+ * function has no row to carry the count on.
9425
+ */
9426
+ async #fetchMessagePage({ selectStatement, tableName, whereClause, orderByStatement, queryParams, perPageInput, perPage, offset }) {
9427
+ const limitClause = perPageInput === false ? "" : ` LIMIT $${queryParams.length + 1} OFFSET $${queryParams.length + 2}`;
9428
+ const dataParams = perPageInput === false ? queryParams : [
9429
+ ...queryParams,
9430
+ perPage,
9431
+ offset
9432
+ ];
9433
+ const rows = await this.#db.client.manyOrNone(`${selectStatement}, COUNT(*) OVER () AS "__total" FROM ${tableName} ${whereClause} ${orderByStatement}${limitClause}`, dataParams) || [];
9434
+ if (rows.length > 0) return {
9435
+ total: Number(rows[0].__total),
9436
+ messages: rows
9437
+ };
9438
+ if (offset === 0) return {
9439
+ total: 0,
9440
+ messages: []
9441
+ };
9442
+ const countResult = await this.#db.client.one(`SELECT COUNT(*) FROM ${tableName} ${whereClause}`, queryParams);
9443
+ return {
9444
+ total: parseInt(countResult.count, 10),
9445
+ messages: []
9446
+ };
9447
+ }
9416
9448
  async listMessages(args) {
9417
9449
  const { threadId, resourceId, include, filter, perPage: perPageInput, page = 0, orderBy } = args;
9418
9450
  const threadIds = (Array.isArray(threadId) ? threadId : [threadId]).filter((id) => typeof id === "string");
@@ -9487,23 +9519,27 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
9487
9519
  hasMore: false
9488
9520
  };
9489
9521
  }
9522
+ let includeFailure;
9523
+ const includePromise = include && include.length > 0 ? this._getIncludedMessages({ include }).catch((error) => {
9524
+ includeFailure = error;
9525
+ return null;
9526
+ }) : null;
9490
9527
  let total;
9491
9528
  let messages;
9492
9529
  if (metadataFilter) {
9493
9530
  const filteredRows = (await this.#db.client.manyOrNone(`${selectStatement} FROM ${tableName} ${whereClause} ${orderByStatement}`, queryParams) || []).filter((row) => (0, _mastra_core_storage.storageMessageMatchesMetadataFilter)(row.content, metadataFilter));
9494
9531
  total = filteredRows.length;
9495
9532
  messages = perPageInput === false ? filteredRows : filteredRows.slice(offset, offset + perPage);
9496
- } else {
9497
- const countResult = await this.#db.client.one(`SELECT COUNT(*) FROM ${tableName} ${whereClause}`, queryParams);
9498
- total = parseInt(countResult.count, 10);
9499
- const limitValue = perPageInput === false ? total : perPage;
9500
- const dataQuery = `${selectStatement} FROM ${tableName} ${whereClause} ${orderByStatement} LIMIT $${paramIndex++} OFFSET $${paramIndex++}`;
9501
- messages = [...await this.#db.client.manyOrNone(dataQuery, [
9502
- ...queryParams,
9503
- limitValue,
9504
- offset
9505
- ]) || []];
9506
- }
9533
+ } else ({total, messages} = await this.#fetchMessagePage({
9534
+ selectStatement,
9535
+ tableName,
9536
+ whereClause,
9537
+ orderByStatement,
9538
+ queryParams,
9539
+ perPageInput,
9540
+ perPage,
9541
+ offset
9542
+ }));
9507
9543
  const primaryPageCount = messages.length;
9508
9544
  if (total === 0 && messages.length === 0 && (!include || include.length === 0)) return {
9509
9545
  messages: [],
@@ -9514,7 +9550,8 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
9514
9550
  };
9515
9551
  const messageIds = new Set(messages.map((m) => m.id));
9516
9552
  if (include && include.length > 0) {
9517
- const includeMessages = await this._getIncludedMessages({ include });
9553
+ const includeMessages = await includePromise;
9554
+ if (includeFailure) throw includeFailure;
9518
9555
  if (includeMessages) {
9519
9556
  for (const includeMsg of includeMessages) if (!messageIds.has(includeMsg.id)) {
9520
9557
  messages.push(includeMsg);
@@ -9622,23 +9659,27 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
9622
9659
  hasMore: false
9623
9660
  };
9624
9661
  }
9662
+ let includeFailure;
9663
+ const includePromise = include && include.length > 0 ? this._getIncludedMessages({ include }).catch((error) => {
9664
+ includeFailure = error;
9665
+ return null;
9666
+ }) : null;
9625
9667
  let total;
9626
9668
  let messages;
9627
9669
  if (metadataFilter) {
9628
9670
  const filteredRows = (await this.#db.client.manyOrNone(`${selectStatement} FROM ${tableName} ${whereClause} ${orderByStatement}`, queryParams) || []).filter((row) => (0, _mastra_core_storage.storageMessageMatchesMetadataFilter)(row.content, metadataFilter));
9629
9671
  total = filteredRows.length;
9630
9672
  messages = perPageInput === false ? filteredRows : filteredRows.slice(offset, offset + perPage);
9631
- } else {
9632
- const countResult = await this.#db.client.one(`SELECT COUNT(*) FROM ${tableName} ${whereClause}`, queryParams);
9633
- total = parseInt(countResult.count, 10);
9634
- const limitValue = perPageInput === false ? total : perPage;
9635
- const dataQuery = `${selectStatement} FROM ${tableName} ${whereClause} ${orderByStatement} LIMIT $${paramIndex++} OFFSET $${paramIndex++}`;
9636
- messages = [...await this.#db.client.manyOrNone(dataQuery, [
9637
- ...queryParams,
9638
- limitValue,
9639
- offset
9640
- ]) || []];
9641
- }
9673
+ } else ({total, messages} = await this.#fetchMessagePage({
9674
+ selectStatement,
9675
+ tableName,
9676
+ whereClause,
9677
+ orderByStatement,
9678
+ queryParams,
9679
+ perPageInput,
9680
+ perPage,
9681
+ offset
9682
+ }));
9642
9683
  if (total === 0 && messages.length === 0 && (!include || include.length === 0)) return {
9643
9684
  messages: [],
9644
9685
  total: 0,
@@ -9648,7 +9689,8 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
9648
9689
  };
9649
9690
  const messageIds = new Set(messages.map((m) => m.id));
9650
9691
  if (include && include.length > 0) {
9651
- const includeMessages = await this._getIncludedMessages({ include });
9692
+ const includeMessages = await includePromise;
9693
+ if (includeFailure) throw includeFailure;
9652
9694
  if (includeMessages) {
9653
9695
  for (const includeMsg of includeMessages) if (!messageIds.has(includeMsg.id)) {
9654
9696
  messages.push(includeMsg);