Skip to content

Commit

Permalink
Merge pull request #22 from mergermarket/redis-4
Browse files Browse the repository at this point in the history
support Redis 4 client
  • Loading branch information
iona-andras-nemes authored Dec 13, 2024
2 parents f5574fb + 140624a commit 7e203e7
Show file tree
Hide file tree
Showing 8 changed files with 7,285 additions and 3,924 deletions.
12 changes: 10 additions & 2 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
{
"extends": ["@acuris"]
}
"extends": [
"@acuris"
],
"parserOptions": {
"project": [
"./tsconfig.json",
"./tsconfig-test.json"
]
}
}
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
node-version: [20.x]
services:
redis:
image: redis
ports:
ports:
- 6379:6379
steps:
- uses: actions/checkout@v1
Expand Down
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,6 @@
"**/.fuse_hidden*": true
},
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
"source.fixAll.eslint": "explicit"
}
}
11,073 changes: 7,227 additions & 3,846 deletions package-lock.json

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@acuris/leprechaun-cache",
"version": "0.0.12",
"version": "0.1.0",
"private": false,
"description": "Caching library that supports double checked caching and stale returns to avoid stampede and slow responses",
"keywords": [
Expand All @@ -17,7 +17,7 @@
"url": "https://github.com/mergermarket/leprechaun-cache.git"
},
"engines": {
"node": ">=10.15.0"
"node": ">=20.15.0"
},
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand All @@ -40,7 +40,7 @@
]
},
"dependencies": {
"@types/redis": "^2.8.14",
"redis": "^4.7.0",
"uuid": "^3.3.3"
},
"devDependencies": {
Expand Down Expand Up @@ -68,7 +68,6 @@
"lint-staged": "^9.4.2",
"mocha": "^6.2.2",
"prettier": "^1.19.1",
"redis": "^2.8.0",
"sinon": "^7.5.0",
"sinon-chai": "^3.3.0",
"ts-mocha": "^6.0.0",
Expand Down
86 changes: 24 additions & 62 deletions src/storage/redis-cache-store.ts
Original file line number Diff line number Diff line change
@@ -1,82 +1,44 @@
import { CacheStore, CacheItem, Cacheable } from '../types'
import { RedisClient } from 'redis'
import { RedisClientType } from 'redis'
import { v4 as uuidV4 } from 'uuid'

function lockKey(key: string): string {
return `LOCK-${key}`
}

export class RedisCacheStore<T extends Cacheable = Cacheable> implements CacheStore<T> {
public constructor(private redisClient: RedisClient) {}
public constructor(private redisClient: RedisClientType<any>) {}

public get(key: string): Promise<CacheItem<T> | null> {
return new Promise<CacheItem<T> | null>((resolve, reject) => {
this.redisClient.get(key, (error, result) => {
if (error) {
reject(error)
}
if (!result) {
resolve(null)
}
resolve(JSON.parse(result))
})
})
public async get(key: string): Promise<CacheItem<T> | null> {
const result = await this.redisClient.get(key)
return JSON.parse(result)
}

public set(key: string, data: CacheItem<T>, ttl: number): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
this.redisClient.set(key, JSON.stringify(data), 'PX', ttl, (error, result) => {
if (error) {
reject(error)
}
if (result === 'OK') {
resolve(true)
}
resolve(false)
})
})
public async set(key: string, data: CacheItem<T>, ttl: number): Promise<boolean> {
const result = await this.redisClient.set(key, JSON.stringify(data), { PX: ttl })
return result === 'OK'
}

public del(key: string): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
this.redisClient.del(key, (error, res) => {
if (error) {
reject(error)
}
resolve(res > 0)
})
})
public async del(key: string): Promise<boolean> {
const result = await this.redisClient.del(key)
return result > 0
}

public lock(key: string, ttl: number): Promise<string | false> {
public async lock(key: string, ttl: number): Promise<string | false> {
const lockId = uuidV4()
return new Promise<string | false>((resolve, reject) => {
this.redisClient.set(lockKey(key), lockId, 'PX', ttl, 'NX', (error, result) => {
if (error) {
reject(error)
}
if (result === 'OK') {
resolve(lockId)
}
resolve(false)
})
})
const result = await this.redisClient.set(lockKey(key), lockId, { PX: ttl, NX: true })
if (result === 'OK') {
return lockId
}
return false
}

public unlock(key: string, lockId: string): Promise<boolean> {
return new Promise((resolve, reject) => {
this.redisClient.get(lockKey(key), (error, result) => {
if (!error && result && result === lockId) {
this.redisClient.del(lockKey(key), err => {
if (err) {
reject(err)
}
resolve(true)
})
} else {
resolve(false)
}
})
})
public async unlock(key: string, lockId: string): Promise<boolean> {
const result = await this.redisClient.get(lockKey(key))
if (result && result === lockId) {
await this.redisClient.del(lockKey(key))
return true
}
return false
}
}
14 changes: 7 additions & 7 deletions test/integration/leprechaun-cache-redis.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import { RedisCacheStore, LeprechaunCache } from '../../src'
import * as chai from 'chai'
import * as sinon from 'sinon'
import sinonChai from 'sinon-chai'
import { RedisClient } from 'redis'
import { createClient, RedisClientType } from 'redis'

chai.use(sinonChai)
const expect = chai.expect
const redisClient = new RedisClient({})
const redisClient = createClient() as RedisClientType<any>

const cacheStore = new RedisCacheStore(redisClient)

function delay(durationMs: number): Promise<void> {
Expand All @@ -20,13 +21,12 @@ function delay(durationMs: number): Promise<void> {

describe('Leprechaun Cache (integration)', () => {
const sandbox = sinon.sandbox.create()
before(async () => {
await redisClient.connect()
})

beforeEach(async () => {
await new Promise(resolve => {
redisClient.FLUSHALL(() => {
resolve()
})
})
await redisClient.FLUSHALL()
})

afterEach(() => {
Expand Down
11 changes: 11 additions & 0 deletions tsconfig-test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": "@acuris/eslint-config/tsconfig.json",
"compilerOptions": {
"noEmit": false,
"module": "commonjs",
"target": "es2017",
"declaration": true,
"outDir": "./dist-test"
},
"include": ["test/**/*"]
}

0 comments on commit 7e203e7

Please sign in to comment.