Skip to content

Commit a8f9a02

Browse files
committed
Divided up the cache and changed keys a bit
1 parent 5787fc3 commit a8f9a02

File tree

7 files changed

+112
-110
lines changed

7 files changed

+112
-110
lines changed

server/api/social/like.delete.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,8 @@ export default eventHandlerWithOAuthSession(async (event, oAuthSession) => {
3232
var result = await likesUtil.unlikeAPackageAndReturnLikes(body.packageName, loggedInUsersDid)
3333
return result
3434
}
35+
36+
console.error(
37+
`User ${loggedInUsersDid} tried to unlike a package ${body.packageName} but it was not liked by them.`,
38+
)
3539
})

server/utils/atproto/utils/likes.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { getCacheAdatper } from '../../cache'
21
import { $nsid as likeNsid } from '#shared/types/lexicons/dev/npmx/feed/like.defs'
32
import type { Backlink } from '#shared/utils/constellation'
43

@@ -14,7 +13,7 @@ export type PackageLikes = {
1413

1514
//Cache keys and helpers
1615
const CACHE_PREFIX = 'atproto-likes:'
17-
const CACHE_PACKAGE_TOTAL_KEY = (packageName: string) => `${CACHE_PREFIX}:${packageName}:total`
16+
const CACHE_PACKAGE_TOTAL_KEY = (packageName: string) => `${CACHE_PREFIX}${packageName}:total`
1817
const CACHE_USER_LIKES_KEY = (packageName: string, did: string) =>
1918
`${CACHE_PREFIX}${packageName}:users:${did}:liked`
2019
const CACHE_USERS_BACK_LINK = (packageName: string, did: string) =>
@@ -41,7 +40,7 @@ export class PackageLikesUtils {
4140
return { data, isStale: false, cachedAt: null }
4241
},
4342
)
44-
this.cache = getCacheAdatper(CACHE_PREFIX)
43+
this.cache = getCacheAdatper('generic')
4544
}
4645

4746
/**

server/utils/cache.ts

Lines changed: 0 additions & 107 deletions
This file was deleted.

server/utils/cache/adapter.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Redis } from '@upstash/redis'
2+
3+
export function getCacheAdatper(prefix: string): CacheAdapter {
4+
const config = useRuntimeConfig()
5+
6+
if (!import.meta.dev && config.upstash?.redisRestUrl && config.upstash?.redisRestToken) {
7+
const redis = new Redis({
8+
url: config.upstash.redisRestUrl,
9+
token: config.upstash.redisRestToken,
10+
})
11+
return new RedisCacheAdatper(redis, prefix)
12+
}
13+
return new StorageCacheAdapter()
14+
}

server/utils/cache/local.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* Local cache data entry
3+
*/
4+
interface LocalCachedEntry<T = unknown> {
5+
value: T
6+
ttl?: number
7+
cachedAt: number
8+
}
9+
10+
/**
11+
* Checks to see if a cache entry is stale locally
12+
* @param entry - The entry from the locla cache
13+
* @returns
14+
*/
15+
function isCacheEntryStale(entry: LocalCachedEntry): boolean {
16+
if (!entry.ttl) return false
17+
const now = Date.now()
18+
const expiresAt = entry.cachedAt + entry.ttl * 1000
19+
return now > expiresAt
20+
}
21+
22+
/**
23+
* Local implmentation of a cache to be used during development
24+
*/
25+
export class StorageCacheAdapter implements CacheAdapter {
26+
private readonly storage = useStorage('generic-cache')
27+
28+
async get<T>(key: string): Promise<T | undefined> {
29+
const result = await this.storage.getItem<LocalCachedEntry<T>>(key)
30+
if (!result) return
31+
if (isCacheEntryStale(result)) {
32+
await this.storage.removeItem(key)
33+
return
34+
}
35+
return result.value
36+
}
37+
38+
async set<T>(key: string, value: T, ttl?: number): Promise<void> {
39+
await this.storage.setItem(key, { value, ttl, cachedAt: Date.now() })
40+
}
41+
42+
async delete(key: string): Promise<void> {
43+
await this.storage.removeItem(key)
44+
}
45+
}

server/utils/cache/redis.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import type { Redis } from '@upstash/redis'
2+
3+
/**
4+
* Redis cache storage with TTL handled by redis for use in production
5+
*/
6+
export class RedisCacheAdatper implements CacheAdapter {
7+
private readonly redis: Redis
8+
private readonly prefix: string
9+
10+
formatKey(key: string): string {
11+
return `${this.prefix}:${key}`
12+
}
13+
14+
constructor(redis: Redis, prefix: string) {
15+
this.redis = redis
16+
this.prefix = prefix
17+
}
18+
19+
async get<T>(key: string): Promise<T | undefined> {
20+
const formattedKey = this.formatKey(key)
21+
const value = await this.redis.get<T>(formattedKey)
22+
if (!value) return
23+
return value
24+
}
25+
26+
async set<T>(key: string, value: T, ttl?: number): Promise<void> {
27+
const formattedKey = this.formatKey(key)
28+
if (ttl) {
29+
await this.redis.setex(formattedKey, ttl, value)
30+
} else {
31+
await this.redis.set(formattedKey, value)
32+
}
33+
}
34+
35+
async delete(key: string): Promise<void> {
36+
const formattedKey = this.formatKey(key)
37+
await this.redis.del(formattedKey)
38+
}
39+
}

server/utils/cache/shared.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* Generic cache adapter to allow using a local cache during development and redis in production
3+
*/
4+
export interface CacheAdapter {
5+
get<T>(key: string): Promise<T | undefined>
6+
set<T>(key: string, value: T, ttl?: number): Promise<void>
7+
delete(key: string): Promise<void>
8+
}

0 commit comments

Comments
 (0)