mirror of
https://github.com/complexcaresolutions/cms.c2sgmbh.git
synced 2026-03-17 17:24:12 +00:00
feat: Redis caching integration
This commit is contained in:
parent
0a8e191747
commit
d053eec21a
5 changed files with 267 additions and 8 deletions
|
|
@ -31,6 +31,7 @@
|
|||
"cross-env": "^7.0.3",
|
||||
"dotenv": "16.4.7",
|
||||
"graphql": "^16.8.1",
|
||||
"ioredis": "^5.8.2",
|
||||
"next": "15.4.7",
|
||||
"node-cron": "^4.2.1",
|
||||
"payload": "3.65.0",
|
||||
|
|
|
|||
|
|
@ -47,6 +47,9 @@ importers:
|
|||
graphql:
|
||||
specifier: ^16.8.1
|
||||
version: 16.12.0
|
||||
ioredis:
|
||||
specifier: ^5.8.2
|
||||
version: 5.8.2
|
||||
next:
|
||||
specifier: 15.4.7
|
||||
version: 15.4.7(@babel/core@7.28.5)(@playwright/test@1.56.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.77.4)
|
||||
|
|
@ -965,6 +968,9 @@ packages:
|
|||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@ioredis/commands@1.4.0':
|
||||
resolution: {integrity: sha512-aFT2yemJJo+TZCmieA7qnYGQooOS7QfNmYrzGtsYd3g9j5iDP8AimYYAesf79ohjbLG12XxC4nG5DyEnC88AsQ==}
|
||||
|
||||
'@jridgewell/gen-mapping@0.3.13':
|
||||
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
|
||||
|
||||
|
|
@ -1882,6 +1888,10 @@ packages:
|
|||
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
cluster-key-slot@1.1.2:
|
||||
resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
color-convert@2.0.1:
|
||||
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
||||
engines: {node: '>=7.0.0'}
|
||||
|
|
@ -2020,6 +2030,10 @@ packages:
|
|||
resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
denque@2.1.0:
|
||||
resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==}
|
||||
engines: {node: '>=0.10'}
|
||||
|
||||
dequal@2.0.3:
|
||||
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
|
||||
engines: {node: '>=6'}
|
||||
|
|
@ -2596,6 +2610,10 @@ packages:
|
|||
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
ioredis@5.8.2:
|
||||
resolution: {integrity: sha512-C6uC+kleiIMmjViJINWk80sOQw5lEzse1ZmvD+S/s8p8CWapftSaC+kocGTx6xrbrJ4WmYQGC08ffHLr6ToR6Q==}
|
||||
engines: {node: '>=12.22.0'}
|
||||
|
||||
ipaddr.js@2.2.0:
|
||||
resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==}
|
||||
engines: {node: '>= 10'}
|
||||
|
|
@ -2845,6 +2863,12 @@ packages:
|
|||
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
lodash.defaults@4.2.0:
|
||||
resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==}
|
||||
|
||||
lodash.isarguments@3.1.0:
|
||||
resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==}
|
||||
|
||||
lodash.merge@4.6.2:
|
||||
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
||||
|
||||
|
|
@ -3397,6 +3421,14 @@ packages:
|
|||
resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==}
|
||||
engines: {node: '>= 12.13.0'}
|
||||
|
||||
redis-errors@1.2.0:
|
||||
resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
redis-parser@3.0.0:
|
||||
resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
reflect.getprototypeof@1.0.10:
|
||||
resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
|
@ -3582,6 +3614,9 @@ packages:
|
|||
stackback@0.0.2:
|
||||
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
|
||||
|
||||
standard-as-callback@2.1.0:
|
||||
resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==}
|
||||
|
||||
state-local@1.0.7:
|
||||
resolution: {integrity: sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==}
|
||||
|
||||
|
|
@ -4740,6 +4775,8 @@ snapshots:
|
|||
'@img/sharp-win32-x64@0.34.5':
|
||||
optional: true
|
||||
|
||||
'@ioredis/commands@1.4.0': {}
|
||||
|
||||
'@jridgewell/gen-mapping@0.3.13':
|
||||
dependencies:
|
||||
'@jridgewell/sourcemap-codec': 1.5.5
|
||||
|
|
@ -5879,6 +5916,8 @@ snapshots:
|
|||
|
||||
clsx@2.1.1: {}
|
||||
|
||||
cluster-key-slot@1.1.2: {}
|
||||
|
||||
color-convert@2.0.1:
|
||||
dependencies:
|
||||
color-name: 1.1.4
|
||||
|
|
@ -6007,6 +6046,8 @@ snapshots:
|
|||
has-property-descriptors: 1.0.2
|
||||
object-keys: 1.1.1
|
||||
|
||||
denque@2.1.0: {}
|
||||
|
||||
dequal@2.0.3: {}
|
||||
|
||||
detect-libc@2.1.2: {}
|
||||
|
|
@ -6244,8 +6285,8 @@ snapshots:
|
|||
'@typescript-eslint/parser': 8.48.0(eslint@9.39.1)(typescript@5.7.3)
|
||||
eslint: 9.39.1
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1)
|
||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1)(typescript@5.7.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1)
|
||||
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1)(typescript@5.7.3))(eslint@9.39.1))(eslint@9.39.1)
|
||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1)(typescript@5.7.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1)(typescript@5.7.3))(eslint@9.39.1))(eslint@9.39.1))(eslint@9.39.1)
|
||||
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.1)
|
||||
eslint-plugin-react: 7.37.5(eslint@9.39.1)
|
||||
eslint-plugin-react-hooks: 5.2.0(eslint@9.39.1)
|
||||
|
|
@ -6264,7 +6305,7 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1):
|
||||
eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1)(typescript@5.7.3))(eslint@9.39.1))(eslint@9.39.1):
|
||||
dependencies:
|
||||
'@nolyfill/is-core-module': 1.0.39
|
||||
debug: 4.4.3
|
||||
|
|
@ -6275,22 +6316,22 @@ snapshots:
|
|||
tinyglobby: 0.2.15
|
||||
unrs-resolver: 1.11.1
|
||||
optionalDependencies:
|
||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1)(typescript@5.7.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1)
|
||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1)(typescript@5.7.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1)(typescript@5.7.3))(eslint@9.39.1))(eslint@9.39.1))(eslint@9.39.1)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.48.0(eslint@9.39.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1):
|
||||
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.48.0(eslint@9.39.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1)(typescript@5.7.3))(eslint@9.39.1))(eslint@9.39.1))(eslint@9.39.1):
|
||||
dependencies:
|
||||
debug: 3.2.7
|
||||
optionalDependencies:
|
||||
'@typescript-eslint/parser': 8.48.0(eslint@9.39.1)(typescript@5.7.3)
|
||||
eslint: 9.39.1
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1)
|
||||
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1)(typescript@5.7.3))(eslint@9.39.1))(eslint@9.39.1)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1)(typescript@5.7.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1):
|
||||
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1)(typescript@5.7.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1)(typescript@5.7.3))(eslint@9.39.1))(eslint@9.39.1))(eslint@9.39.1):
|
||||
dependencies:
|
||||
'@rtsao/scc': 1.1.0
|
||||
array-includes: 3.1.9
|
||||
|
|
@ -6301,7 +6342,7 @@ snapshots:
|
|||
doctrine: 2.1.0
|
||||
eslint: 9.39.1
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.48.0(eslint@9.39.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1)
|
||||
eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.48.0(eslint@9.39.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1)(typescript@5.7.3))(eslint@9.39.1))(eslint@9.39.1))(eslint@9.39.1)
|
||||
hasown: 2.0.2
|
||||
is-core-module: 2.16.1
|
||||
is-glob: 4.0.3
|
||||
|
|
@ -6673,6 +6714,20 @@ snapshots:
|
|||
hasown: 2.0.2
|
||||
side-channel: 1.1.0
|
||||
|
||||
ioredis@5.8.2:
|
||||
dependencies:
|
||||
'@ioredis/commands': 1.4.0
|
||||
cluster-key-slot: 1.1.2
|
||||
debug: 4.4.3
|
||||
denque: 2.1.0
|
||||
lodash.defaults: 4.2.0
|
||||
lodash.isarguments: 3.1.0
|
||||
redis-errors: 1.2.0
|
||||
redis-parser: 3.0.0
|
||||
standard-as-callback: 2.1.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
ipaddr.js@2.2.0: {}
|
||||
|
||||
is-alphabetical@2.0.1: {}
|
||||
|
|
@ -6932,6 +6987,10 @@ snapshots:
|
|||
dependencies:
|
||||
p-locate: 5.0.0
|
||||
|
||||
lodash.defaults@4.2.0: {}
|
||||
|
||||
lodash.isarguments@3.1.0: {}
|
||||
|
||||
lodash.merge@4.6.2: {}
|
||||
|
||||
lodash@4.17.21: {}
|
||||
|
|
@ -7652,6 +7711,12 @@ snapshots:
|
|||
|
||||
real-require@0.2.0: {}
|
||||
|
||||
redis-errors@1.2.0: {}
|
||||
|
||||
redis-parser@3.0.0:
|
||||
dependencies:
|
||||
redis-errors: 1.2.0
|
||||
|
||||
reflect.getprototypeof@1.0.10:
|
||||
dependencies:
|
||||
call-bind: 1.0.8
|
||||
|
|
@ -7927,6 +7992,8 @@ snapshots:
|
|||
|
||||
stackback@0.0.2: {}
|
||||
|
||||
standard-as-callback@2.1.0: {}
|
||||
|
||||
state-local@1.0.7: {}
|
||||
|
||||
std-env@3.10.0: {}
|
||||
|
|
|
|||
50
src/hooks/invalidateCache.ts
Normal file
50
src/hooks/invalidateCache.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
import type { CollectionAfterChangeHook, CollectionAfterDeleteHook } from 'payload'
|
||||
import { cache } from '@/lib/redis'
|
||||
|
||||
// Nach dem Speichern/Ändern Cache invalidieren
|
||||
export const invalidateCacheOnChange: CollectionAfterChangeHook = async ({
|
||||
collection,
|
||||
doc,
|
||||
operation,
|
||||
}) => {
|
||||
const collectionSlug = collection.slug
|
||||
|
||||
console.log(`[Cache Invalidation] ${operation} on ${collectionSlug}`)
|
||||
|
||||
// Pattern-basierte Invalidierung
|
||||
switch (collectionSlug) {
|
||||
case 'pages':
|
||||
await cache.delPattern('page:*')
|
||||
await cache.delPattern('pages:*')
|
||||
break
|
||||
case 'posts':
|
||||
await cache.delPattern('post:*')
|
||||
await cache.delPattern('posts:*')
|
||||
break
|
||||
case 'navigation':
|
||||
await cache.delPattern('nav:*')
|
||||
break
|
||||
case 'categories':
|
||||
await cache.delPattern('categories:*')
|
||||
break
|
||||
default:
|
||||
// Fallback: Collection-spezifisches Pattern
|
||||
await cache.delPattern(`${collectionSlug}:*`)
|
||||
}
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
// Nach dem Löschen Cache invalidieren
|
||||
export const invalidateCacheOnDelete: CollectionAfterDeleteHook = async ({
|
||||
collection,
|
||||
doc,
|
||||
}) => {
|
||||
const collectionSlug = collection.slug
|
||||
|
||||
console.log(`[Cache Invalidation] delete on ${collectionSlug}`)
|
||||
|
||||
await cache.delPattern(`${collectionSlug}:*`)
|
||||
|
||||
return doc
|
||||
}
|
||||
33
src/lib/cache-keys.ts
Normal file
33
src/lib/cache-keys.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Zentrale Cache-Key Definitionen
|
||||
export const CacheKeys = {
|
||||
// Pages
|
||||
page: (slug: string, locale: string) => `page:${locale}:${slug}`,
|
||||
pages: (tenant: string, locale: string) => `pages:${tenant}:${locale}`,
|
||||
|
||||
// Posts
|
||||
post: (slug: string, locale: string) => `post:${locale}:${slug}`,
|
||||
posts: (tenant: string, locale: string) => `posts:${tenant}:${locale}`,
|
||||
postsList: (tenant: string, locale: string, page: number) =>
|
||||
`posts:${tenant}:${locale}:list:${page}`,
|
||||
|
||||
// Navigation
|
||||
navigation: (tenant: string, locale: string) => `nav:${tenant}:${locale}`,
|
||||
|
||||
// Categories
|
||||
categories: (tenant: string, locale: string) => `categories:${tenant}:${locale}`,
|
||||
|
||||
// Global Settings
|
||||
globals: (tenant: string, slug: string) => `global:${tenant}:${slug}`,
|
||||
|
||||
// Tenant-spezifisch
|
||||
tenant: (slug: string) => `tenant:${slug}`,
|
||||
}
|
||||
|
||||
// TTL Werte (in Sekunden)
|
||||
export const CacheTTL = {
|
||||
SHORT: 60, // 1 Minute
|
||||
DEFAULT: 300, // 5 Minuten
|
||||
MEDIUM: 900, // 15 Minuten
|
||||
LONG: 3600, // 1 Stunde
|
||||
VERY_LONG: 86400, // 24 Stunden
|
||||
}
|
||||
108
src/lib/redis.ts
Normal file
108
src/lib/redis.ts
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
import Redis from 'ioredis'
|
||||
|
||||
const getRedisClient = () => {
|
||||
const host = process.env.REDIS_HOST || 'localhost'
|
||||
const port = parseInt(process.env.REDIS_PORT || '6379')
|
||||
|
||||
if (!process.env.REDIS_HOST) {
|
||||
console.warn('[Redis] REDIS_HOST nicht gesetzt, verwende localhost')
|
||||
}
|
||||
|
||||
return new Redis({
|
||||
host,
|
||||
port,
|
||||
maxRetriesPerRequest: 3,
|
||||
retryDelayOnFailover: 100,
|
||||
lazyConnect: true,
|
||||
})
|
||||
}
|
||||
|
||||
// Singleton Pattern
|
||||
let redisClient: Redis | null = null
|
||||
|
||||
export const getRedis = (): Redis => {
|
||||
if (!redisClient) {
|
||||
redisClient = getRedisClient()
|
||||
}
|
||||
return redisClient
|
||||
}
|
||||
|
||||
// Cache Helper Funktionen
|
||||
export const cache = {
|
||||
async get<T>(key: string): Promise<T | null> {
|
||||
try {
|
||||
const redis = getRedis()
|
||||
const data = await redis.get(key)
|
||||
if (data) {
|
||||
console.log(`[Cache] HIT: ${key}`)
|
||||
return JSON.parse(data)
|
||||
}
|
||||
console.log(`[Cache] MISS: ${key}`)
|
||||
return null
|
||||
} catch (error) {
|
||||
console.error('[Cache] GET Error:', error)
|
||||
return null
|
||||
}
|
||||
},
|
||||
|
||||
async set(key: string, value: unknown, ttlSeconds = 300): Promise<void> {
|
||||
try {
|
||||
const redis = getRedis()
|
||||
await redis.setex(key, ttlSeconds, JSON.stringify(value))
|
||||
console.log(`[Cache] SET: ${key} (TTL: ${ttlSeconds}s)`)
|
||||
} catch (error) {
|
||||
console.error('[Cache] SET Error:', error)
|
||||
}
|
||||
},
|
||||
|
||||
async del(key: string): Promise<void> {
|
||||
try {
|
||||
const redis = getRedis()
|
||||
await redis.del(key)
|
||||
console.log(`[Cache] DEL: ${key}`)
|
||||
} catch (error) {
|
||||
console.error('[Cache] DEL Error:', error)
|
||||
}
|
||||
},
|
||||
|
||||
async delPattern(pattern: string): Promise<void> {
|
||||
try {
|
||||
const redis = getRedis()
|
||||
const keys = await redis.keys(pattern)
|
||||
if (keys.length > 0) {
|
||||
await redis.del(...keys)
|
||||
console.log(`[Cache] DEL Pattern: ${pattern} (${keys.length} keys)`)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Cache] DEL Pattern Error:', error)
|
||||
}
|
||||
},
|
||||
|
||||
async flush(): Promise<void> {
|
||||
try {
|
||||
const redis = getRedis()
|
||||
await redis.flushdb()
|
||||
console.log('[Cache] FLUSH: Database cleared')
|
||||
} catch (error) {
|
||||
console.error('[Cache] FLUSH Error:', error)
|
||||
}
|
||||
},
|
||||
|
||||
// Cache-Wrapper für einfache Verwendung
|
||||
async wrap<T>(
|
||||
key: string,
|
||||
fn: () => Promise<T>,
|
||||
ttlSeconds = 300
|
||||
): Promise<T> {
|
||||
const cached = await this.get<T>(key)
|
||||
if (cached !== null) {
|
||||
return cached
|
||||
}
|
||||
|
||||
const result = await fn()
|
||||
await this.set(key, result, ttlSeconds)
|
||||
return result
|
||||
},
|
||||
}
|
||||
|
||||
export default getRedis
|
||||
Loading…
Reference in a new issue