@mastra/redis 1.4.3 → 1.4.4-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/cache.d.ts +35 -2
- package/dist/cache.d.ts.map +1 -1
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/index.cjs +65 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +65 -3
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export * from './storage/index.js';
|
|
2
|
-
export { RedisServerCache, type RedisClient, type RedisServerCacheOptions, upstashPreset, nodeRedisPreset, } from './cache.js';
|
|
2
|
+
export { RedisServerCache, type RedisClient, type RedisServerCacheOptions, upstashPreset, nodeRedisPreset, LIST_PUSH_INDEXED_SCRIPT, } from './cache.js';
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,WAAW,CAAC;AAG1B,OAAO,EACL,gBAAgB,EAChB,KAAK,WAAW,EAChB,KAAK,uBAAuB,EAC5B,aAAa,EACb,eAAe,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,WAAW,CAAC;AAG1B,OAAO,EACL,gBAAgB,EAChB,KAAK,WAAW,EAChB,KAAK,uBAAuB,EAC5B,aAAa,EACb,eAAe,EACf,wBAAwB,GACzB,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1596,6 +1596,38 @@ const defaultPushToList = (client, key, value) => {
|
|
|
1596
1596
|
const defaultGetListRange = (client, key, start, stop) => {
|
|
1597
1597
|
return client.lrange(key, start, stop);
|
|
1598
1598
|
};
|
|
1599
|
+
const defaultEvalScript = (client, script, keys, args) => {
|
|
1600
|
+
return client.eval(script, keys.length, ...keys, ...args);
|
|
1601
|
+
};
|
|
1602
|
+
/**
|
|
1603
|
+
* Atomic "allocate index + append + refresh TTLs" used by `listPushIndexed`.
|
|
1604
|
+
*
|
|
1605
|
+
* KEYS[1] = list key, KEYS[2] = counter key
|
|
1606
|
+
* ARGV[1] = JSON-serialized object WITHOUT an `index` property
|
|
1607
|
+
* ARGV[2] = TTL in seconds (0 = no expiry)
|
|
1608
|
+
*
|
|
1609
|
+
* The index is spliced into the JSON text as the first property rather than
|
|
1610
|
+
* decoded/re-encoded with cjson, which would silently alter large integers
|
|
1611
|
+
* and sparse arrays. `JSON.stringify` of an object always starts with `{`,
|
|
1612
|
+
* so `{...}` → `{"index":N,...}` and `{}` → `{"index":N}`.
|
|
1613
|
+
*/
|
|
1614
|
+
const LIST_PUSH_INDEXED_SCRIPT = `
|
|
1615
|
+
local i = redis.call('INCR', KEYS[2]) - 1
|
|
1616
|
+
local body = ARGV[1]
|
|
1617
|
+
local doc
|
|
1618
|
+
if #body <= 2 then
|
|
1619
|
+
doc = '{"index":' .. i .. '}'
|
|
1620
|
+
else
|
|
1621
|
+
doc = '{"index":' .. i .. ',' .. string.sub(body, 2)
|
|
1622
|
+
end
|
|
1623
|
+
redis.call('RPUSH', KEYS[1], doc)
|
|
1624
|
+
local ttl = tonumber(ARGV[2])
|
|
1625
|
+
if ttl > 0 then
|
|
1626
|
+
redis.call('EXPIRE', KEYS[1], ttl)
|
|
1627
|
+
redis.call('EXPIRE', KEYS[2], ttl)
|
|
1628
|
+
end
|
|
1629
|
+
return i
|
|
1630
|
+
`.trim();
|
|
1599
1631
|
var RedisServerCache = class extends MastraServerCache {
|
|
1600
1632
|
client;
|
|
1601
1633
|
keyPrefix;
|
|
@@ -1605,6 +1637,9 @@ var RedisServerCache = class extends MastraServerCache {
|
|
|
1605
1637
|
getListLength;
|
|
1606
1638
|
pushToList;
|
|
1607
1639
|
getListRange;
|
|
1640
|
+
evalScript;
|
|
1641
|
+
/** Set once scripting is known to be unusable (no `eval`, or Cluster CROSSSLOT). */
|
|
1642
|
+
scriptingDisabled;
|
|
1608
1643
|
constructor(config, options = {}) {
|
|
1609
1644
|
super({ name: "RedisServerCache" });
|
|
1610
1645
|
this.client = config.client;
|
|
@@ -1615,6 +1650,8 @@ var RedisServerCache = class extends MastraServerCache {
|
|
|
1615
1650
|
this.getListLength = options.getListLength ?? defaultGetListLength;
|
|
1616
1651
|
this.pushToList = options.pushToList ?? defaultPushToList;
|
|
1617
1652
|
this.getListRange = options.getListRange ?? defaultGetListRange;
|
|
1653
|
+
this.evalScript = options.evalScript ?? defaultEvalScript;
|
|
1654
|
+
this.scriptingDisabled = typeof this.client.eval !== "function";
|
|
1618
1655
|
}
|
|
1619
1656
|
getKey(key) {
|
|
1620
1657
|
return `${this.keyPrefix}${key}`;
|
|
@@ -1676,13 +1713,34 @@ var RedisServerCache = class extends MastraServerCache {
|
|
|
1676
1713
|
if (this.ttlSeconds > 0) await this.client.expire(fullKey, this.ttlSeconds);
|
|
1677
1714
|
return value;
|
|
1678
1715
|
}
|
|
1716
|
+
/**
|
|
1717
|
+
* Single round-trip index allocation + list append + TTL refresh via Lua.
|
|
1718
|
+
* This is the durable stream per-chunk hot path (issue #22477): the composed
|
|
1719
|
+
* default costs four awaited commands (INCR, EXPIRE, RPUSH, EXPIRE).
|
|
1720
|
+
*/
|
|
1721
|
+
async listPushIndexed(listKey, counterKey, value) {
|
|
1722
|
+
if (this.scriptingDisabled) return super.listPushIndexed(listKey, counterKey, value);
|
|
1723
|
+
const { index: _ignored, ...body } = value;
|
|
1724
|
+
try {
|
|
1725
|
+
const result = await this.evalScript(this.client, LIST_PUSH_INDEXED_SCRIPT, [this.getKey(listKey), this.getKey(counterKey)], [this.serialize(body), String(this.ttlSeconds)]);
|
|
1726
|
+
return Number(result);
|
|
1727
|
+
} catch (error) {
|
|
1728
|
+
if (error instanceof Error && error.message.includes("CROSSSLOT")) {
|
|
1729
|
+
this.scriptingDisabled = true;
|
|
1730
|
+
this.logger.warn("[RedisServerCache] listPushIndexed script rejected with CROSSSLOT; falling back to increment + listPush");
|
|
1731
|
+
return super.listPushIndexed(listKey, counterKey, value);
|
|
1732
|
+
}
|
|
1733
|
+
throw error;
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1679
1736
|
};
|
|
1680
1737
|
const upstashPreset = {
|
|
1681
1738
|
setWithExpiry: (client, key, value, seconds) => client.set(key, value, { ex: seconds }),
|
|
1682
1739
|
scanKeys: (client, cursor, pattern, count) => client.scan(cursor, {
|
|
1683
1740
|
match: pattern,
|
|
1684
1741
|
count
|
|
1685
|
-
})
|
|
1742
|
+
}),
|
|
1743
|
+
evalScript: (client, script, keys, args) => client.eval(script, keys, args)
|
|
1686
1744
|
};
|
|
1687
1745
|
const nodeRedisPreset = {
|
|
1688
1746
|
setWithExpiry: (client, key, value, seconds) => client.set(key, value, { EX: seconds }),
|
|
@@ -1692,9 +1750,13 @@ const nodeRedisPreset = {
|
|
|
1692
1750
|
}),
|
|
1693
1751
|
getListLength: (client, key) => client.lLen(key),
|
|
1694
1752
|
pushToList: (client, key, value) => client.rPush(key, value),
|
|
1695
|
-
getListRange: (client, key, start, stop) => client.lRange(key, start, stop)
|
|
1753
|
+
getListRange: (client, key, start, stop) => client.lRange(key, start, stop),
|
|
1754
|
+
evalScript: (client, script, keys, args) => client.eval(script, {
|
|
1755
|
+
keys,
|
|
1756
|
+
arguments: args
|
|
1757
|
+
})
|
|
1696
1758
|
};
|
|
1697
1759
|
//#endregion
|
|
1698
|
-
export { RedisServerCache, RedisStore, ScoresRedis, StoreMemoryRedis, WorkflowsRedis, nodeRedisPreset, upstashPreset };
|
|
1760
|
+
export { LIST_PUSH_INDEXED_SCRIPT, RedisServerCache, RedisStore, ScoresRedis, StoreMemoryRedis, WorkflowsRedis, nodeRedisPreset, upstashPreset };
|
|
1699
1761
|
|
|
1700
1762
|
//# sourceMappingURL=index.js.map
|