Skip to content

Commit

Permalink
Fix: Redis race conditions with .set, .delete. and .clear when useRed…
Browse files Browse the repository at this point in the history
…isSets=true
  • Loading branch information
ryanrobertsname committed Jul 23, 2023
1 parent 1524a04 commit 08c68fc
Showing 1 changed file with 29 additions and 9 deletions.
38 changes: 29 additions & 9 deletions packages/redis/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,22 +73,37 @@ class KeyvRedis<Value = any> extends EventEmitter {

key = this._getKeyName(key);

if (typeof ttl === 'number') {
await this.redis.set(key, value, 'PX', ttl);
} else {
await this.redis.set(key, value);
}
const set = async (redis: any) => {
if (typeof ttl === 'number') {
await redis.set(key, value, 'PX', ttl);
} else {
await redis.set(key, value);
}
};

if (this.opts.useRedisSets) {
await this.redis.sadd(this._getNamespace(), key);
const trx = await this.redis.multi();
await set(trx);
await trx.sadd(this._getNamespace(), key);
await trx.exec();
} else {
await set(this.redis);
}
}

async delete(key: string): DeleteOutput {
key = this._getKeyName(key);
const items: number = await this.redis.del(key);
let items = 0;
const del = async (redis: any) => redis.del(key);

if (this.opts.useRedisSets) {
await this.redis.srem(this._getNamespace(), key);
const trx = this.redis.multi();
await del(trx);
await trx.srem(this._getNamespace(), key);
const r = await trx.exec();
items = r[0][1];
} else {
items = await del(this.redis);

Check warning on line 106 in packages/redis/src/index.ts

View check run for this annotation

Codecov / codecov/patch

packages/redis/src/index.ts#L106

Added line #L106 was not covered by tests
}

return items > 0;
Expand All @@ -104,7 +119,12 @@ class KeyvRedis<Value = any> extends EventEmitter {
async clear(): ClearOutput {
if (this.opts.useRedisSets) {
const keys: string[] = await this.redis.smembers(this._getNamespace());
await this.redis.del([...keys, this._getNamespace()]);
if (keys.length > 0) {
await Promise.all([
this.redis.del([...keys]),
this.redis.srem(this._getNamespace(), [...keys]),
]);
}
} else {
const pattern = 'sets:*';
const keys: string[] = await this.redis.keys(pattern);
Expand Down

0 comments on commit 08c68fc

Please sign in to comment.