@mastra/upstash 1.2.1-alpha.0 → 1.2.1-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/upstash
2
2
 
3
+ ## 1.2.1-alpha.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Fixed workflow runs preserving their original creation time when re-persisted in Upstash storage, including concurrent saves. ([#18004](https://github.com/mastra-ai/mastra/pull/18004))
8
+
9
+ - Updated dependencies [[`bf3fe49`](https://github.com/mastra-ai/mastra/commit/bf3fe49f9467dbbdb8f9eaf74e0f7971ffb19559), [`24ceaea`](https://github.com/mastra-ai/mastra/commit/24ceaea0bdd8609cabbab764380608ca6621a194), [`6ccf67b`](https://github.com/mastra-ai/mastra/commit/6ccf67bf075753754927a57bc2e1734ba2c820c5), [`825d8de`](https://github.com/mastra-ai/mastra/commit/825d8def9fa64c2bcc3d8dd6b49e09342c3ac5c7), [`ffa09e7`](https://github.com/mastra-ai/mastra/commit/ffa09e772a5c92270eabe2090fc42d45bd8ec4b7), [`461a7c5`](https://github.com/mastra-ai/mastra/commit/461a7c501449295287f4f0ee4b0b42344f39fcf8), [`4211472`](https://github.com/mastra-ai/mastra/commit/4211472a5a2bd319c60cd2e42d9109c3eef7ac1c), [`9e45902`](https://github.com/mastra-ai/mastra/commit/9e4590208e745055cecca202e2db0e5c65e17d3c), [`5c0df77`](https://github.com/mastra-ai/mastra/commit/5c0df776c40efa420f8c07a2f3ee66010296618e)]:
10
+ - @mastra/core@1.47.0-alpha.3
11
+
3
12
  ## 1.2.1-alpha.0
4
13
 
5
14
  ### Patch Changes
@@ -3,7 +3,7 @@ name: mastra-upstash
3
3
  description: Documentation for @mastra/upstash. Use when working with @mastra/upstash APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/upstash"
6
- version: "1.2.1-alpha.0"
6
+ version: "1.2.1-alpha.1"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.2.1-alpha.0",
2
+ "version": "1.2.1-alpha.1",
3
3
  "package": "@mastra/upstash",
4
4
  "exports": {
5
5
  "RedisServerCache": {
package/dist/index.cjs CHANGED
@@ -1765,6 +1765,36 @@ var WorkflowsUpstash = class extends storage.WorkflowsStorage {
1765
1765
  async dangerouslyClearAll() {
1766
1766
  await this.#db.deleteData({ tableName: storage.TABLE_WORKFLOW_SNAPSHOT });
1767
1767
  }
1768
+ async getWorkflowRunRecord({
1769
+ namespace,
1770
+ runId,
1771
+ resourceId,
1772
+ workflowName
1773
+ }) {
1774
+ if (workflowName) {
1775
+ const keyVariants = [
1776
+ ...resourceId ? [{ namespace, workflow_name: workflowName, run_id: runId, resourceId }] : [],
1777
+ { namespace, workflow_name: workflowName, run_id: runId }
1778
+ ];
1779
+ for (const keys2 of keyVariants) {
1780
+ const data = await this.#db.get({
1781
+ tableName: storage.TABLE_WORKFLOW_SNAPSHOT,
1782
+ keys: keys2
1783
+ });
1784
+ if (data) return data;
1785
+ }
1786
+ }
1787
+ const key = `${getKey(storage.TABLE_WORKFLOW_SNAPSHOT, { namespace })}:*run_id:${runId}*`;
1788
+ const keys = await this.#db.scanKeys(key);
1789
+ const workflows = await Promise.all(
1790
+ keys.map(async (key2) => {
1791
+ return this.client.get(key2);
1792
+ })
1793
+ );
1794
+ return workflows.find(
1795
+ (w) => w?.run_id === runId && (!workflowName || w.workflow_name === workflowName) && (!resourceId || w.resourceId === resourceId)
1796
+ ) ?? null;
1797
+ }
1768
1798
  async updateWorkflowResults({
1769
1799
  workflowName,
1770
1800
  runId,
@@ -1968,18 +1998,38 @@ var WorkflowsUpstash = class extends storage.WorkflowsStorage {
1968
1998
  async persistWorkflowSnapshot(params) {
1969
1999
  const { namespace = "workflows", workflowName, runId, resourceId, snapshot, createdAt, updatedAt } = params;
1970
2000
  try {
1971
- await this.#db.insert({
1972
- tableName: storage.TABLE_WORKFLOW_SNAPSHOT,
1973
- record: {
1974
- namespace,
1975
- workflow_name: workflowName,
1976
- run_id: runId,
1977
- resourceId,
1978
- snapshot,
1979
- createdAt: createdAt ?? /* @__PURE__ */ new Date(),
1980
- updatedAt: updatedAt ?? /* @__PURE__ */ new Date()
1981
- }
2001
+ const now = /* @__PURE__ */ new Date();
2002
+ const key = getKey(storage.TABLE_WORKFLOW_SNAPSHOT, {
2003
+ namespace,
2004
+ workflow_name: workflowName,
2005
+ run_id: runId,
2006
+ ...resourceId ? { resourceId } : {}
1982
2007
  });
2008
+ const record = {
2009
+ namespace,
2010
+ workflow_name: workflowName,
2011
+ run_id: runId,
2012
+ resourceId,
2013
+ snapshot,
2014
+ createdAt: (createdAt ?? now).toISOString(),
2015
+ updatedAt: (updatedAt ?? now).toISOString()
2016
+ };
2017
+ await this.client.eval(
2018
+ `
2019
+ local existing = redis.call("GET", KEYS[1])
2020
+ local next = cjson.decode(ARGV[1])
2021
+ if existing then
2022
+ local current = cjson.decode(existing)
2023
+ if current["createdAt"] then
2024
+ next["createdAt"] = current["createdAt"]
2025
+ end
2026
+ end
2027
+ redis.call("SET", KEYS[1], cjson.encode(next))
2028
+ return 1
2029
+ `,
2030
+ [key],
2031
+ [JSON.stringify(record)]
2032
+ );
1983
2033
  } catch (error$1) {
1984
2034
  throw new error.MastraError(
1985
2035
  {
@@ -1998,15 +2048,10 @@ var WorkflowsUpstash = class extends storage.WorkflowsStorage {
1998
2048
  }
1999
2049
  async loadWorkflowSnapshot(params) {
2000
2050
  const { namespace = "workflows", workflowName, runId } = params;
2001
- const key = getKey(storage.TABLE_WORKFLOW_SNAPSHOT, {
2002
- namespace,
2003
- workflow_name: workflowName,
2004
- run_id: runId
2005
- });
2006
2051
  try {
2007
- const data = await this.client.get(key);
2052
+ const data = await this.getWorkflowRunRecord({ namespace, runId, workflowName });
2008
2053
  if (!data) return null;
2009
- return data.snapshot;
2054
+ return typeof data.snapshot === "string" ? JSON.parse(data.snapshot) : data.snapshot;
2010
2055
  } catch (error$1) {
2011
2056
  throw new error.MastraError(
2012
2057
  {
@@ -2028,15 +2073,7 @@ var WorkflowsUpstash = class extends storage.WorkflowsStorage {
2028
2073
  workflowName
2029
2074
  }) {
2030
2075
  try {
2031
- const key = getKey(storage.TABLE_WORKFLOW_SNAPSHOT, { namespace: "workflows", workflow_name: workflowName, run_id: runId }) + "*";
2032
- const keys = await this.#db.scanKeys(key);
2033
- const workflows = await Promise.all(
2034
- keys.map(async (key2) => {
2035
- const data2 = await this.client.get(key2);
2036
- return data2;
2037
- })
2038
- );
2039
- const data = workflows.find((w) => w?.run_id === runId && w?.workflow_name === workflowName);
2076
+ const data = await this.getWorkflowRunRecord({ namespace: "workflows", runId, workflowName });
2040
2077
  if (!data) return null;
2041
2078
  return this.parseWorkflowRun(data);
2042
2079
  } catch (error$1) {
@@ -2056,8 +2093,14 @@ var WorkflowsUpstash = class extends storage.WorkflowsStorage {
2056
2093
  }
2057
2094
  }
2058
2095
  async deleteWorkflowRunById({ runId, workflowName }) {
2059
- const key = getKey(storage.TABLE_WORKFLOW_SNAPSHOT, { namespace: "workflows", workflow_name: workflowName, run_id: runId });
2060
2096
  try {
2097
+ const record = await this.getWorkflowRunRecord({ namespace: "workflows", runId, workflowName });
2098
+ const key = getKey(storage.TABLE_WORKFLOW_SNAPSHOT, {
2099
+ namespace: "workflows",
2100
+ workflow_name: workflowName,
2101
+ run_id: runId,
2102
+ ...record?.resourceId ? { resourceId: record.resourceId } : {}
2103
+ });
2061
2104
  await this.client.del(key);
2062
2105
  } catch (error$1) {
2063
2106
  throw new error.MastraError(
@@ -2096,24 +2139,7 @@ var WorkflowsUpstash = class extends storage.WorkflowsStorage {
2096
2139
  new Error("page must be >= 0")
2097
2140
  );
2098
2141
  }
2099
- let pattern = getKey(storage.TABLE_WORKFLOW_SNAPSHOT, { namespace: "workflows" }) + ":*";
2100
- if (workflowName && resourceId) {
2101
- pattern = getKey(storage.TABLE_WORKFLOW_SNAPSHOT, {
2102
- namespace: "workflows",
2103
- workflow_name: workflowName,
2104
- run_id: "*",
2105
- resourceId
2106
- });
2107
- } else if (workflowName) {
2108
- pattern = getKey(storage.TABLE_WORKFLOW_SNAPSHOT, { namespace: "workflows", workflow_name: workflowName }) + ":*";
2109
- } else if (resourceId) {
2110
- pattern = getKey(storage.TABLE_WORKFLOW_SNAPSHOT, {
2111
- namespace: "workflows",
2112
- workflow_name: "*",
2113
- run_id: "*",
2114
- resourceId
2115
- });
2116
- }
2142
+ const pattern = `${getKey(storage.TABLE_WORKFLOW_SNAPSHOT, { namespace: "workflows" })}:*`;
2117
2143
  const keys = await this.#db.scanKeys(pattern);
2118
2144
  if (keys.length === 0) {
2119
2145
  return { runs: [], total: 0 };
@@ -2123,7 +2149,7 @@ var WorkflowsUpstash = class extends storage.WorkflowsStorage {
2123
2149
  const results = await pipeline.exec();
2124
2150
  let runs = results.map((result) => result).filter(
2125
2151
  (record) => record !== null && record !== void 0 && typeof record === "object" && "workflow_name" in record
2126
- ).filter((record) => !workflowName || record.workflow_name === workflowName).map((w) => this.parseWorkflowRun(w)).filter((w) => {
2152
+ ).filter((record) => !workflowName || record.workflow_name === workflowName).filter((record) => !resourceId || record.resourceId === resourceId).map((w) => this.parseWorkflowRun(w)).filter((w) => {
2127
2153
  if (fromDate && w.createdAt < fromDate) return false;
2128
2154
  if (toDate && w.createdAt > toDate) return false;
2129
2155
  if (status) {