diff --git a/src/redis.ts b/src/redis.ts index bb8e7bf..111013e 100644 --- a/src/redis.ts +++ b/src/redis.ts @@ -3,7 +3,7 @@ import { RedisClientType, RedisDefaultModules, RedisFunctions, - RedisModules, RedisScripts + RedisModules, RedisScripts, WatchError } from 'redis'; import {Milliseconds, RedisStore, TConfig, TMset} from './types'; import {ScanReply} from '@redis/client/dist/lib/commands/SCAN'; @@ -110,6 +110,16 @@ class buildRedisStoreWithConfig implements RedisStore { return await this.redisCache.scan(cursor, { MATCH: pattern, COUNT: count }); } + public async atomicGetAndSet(key: string, func: (val: any) => any): Promise { + await this.redisCache.watch(key); + const val = await this.redisCache.get(key); + return await this.redisCache.multi().set(key, func(val)).exec(); + } + + public async flushAll() { + await this.redisCache.flushAll(); + } + public getClient(): RedisClientType { return this.redisCache; } diff --git a/src/types/RedisStore.interface.ts b/src/types/RedisStore.interface.ts index c7bb025..9277109 100644 --- a/src/types/RedisStore.interface.ts +++ b/src/types/RedisStore.interface.ts @@ -8,4 +8,9 @@ export interface RedisStore extends Store { getClient(): RedisClientType; scan(pattern: string, cursor? :number, count?: number): Promise; + + atomicGetAndSet(key: string, updateFunction: (val: any) => any): Promise; + + flushAll(): Promise + } diff --git a/test/redis.test.ts b/test/redis.test.ts index f62e546..5d77cde 100644 --- a/test/redis.test.ts +++ b/test/redis.test.ts @@ -1,6 +1,6 @@ -import {redisStore} from '../src'; -import {RedisStore} from "../src/types"; -import {describe, beforeEach, it, expect} from "vitest"; +import { redisStore } from '../src'; +import { RedisStore } from "../src/types"; +import { describe, beforeEach, it, expect, afterEach } from "vitest"; let redisClient: RedisStore const config = { @@ -12,10 +12,16 @@ const config = { db: 0, ttl: 1000 * 60, }; + beforeEach(async () => { redisClient = await redisStore(config); await redisClient.reset(); }); + +afterEach(async () => { + await redisClient.flushAll() +}); + describe('Redis Store', () => { it('should set and get a value', async () => { @@ -80,7 +86,7 @@ describe('Redis Store', () => { expect(retrievedTtl).toBeLessThanOrEqual(ttl / 1000); // Redis returns TTL in seconds }); - it(`should return scan result by pattern`, async () => { + it('should return scan result by pattern', async () => { const key1 = 'ttl:a:b'; const key2 = 'ttl1:a:b'; const key3 = 'ttl:a:b1'; @@ -106,4 +112,17 @@ describe('Redis Store', () => { expect(thirdScanWithCount.keys).toEqual([]); expect(thirdScanWithCount.cursor).equal(0); }); + + it('should inc value by one', async () => { + await redisClient.set('test', { a: 1 }); + const res = await redisClient.atomicGetAndSet('test', (obj) => { + const parsedVal = JSON.parse(obj); + parsedVal.a = parsedVal.a + 1; + return JSON.stringify(parsedVal); + }); + const newVal = await redisClient.get('test') + expect(newVal).to.deep.equal({ a: 2 }); + expect(res[0]).to.deep.equal("OK"); + }) + });