mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 13:35:42 +09:00
perf(kv-client): use EVALSHA for rate limit scripts (#2130)
This commit is contained in:
1 parent
e06436d6f5
commit
9d1733bdb3
5 files changed
+279
-2
No files matched your search
@@ -1,5 +1,6 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {createHash} from 'node:crypto';
|
||||
import type {IKVPipeline, IKVProvider, IKVSubscription, KVRateLimitResult} from '@pkgs/kv_client/src/IKVProvider';
|
||||
import {
|
||||
type IKVLogger,
|
||||
@@ -232,6 +233,8 @@ redis.call('DEL', KEYS[2])
|
||||
return 1
|
||||
`;
|
||||
|
||||
const SCRIPT_SHA_CACHE = new Map<string, string>();
|
||||
|
||||
interface ScriptPurgeBatchResult {
|
||||
urls: Array<string>;
|
||||
tokens: number;
|
||||
@@ -699,7 +702,18 @@ export class KVClient implements IKVProvider {
|
||||
keyCount: number,
|
||||
...args: Array<string | number>
|
||||
): Promise<unknown> {
|
||||
return await this.execute(command, async () => this.client.eval(script, keyCount, ...args));
|
||||
return await this.execute(command, async () => this.evalCachedScript(script, keyCount, args));
|
||||
}
|
||||
|
||||
private async evalCachedScript(script: string, keyCount: number, args: Array<string | number>): Promise<unknown> {
|
||||
try {
|
||||
return await this.client.evalsha(getScriptSha(script), keyCount, ...args);
|
||||
} catch (error) {
|
||||
if (!isNoScriptError(error)) {
|
||||
throw error;
|
||||
}
|
||||
return await this.client.eval(script, keyCount, ...args);
|
||||
}
|
||||
}
|
||||
|
||||
private async executeJsonScript<T>(
|
||||
@@ -795,6 +809,23 @@ function normalizeRateLimitResult(result: KVRateLimitResult): KVRateLimitResult
|
||||
};
|
||||
}
|
||||
|
||||
function getScriptSha(script: string): string {
|
||||
const cached = SCRIPT_SHA_CACHE.get(script);
|
||||
if (cached !== undefined) {
|
||||
return cached;
|
||||
}
|
||||
const sha = createHash('sha1').update(script).digest('hex');
|
||||
SCRIPT_SHA_CACHE.set(script, sha);
|
||||
return sha;
|
||||
}
|
||||
|
||||
function isNoScriptError(error: unknown): boolean {
|
||||
if (!(error instanceof Error)) {
|
||||
return false;
|
||||
}
|
||||
return error.message.includes('NOSCRIPT');
|
||||
}
|
||||
|
||||
function isTimeoutError(error: unknown): boolean {
|
||||
if (!(error instanceof Error)) {
|
||||
return false;
|
||||
|
||||
Reference in new issue
Block a user