Updating writethrough cache a bit to make sure it implements the PouchDB API properly.

This commit is contained in:
mike12345567 2022-06-24 13:34:00 +01:00
parent e3f25795e8
commit eeca1cb3ba
3 changed files with 54 additions and 25 deletions

View File

@ -3,5 +3,6 @@ const generic = require("./src/cache/generic")
module.exports = { module.exports = {
user: require("./src/cache/user"), user: require("./src/cache/user"),
app: require("./src/cache/appMetadata"), app: require("./src/cache/appMetadata"),
writethrough: require("./src/cache/writethrough"),
...generic, ...generic,
} }

View File

@ -9,30 +9,30 @@ tk.freeze(START_DATE)
const DELAY = 5000 const DELAY = 5000
const db = dangerousGetDB("test") const db = dangerousGetDB("test")
const writethrough = new Writethrough(db) const writethrough = new Writethrough(db, DELAY)
describe("writethrough", () => { describe("writethrough", () => {
describe("put", () => { describe("put", () => {
let first let first
it("should be able to store, will go to DB", async () => { it("should be able to store, will go to DB", async () => {
const response = await writethrough.put({ _id: "test", value: 1 }, DELAY) const response = await writethrough.put({ _id: "test", value: 1 })
const output = await db.get(response._id) const output = await db.get(response.id)
first = output first = output
expect(output.value).toBe(1) expect(output.value).toBe(1)
}) })
it("second put shouldn't update DB", async () => { it("second put shouldn't update DB", async () => {
const response = await writethrough.put({ ...first, value: 2 }, DELAY) const response = await writethrough.put({ ...first, value: 2 })
const output = await db.get(response._id) const output = await db.get(response.id)
expect(first._rev).toBe(output._rev) expect(first._rev).toBe(output._rev)
expect(output.value).toBe(1) expect(output.value).toBe(1)
}) })
it("should put it again after delay period", async () => { it("should put it again after delay period", async () => {
tk.freeze(START_DATE + DELAY + 1) tk.freeze(START_DATE + DELAY + 1)
const response = await writethrough.put({ ...first, value: 3 }, DELAY) const response = await writethrough.put({ ...first, value: 3 })
const output = await db.get(response._id) const output = await db.get(response.id)
expect(response._rev).not.toBe(first._rev) expect(response.rev).not.toBe(first._rev)
expect(output.value).toBe(3) expect(output.value).toBe(3)
}) })
}) })

View File

@ -5,7 +5,7 @@ const DEFAULT_WRITE_RATE_MS = 10000
let CACHE: BaseCache | null = null let CACHE: BaseCache | null = null
interface CacheItem { interface CacheItem {
value: any doc: any
lastWrite: number lastWrite: number
} }
@ -17,57 +17,85 @@ async function getCache() {
return CACHE return CACHE
} }
function makeCacheItem(value: any, lastWrite: number | null = null): CacheItem { function makeCacheItem(doc: any, lastWrite: number | null = null): CacheItem {
return { value, lastWrite: lastWrite || Date.now() } return { doc, lastWrite: lastWrite || Date.now() }
} }
export async function put( export async function put(
db: PouchDB.Database, db: PouchDB.Database,
value: any, doc: any,
writeRateMs: number = DEFAULT_WRITE_RATE_MS writeRateMs: number = DEFAULT_WRITE_RATE_MS
) { ) {
const cache = await getCache() const cache = await getCache()
const key = value._id const key = doc._id
let cacheItem: CacheItem | undefined = await cache.get(key) let cacheItem: CacheItem | undefined = await cache.get(key)
const updateDb = !cacheItem || cacheItem.lastWrite < Date.now() - writeRateMs const updateDb = !cacheItem || cacheItem.lastWrite < Date.now() - writeRateMs
let output = value let output = doc
if (updateDb) { if (updateDb) {
// value should contain the _id and _rev // doc should contain the _id and _rev
const response = await db.put(value) const response = await db.put(doc)
output = { output = {
...value, ...doc,
_id: response.id, _id: response.id,
_rev: response.rev, _rev: response.rev,
} }
} }
// if we are updating the DB then need to set the lastWrite to now // if we are updating the DB then need to set the lastWrite to now
cacheItem = makeCacheItem(value, updateDb ? null : cacheItem?.lastWrite) cacheItem = makeCacheItem(output, updateDb ? null : cacheItem?.lastWrite)
await cache.store(key, cacheItem) await cache.store(key, cacheItem)
return output return { ok: true, id: output._id, rev: output._rev }
} }
export async function get(db: PouchDB.Database, id: string): Promise<any> { export async function get(db: PouchDB.Database, id: string): Promise<any> {
const cache = await getCache() const cache = await getCache()
let cacheItem: CacheItem = await cache.get(id) let cacheItem: CacheItem = await cache.get(id)
if (!cacheItem) { if (!cacheItem) {
const value = await db.get(id) const doc = await db.get(id)
cacheItem = makeCacheItem(value) cacheItem = makeCacheItem(doc)
await cache.store(id, cacheItem) await cache.store(id, cacheItem)
} }
return cacheItem.value return cacheItem.doc
}
export async function remove(
db: PouchDB.Database,
docOrId: any,
rev?: any
): Promise<void> {
const cache = await getCache()
if (!docOrId) {
throw new Error("No ID/Rev provided.")
}
const id = typeof docOrId === "string" ? docOrId : docOrId._id
rev = typeof docOrId === "string" ? rev : docOrId._rev
try {
await cache.delete(id)
} finally {
await db.remove(id, rev)
}
} }
export class Writethrough { export class Writethrough {
db: PouchDB.Database db: PouchDB.Database
constructor(db: PouchDB.Database) { writeRateMs: number
constructor(
db: PouchDB.Database,
writeRateMs: number = DEFAULT_WRITE_RATE_MS
) {
this.db = db this.db = db
this.writeRateMs = writeRateMs
} }
async put(value: any, writeRateMs: number = DEFAULT_WRITE_RATE_MS) { async put(doc: any) {
return put(this.db, value, writeRateMs) return put(this.db, doc, this.writeRateMs)
} }
async get(id: string) { async get(id: string) {
return get(this.db, id) return get(this.db, id)
} }
async remove(docOrId: any, rev?: any) {
return remove(this.db, docOrId, rev)
}
} }