diff --git a/src/drivers/redis.ts b/src/drivers/redis.ts index 8d00fa116..132bc7734 100644 --- a/src/drivers/redis.ts +++ b/src/drivers/redis.ts @@ -122,6 +122,31 @@ const driver: DriverFactory = (opts) => { await getRedisClient().set(p(key), value); } }, + async setItems(items, commonOptions) { + const defaultTtl = commonOptions?.ttl ?? opts.ttl; + // `MSET` cannot set a per-key TTL, so fall back to a pipeline of + // `SET ... EX` (mirroring `setItem`) whenever a TTL applies; otherwise + // use a single `MSET` for efficiency. + const hasTtl = defaultTtl || items.some((item) => item.options?.ttl); + if (hasTtl) { + const pipeline = getRedisClient().pipeline(); + for (const item of items) { + const ttl = item.options?.ttl ?? defaultTtl; + if (ttl) { + pipeline.set(p(item.key), item.value, "EX", ttl); + } else { + pipeline.set(p(item.key), item.value); + } + } + await pipeline.exec(); + } else { + const args: string[] = []; + for (const item of items) { + args.push(p(item.key), item.value); + } + await getRedisClient().mset(...args); + } + }, async setItemRaw(key, value, tOptions) { const _value = normalizeValue(value); const ttl = tOptions?.ttl ?? opts.ttl; diff --git a/test/drivers/redis.test.ts b/test/drivers/redis.test.ts index 295f2c85d..26e6d5f0f 100644 --- a/test/drivers/redis.test.ts +++ b/test/drivers/redis.test.ts @@ -39,6 +39,24 @@ describe("drivers: redis", () => { await client.disconnect(); }); + + it("setItems with ttl sets each key with an expiry", async () => { + await ctx.storage.setItems( + [ + { key: "s6:a", value: "a" }, + { key: "s6:b", value: "b" }, + ], + { ttl: 1000 }, + ); + + const client = new (ioredisMock as any).default("ioredis://localhost:6379/0"); + + expect(await client.get("test:s6:a")).toBe("a"); + expect(await client.get("test:s6:b")).toBe("b"); + expect(await client.ttl("test:s6:a")).toBeGreaterThan(0); + + await client.disconnect(); + }); }, }); });