From 367b8d64eb002fc1dd36bdf0d20df805034be55b Mon Sep 17 00:00:00 2001 From: SegaraRai Date: Mon, 13 Jan 2025 11:34:49 +0900 Subject: [PATCH] feat: caching --- .changeset/wild-files-repair.md | 5 +++ src/factory.ts | 58 ++++++++++++++++++++++++++++----- src/prisma.ts | 18 ++++++---- 3 files changed, 66 insertions(+), 15 deletions(-) create mode 100644 .changeset/wild-files-repair.md diff --git a/.changeset/wild-files-repair.md b/.changeset/wild-files-repair.md new file mode 100644 index 0000000..42794aa --- /dev/null +++ b/.changeset/wild-files-repair.md @@ -0,0 +1,5 @@ +--- +"fraci": minor +--- + +Add caching feature. diff --git a/src/factory.ts b/src/factory.ts index 24350bb..2cead4d 100644 --- a/src/factory.ts +++ b/src/factory.ts @@ -37,23 +37,63 @@ export interface FraciOptions { maxRetries?: number; } +export type FraciCache = Map & { __fraci__: never }; + +/** + * Create cache. + * + * @returns Cache + */ +export function createFraciCache(): FraciCache { + return new Map() as FraciCache; +} + +function withCache( + cache: FraciCache | undefined, + key: string, + fn: () => T +): T { + if (!cache) { + return fn(); + } + + let value = cache.get(key) as T | undefined; + if (value === undefined) { + value = fn(); + cache.set(key, value); + } + + return value; +} + /** * Create fractional indexing utility. * * @param options Options + * @param cache Cache (optional) * @returns Fractional indexing utility */ -export function fraci({ - digitBase, - lengthBase, - maxLength = DEFAULT_MAX_LENGTH, - maxRetries = DEFAULT_MAX_RETRIES, -}: FraciOptions): Fraci { +export function fraci( + { + digitBase, + lengthBase, + maxLength = DEFAULT_MAX_LENGTH, + maxRetries = DEFAULT_MAX_RETRIES, + }: FraciOptions, + cache?: FraciCache +): Fraci { type F = FractionalIndex; - const [digBaseForward, digBaseReverse] = createDigitBaseMap(digitBase); - const [lenBaseForward, lenBaseReverse] = - createIntegerLengthBaseMap(lengthBase); + const [digBaseForward, digBaseReverse] = withCache( + cache, + `D${digitBase}`, + createDigitBaseMap.bind(null, digitBase) + ); + const [lenBaseForward, lenBaseReverse] = withCache( + cache, + `L${lengthBase}`, + createIntegerLengthBaseMap.bind(null, lengthBase) + ); const smallestInteger = getSmallestInteger(digBaseForward, lenBaseForward); return { diff --git a/src/prisma.ts b/src/prisma.ts index a5c4422..a61cc09 100644 --- a/src/prisma.ts +++ b/src/prisma.ts @@ -3,6 +3,7 @@ import { Prisma, PrismaClient } from "@prisma/client/extension.js"; import type { PrismaClientKnownRequestError } from "@prisma/client/runtime/library.js"; import { + createFraciCache, DEFAULT_MAX_LENGTH, DEFAULT_MAX_RETRIES, fraci, @@ -360,6 +361,8 @@ export function fraciExtension({ maxRetries = DEFAULT_MAX_RETRIES, }: Options) { return Prisma.defineExtension((client) => { + const cache = createFraciCache(); + type HelperValue = FraciForPrisma; const helperMap = new Map(); @@ -376,12 +379,15 @@ export function fraciExtension({ ); } - const helper = fraci({ - digitBase, - lengthBase, - maxLength, - maxRetries, - }); + const helper = fraci( + { + digitBase, + lengthBase, + maxLength, + maxRetries, + }, + cache + ); const indicesForAfter = async ( cursor: any,