Skip to content

Commit caa1b87

Browse files
committed
feat: implement caching for user admission check
1 parent 12688ec commit caa1b87

3 files changed

Lines changed: 48 additions & 7 deletions

File tree

src/factories/message-handler-factory.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,21 @@ import { IncomingMessage, MessageType } from '../@types/messages'
33
import { createSettings } from './settings-factory'
44
import { EventMessageHandler } from '../handlers/event-message-handler'
55
import { eventStrategyFactory } from './event-strategy-factory'
6-
import { IWebSocketAdapter } from '../@types/adapters'
6+
import { getCacheClient } from '../cache/client'
7+
import { ICacheAdapter, IWebSocketAdapter } from '../@types/adapters'
8+
import { RedisAdapter } from '../adapters/redis-adapter'
79
import { slidingWindowRateLimiterFactory } from './rate-limiter-factory'
810
import { SubscribeMessageHandler } from '../handlers/subscribe-message-handler'
911
import { UnsubscribeMessageHandler } from '../handlers/unsubscribe-message-handler'
1012

13+
let cacheAdapter: ICacheAdapter | undefined = undefined
14+
const getCache = (): ICacheAdapter => {
15+
if (!cacheAdapter) {
16+
cacheAdapter = new RedisAdapter(getCacheClient())
17+
}
18+
return cacheAdapter
19+
}
20+
1121
export const messageHandlerFactory = (
1222
eventRepository: IEventRepository,
1323
userRepository: IUserRepository,
@@ -22,6 +32,7 @@ export const messageHandlerFactory = (
2232
userRepository,
2333
createSettings,
2434
slidingWindowRateLimiterFactory,
35+
getCache(),
2536
)
2637
}
2738
case MessageType.REQ:

src/handlers/event-message-handler.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { IEventStrategy, IMessageHandler } from '../@types/message-handlers'
1818
import { createCommandResult } from '../utils/messages'
1919
import { createLogger } from '../factories/logger-factory'
2020
import { Factory } from '../@types/base'
21+
import { ICacheAdapter } from '../@types/adapters'
2122
import { IncomingEventMessage } from '../@types/messages'
2223
import { IRateLimiter } from '../@types/utils'
2324
import { IWebSocketAdapter } from '../@types/adapters'
@@ -33,6 +34,7 @@ export class EventMessageHandler implements IMessageHandler {
3334
protected readonly userRepository: IUserRepository,
3435
private readonly settings: () => Settings,
3536
private readonly slidingWindowRateLimiter: Factory<IRateLimiter>,
37+
private readonly cache: ICacheAdapter,
3638
) {}
3739

3840
public async handleMessage(message: IncomingEventMessage): Promise<void> {
@@ -313,17 +315,41 @@ export class EventMessageHandler implements IMessageHandler {
313315
return
314316
}
315317

316-
// const hasKey = await this.cache.hasKey(`${event.pubkey}:is-admitted`)
317-
// TODO: use cache
318+
const cacheKey = `${event.pubkey}:is-admitted`
319+
320+
try {
321+
const cachedValue = await this.cache.getKey(cacheKey)
322+
if (cachedValue === '1') {
323+
debug('cache hit for %s admission: admitted', event.pubkey)
324+
return
325+
}
326+
if (cachedValue === '0') {
327+
debug('cache hit for %s admission: blocked', event.pubkey)
328+
return 'blocked: pubkey not admitted'
329+
}
330+
} catch (error) {
331+
debug('cache error for %s: %o', event.pubkey, error)
332+
}
333+
318334
const user = await this.userRepository.findByPubkey(event.pubkey)
319335
if (!user || !user.isAdmitted) {
336+
this.cacheSet(cacheKey, '0', 60)
320337
return 'blocked: pubkey not admitted'
321338
}
322339

323340
const minBalance = currentSettings.limits?.event?.pubkey?.minBalance ?? 0n
324341
if (minBalance > 0n && user.balance < minBalance) {
342+
this.cacheSet(cacheKey, '0', 60)
325343
return 'blocked: insufficient balance'
326344
}
345+
346+
this.cacheSet(cacheKey, '1', 300)
347+
}
348+
349+
private cacheSet(key: string, value: string, ttl: number): void {
350+
this.cache.setKey(key, value)
351+
.then(() => this.cache.setKeyExpiry(key, ttl))
352+
.catch((error) => debug('unable to cache %s: %o', key, error))
327353
}
328354

329355
protected addExpirationMetadata(event: Event): Event | ExpiringEvent {

test/unit/handlers/event-message-handler.spec.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ describe('EventMessageHandler', () => {
8888
() => ({
8989
info: { relay_url: 'relay_url' },
9090
}) as any,
91-
() => ({ hit: async () => false })
91+
() => ({ hit: async () => false }),
92+
{ hasKey: async () => false, setKey: async () => true } as any,
9293
)
9394
})
9495

@@ -262,7 +263,8 @@ describe('EventMessageHandler', () => {
262263
{ hasActiveRequestToVanish: async () => false } as any,
263264
userRepository,
264265
() => settings,
265-
() => ({ hit: async () => false })
266+
() => ({ hit: async () => false }),
267+
{ hasKey: async () => false, setKey: async () => true } as any,
266268
)
267269
})
268270

@@ -738,7 +740,8 @@ describe('EventMessageHandler', () => {
738740
{ hasActiveRequestToVanish: async () => false } as any,
739741
userRepository,
740742
() => settings,
741-
() => ({ hit: rateLimiterHitStub })
743+
() => ({ hit: rateLimiterHitStub }),
744+
{ hasKey: async () => false, setKey: async () => true } as any,
742745
)
743746
})
744747

@@ -1006,7 +1009,8 @@ describe('EventMessageHandler', () => {
10061009
{ hasActiveRequestToVanish: async () => false } as any,
10071010
userRepository,
10081011
() => settings,
1009-
() => ({ hit: async () => false })
1012+
() => ({ hit: async () => false }),
1013+
{ hasKey: async () => false, getKey: async () => null, setKey: async () => true, setKeyExpiry: async () => undefined } as any,
10101014
)
10111015
})
10121016

0 commit comments

Comments
 (0)