Thinking out loud about v2 of this library
Asjas opened this issue · comments
At the moment this Prisma middleware isn't very flexible and I feel that the caching API isn't that nice to use.
prismaClient.$use(
createPrismaRedisCache({
models: ["User", "Post"],
cacheTime: 300,
redis,
excludeCacheMethods: ["findMany"],
}),
);
I want to update the API to possibly look like this:
models
: Array of objects. Thekey
is themodel
to cache and thevalue
is thetime
to cache it.excludeModels
: Array of strings. These models will NOT be cached.redis
: Optional. Falls back to using an in-memoryLRU
cachecacheTime
: Still an integerexcludeCacheMethods
: Still an array of methods to ignore when caching
Example 1:
prismaClient.$use(
createPrismaRedisCache({
cacheTime: 300,
}),
);
You can invoke the middleware while leaving the models
out which will cause all models to be cached based on cacheTime
.
And if you leave the redis
instance out this should fall back to using an in-memory LRU
cache. This should make it easier for someone to test this in development without needing to configure or install Redis.
Thoughts: In such a case it should print out a warning
stating that an in-memory cache is being used and that you should pass a Redis instance to persist the cache.
Example 2:
prismaClient.$use(
createPrismaRedisCache({
models: [{ "User", 300 }, { "Post": 900 }],
cacheTime: 300,
redis,
excludeCacheMethods: ["findMany"],
}),
);
You can specify the caching time per model.
The global cacheTime
middleware option is then used for any other Model that isn't explicitly specified in models
.
You can then specify a value of 0
to cacheTime
or leave the cacheTime
option out to stop it from caching any explicit models
you didn't specify.
Some thoughts about the models
API
I don't know if I want the models to have an API that looks like this.
models: [{ "User", 300 }, { "Post": 900 }],
Or like this:
models: [{ model: "User", cacheTime: 300 }, { model: "Post", cacheTime: 900 }],
I like the 2nd one, but it also feels a slightly verbose... 🤔
Some other thoughts.
-
Should I just ignore
cacheTime
if there is amodels
value (which will include a caching value per model)? Or should I use it for any model that isn't specified? -
Allowing someone to specify their own caching key per model...? yikes
-
Allowing an option called
excludeModels
which could be an Array of strings which will NOT be cached?
The createPrismaRedisCache
API I decided on is represented as this TypeScript type.
export type PrismaMutationAction =
| "create"
| "createMany"
| "update"
| "updateMany"
| "upsert"
| "delete"
| "deleteMany"
| "executeRawUnsafe";
export type PrismaQueryAction =
| "findFirst"
| "findUnique"
| "findMany"
| "aggregate"
| "count"
| "groupBy"
| "queryRaw";
export type PrismaAction = PrismaMutationAction | PrismaQueryAction;
export type RedisMemoryOptions = {
client: Redis.Redis;
invalidation?: boolean | { referencesTTL?: number };
log?: any;
};
export type MemoryStorageOptions = {
size?: number;
invalidation?: boolean;
log?: any;
};
export type CreatePrismaRedisCache = {
models?: [
{
model: string;
primaryKey?: string;
cacheTime?: number;
excludeCacheMethods?: [PrismaQueryAction];
},
];
storage?:
| {
type: "redis";
options?: RedisMemoryOptions;
}
| {
type: "memory";
options?: MemoryStorageOptions;
};
defaultCacheTime?: number;
defaultExcludeCacheModels?: [string];
defaultExcludeCacheMethods?: [PrismaQueryAction];
onError?: () => void;
onHit?: () => void;
onMiss?: () => void;
onDedupe?: () => void;
};