Skip to content

Commit

Permalink
enhance(redis): use SCAN instead of KEYS
Browse files Browse the repository at this point in the history
  • Loading branch information
ardatan committed Dec 12, 2024
1 parent 94a8bdd commit e58b4ac
Showing 3 changed files with 38 additions and 1 deletion.
6 changes: 6 additions & 0 deletions .changeset/shaggy-poets-bow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@graphql-mesh/cache-redis': patch
---

Use `SCAN` instead of `KEYS` to avoid the error `ERR KEYS command is disabled because total
number of keys is too large, please use SCAN`
15 changes: 14 additions & 1 deletion packages/cache/redis/src/index.ts
Original file line number Diff line number Diff line change
@@ -96,7 +96,7 @@ export default class RedisCache<V = string> implements KeyValueCache<V>, Disposa
}

getKeysByPrefix(prefix: string): Promise<string[]> {
return this.client.keys(`${prefix}*`);
return scanPatterns(this.client, `${prefix}*`);
}

delete(key: string): PromiseLike<boolean> | boolean {
@@ -111,3 +111,16 @@ export default class RedisCache<V = string> implements KeyValueCache<V>, Disposa
}
}
}

function scanPatterns(redis: Redis, pattern: string, cursor: string = '0', keys: string[] = []) {
return mapMaybePromise(
redis.scan(cursor, 'MATCH', pattern, 'COUNT', '10'),
([nextCursor, nextKeys]) => {
keys.push(...nextKeys);
if (nextCursor === '0') {
return keys;
}
return scanPatterns(redis, pattern, nextCursor, keys);
},
);
}
18 changes: 18 additions & 0 deletions packages/cache/redis/test/cache.spec.ts
Original file line number Diff line number Diff line change
@@ -165,4 +165,22 @@ describe('redis', () => {
});
});
});

describe('methods', () => {
it('get/set/delete', async () => {
using redis = new RedisCache({ logger });
const key = 'key';
const value = 'value';
await redis.set(key, value);
await expect(redis.get(key)).resolves.toBe(value);
await redis.delete(key);
await expect(redis.get(key)).resolves.toBeUndefined();
});
it('getKeysByPrefix', async () => {
using redis = new RedisCache({ logger });
const keys = ['foo1', 'foo2', 'foo3'];
await Promise.all(keys.map((key, i) => redis.set(key, `value${i}`)));
await expect(redis.getKeysByPrefix('foo')).resolves.toEqual(keys);
});
});
});

0 comments on commit e58b4ac

Please sign in to comment.