@mastra/pg 1.17.0 → 1.17.1-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,16 @@
1
1
  # @mastra/pg
2
2
 
3
+ ## 1.17.1-alpha.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Improved Factory work-item concurrency by replacing distributed advisory locks with atomic claims, idempotent replay, and serializable relationship transactions. ([#20135](https://github.com/mastra-ai/mastra/pull/20135))
8
+
9
+ - Hardened distributed lock cleanup so clients are destroyed when transaction rollback fails. ([#20135](https://github.com/mastra-ai/mastra/pull/20135))
10
+
11
+ - Updated dependencies [[`73839cb`](https://github.com/mastra-ai/mastra/commit/73839cb58322679c170627d1015669ede5f619aa), [`8e4dc79`](https://github.com/mastra-ai/mastra/commit/8e4dc793dcf035ea506f9ce79f56d2d501a4be14), [`2db93cc`](https://github.com/mastra-ai/mastra/commit/2db93ccd0b872e4de7853a93383efe0647901df8), [`094ab61`](https://github.com/mastra-ai/mastra/commit/094ab6129a1a3ecf6eeb86decac17d5faea4e02a), [`fe80944`](https://github.com/mastra-ai/mastra/commit/fe80944f3ef6681fea6eae8200fce387b7bb3c2f), [`e51e166`](https://github.com/mastra-ai/mastra/commit/e51e166c52e220abc9b64554ce37359dca8544b1)]:
12
+ - @mastra/core@1.53.0-alpha.4
13
+
3
14
  ## 1.17.0
4
15
 
5
16
  ### 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.17.0"
6
+ version: "1.17.1-alpha.0"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.17.0",
2
+ "version": "1.17.1-alpha.0",
3
3
  "package": "@mastra/pg",
4
4
  "exports": {},
5
5
  "modules": {}
@@ -47,7 +47,7 @@ export const agent = new Agent({
47
47
 
48
48
  **options.observationalMemory** (`boolean | ObservationalMemoryOptions`): Enable Observational Memory for long-context agentic memory. Set to true for defaults, or pass a config object to customize token budgets, models, and scope. See Observational Memory reference for configuration details.
49
49
 
50
- **options.generateTitle** (`boolean | { model: DynamicArgument<MastraLanguageModel>; instructions?: DynamicArgument<string> }`): Controls automatic thread title generation from the user's first message. Can be a boolean or an object with custom model and instructions.
50
+ **options.generateTitle** (`boolean | { model: DynamicArgument<MastraLanguageModel>; instructions?: DynamicArgument<string> }`): Controls automatic thread title generation from the conversation transcript. Can be a boolean or an object with custom model and instructions.
51
51
 
52
52
  ## Returns
53
53
 
package/dist/index.cjs CHANGED
@@ -20250,10 +20250,6 @@ function serializeDefault(value) {
20250
20250
  if (typeof value === "string") return `'${value.replace(/'/g, "''")}'`;
20251
20251
  return String(value);
20252
20252
  }
20253
- function hashAdvisoryLockKey(key) {
20254
- const digest = crypto$1.createHash("sha256").update(key).digest();
20255
- return [digest.readInt32BE(0), digest.readInt32BE(4)];
20256
- }
20257
20253
  var PgFactoryStorageOps = class {
20258
20254
  #queryable;
20259
20255
  #transactionClient;
@@ -20548,21 +20544,36 @@ var PgFactoryStorage = class extends storage.FactoryStorage {
20548
20544
  async initStorage() {
20549
20545
  await this.#pool.query("SELECT 1");
20550
20546
  }
20551
- async withTransaction(fn) {
20552
- const client = await this.#pool.connect();
20553
- try {
20554
- await client.query("BEGIN");
20547
+ async withTransaction(fn, options) {
20548
+ const maxAttempts = options?.isolationLevel === "serializable" ? 3 : 1;
20549
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
20550
+ const client = await this.#pool.connect();
20551
+ let transactionOpen = false;
20552
+ let releaseError;
20555
20553
  try {
20554
+ await client.query(options?.isolationLevel === "serializable" ? "BEGIN ISOLATION LEVEL SERIALIZABLE" : "BEGIN");
20555
+ transactionOpen = true;
20556
20556
  const result = await fn(new PgFactoryStorageOps(client, this.#schemas, client));
20557
20557
  await client.query("COMMIT");
20558
+ transactionOpen = false;
20558
20559
  return result;
20559
20560
  } catch (error) {
20560
- await client.query("ROLLBACK");
20561
- throw error;
20561
+ if (transactionOpen) {
20562
+ try {
20563
+ await client.query("ROLLBACK");
20564
+ transactionOpen = false;
20565
+ } catch (rollbackError) {
20566
+ releaseError = rollbackError instanceof Error ? rollbackError : new Error(String(rollbackError));
20567
+ throw new AggregateError([error, rollbackError], "Factory transaction and rollback both failed");
20568
+ }
20569
+ }
20570
+ const serializationFailure = typeof error === "object" && error !== null && error.code === "40001";
20571
+ if (!serializationFailure || attempt === maxAttempts) throw error;
20572
+ } finally {
20573
+ client.release(releaseError);
20562
20574
  }
20563
- } finally {
20564
- client.release();
20565
20575
  }
20576
+ throw new Error("PgFactoryStorage: serializable transaction retry limit exceeded");
20566
20577
  }
20567
20578
  async ensureCollections(schemas) {
20568
20579
  for (const schema of schemas) {
@@ -20580,30 +20591,6 @@ var PgFactoryStorage = class extends storage.FactoryStorage {
20580
20591
  authDatabase() {
20581
20592
  return { dialect: "postgres", pool: this.#pool };
20582
20593
  }
20583
- /**
20584
- * Run `fn` while holding a Postgres transaction-scoped advisory lock for
20585
- * `key`, serializing callers across replicas. The lock releases when the
20586
- * transaction ends (commit, rollback, or connection loss), so a crashed
20587
- * replica can never hold it forever.
20588
- */
20589
- async withDistributedLock(key, fn) {
20590
- const [k1, k2] = hashAdvisoryLockKey(key);
20591
- const client = await this.#pool.connect();
20592
- try {
20593
- await client.query("BEGIN");
20594
- await client.query("SELECT pg_advisory_xact_lock($1, $2)", [k1, k2]);
20595
- try {
20596
- const result = await fn();
20597
- await client.query("COMMIT");
20598
- return result;
20599
- } catch (error) {
20600
- await client.query("ROLLBACK");
20601
- throw error;
20602
- }
20603
- } finally {
20604
- client.release();
20605
- }
20606
- }
20607
20594
  #columnDdl(name, spec) {
20608
20595
  assertIdentifier("column", name);
20609
20596
  let ddl = `"${name}" ${COLUMN_DDL[spec.type]}`;
@@ -21067,6 +21054,5 @@ exports.ToolProviderConnectionsPG = ToolProviderConnectionsPG;
21067
21054
  exports.WorkflowsPG = WorkflowsPG;
21068
21055
  exports.WorkspacesPG = WorkspacesPG;
21069
21056
  exports.exportSchemas = exportSchemas;
21070
- exports.hashAdvisoryLockKey = hashAdvisoryLockKey;
21071
21057
  //# sourceMappingURL=index.cjs.map
21072
21058
  //# sourceMappingURL=index.cjs.map