Write behind reading progress as a list that can be reduced at commit or read time

This commit is contained in:
Jackson Harper
2024-01-31 09:28:09 +08:00
parent c2327781e1
commit fbfa934479
6 changed files with 137 additions and 131 deletions

View File

@ -4,80 +4,64 @@ type ReadingProgressCacheItem = {
readingProgressPercent: number
readingProgressTopPercent: number | undefined
readingProgressAnchorIndex: number | undefined
updatedAt: Date
updatedAt: string
}
export class ReadingProgressDataSource {
private cacheItems: { [id: string]: ReadingProgressCacheItem } = {}
constructor() {}
async getReadingProgress(
uid: string,
libraryItemID: string
): Promise<ReadingProgressCacheItem | undefined> {
const cacheKey = `omnivore:reading-progress:${libraryItemID}`
const cacheKey = `omnivore:reading-progress:${uid}:${libraryItemID}`
const cached = this.cacheItems[cacheKey]
if (cached) {
return cached
}
return this.valueFromRedis(libraryItemID)
return this.valueFromRedis(cacheKey)
}
async updateReadingProgress(
uid: string,
libraryItemID: string,
progress: {
readingProgressPercent: number
readingProgressTopPercent: number | undefined | null
readingProgressAnchorIndex: number | undefined | null
readingProgressTopPercent: number | undefined
readingProgressAnchorIndex: number | undefined
}
): Promise<void> {
const cacheKey = `omnivore:reading-progress:${libraryItemID}`
const existingItem = await this.valueFromRedis(cacheKey)
const cacheItem = {
readingProgressPercent: Math.max(
progress.readingProgressPercent,
existingItem?.readingProgressPercent ?? 0
),
readingProgressTopPercent: Math.max(
progress.readingProgressTopPercent ?? 0,
existingItem?.readingProgressTopPercent ?? 0
),
readingProgressAnchorIndex: Math.max(
progress.readingProgressAnchorIndex ?? 0,
existingItem?.readingProgressAnchorIndex ?? 0
),
updatedAt: new Date(),
const cacheKey = `omnivore:reading-progress:${uid}:${libraryItemID}`
const cacheItem: ReadingProgressCacheItem = {
...progress,
updatedAt: new Date().toISOString(),
}
this.cacheItems[cacheKey] = cacheItem
if (await redisDataSource.redisClient?.hmset(cacheKey, cacheItem)) {
console.log('cached reading progress')
if (
await redisDataSource.redisClient?.lpush(
cacheKey,
JSON.stringify(cacheItem)
)
) {
console.log('cached reading progress', cacheKey)
} else {
console.log('failed to cache reading progress')
}
}
async valueFromRedis(
libraryItemID: string
cacheKey: string
): Promise<ReadingProgressCacheItem | undefined> {
const cacheKey = `omnivore:reading-progress:${libraryItemID}`
const redisCached = await redisDataSource.redisClient?.hgetall(cacheKey)
if (redisCached) {
const readingProgressPercent = parseInt(
redisCached.readingProgressPercent,
10
)
const updatedAt = new Date(parseInt(redisCached.updatedAt, 10))
if (!Number.isNaN(readingProgressPercent) && updatedAt) {
return {
readingProgressPercent,
readingProgressTopPercent: redisCached.readingProgressTopPercent
? parseInt(redisCached.readingProgressTopPercent, 10)
: undefined,
readingProgressAnchorIndex: redisCached.readingProgressAnchorIndex
? parseInt(redisCached.readingProgressAnchorIndex, 10)
: undefined,
updatedAt,
}
}
const redisCached = await redisDataSource.redisClient?.lrange(
cacheKey,
0,
0
)
if (redisCached && redisCached.length > 0) {
return JSON.parse(redisCached[0])
}
return undefined
}