Adds gSheet read cache

This commit is contained in:
forceoranj 2021-11-16 17:32:58 +01:00
parent db3dba7a40
commit cdb6f1c3fe
3 changed files with 70 additions and 36 deletions

64
src/gsheets/DBManager.ts Normal file
View File

@ -0,0 +1,64 @@
const CACHE_RENEW_DELAY = 10000
export default function DBManager<OperationReturn>(): any {
type OperationType = "add" | "list" | "set"
interface Operation {
task: () => Promise<OperationReturn>
type: OperationType
resolve: (value: OperationReturn) => void
reject: (reason: unknown) => void
}
let cache: any
let cacheTime = 0
const operations: Operation[] = []
async function addDBOperation(type: OperationType, task: () => Promise<OperationReturn>) {
console.log(`New ${type} DB Operation in line.`)
return new Promise(
(resolve: (value: OperationReturn) => void, reject: (reason: unknown) => void) => {
operations.push({ task, type, resolve, reject })
if (operations.length === 1) {
runOperation(operations[0])
}
}
)
}
function runNextDBOperation(): void {
operations.shift()
console.log("DB Operation completed.")
if (operations[0]) {
runOperation(operations[0])
}
}
function runOperation(operation: Operation): void {
const { task, type, resolve, reject } = operation
if (type === "list") {
const now = +new Date()
if (now < cacheTime + CACHE_RENEW_DELAY) {
console.log("Using cache")
resolve(cache)
runNextDBOperation()
} else {
console.log("Refreshing cache")
task()
.then((val: OperationReturn) => {
cache = val
cacheTime = now
resolve(val)
})
.catch(reject)
.finally(runNextDBOperation)
}
} else {
cacheTime = 0
task().then(resolve).catch(reject).finally(runNextDBOperation)
}
}
return addDBOperation
}

View File

@ -3,9 +3,9 @@ import _ from "lodash"
import { promises as fs } from "fs"
import { GoogleSpreadsheet, GoogleSpreadsheetWorksheet } from "google-spreadsheet"
import sequentialDBOperations from "./sequentialDBOperations"
import DBManager from "./DBManager"
const addDBOperation = sequentialDBOperations()
const addDBOperation = DBManager()
const SCOPES = ["https://www.googleapis.com/auth/spreadsheets"]
const CRED_PATH = path.resolve(process.cwd(), "access/gsheets.json")
@ -17,7 +17,7 @@ export async function listGet<Element extends ElementWithId>(
specimen: Element
): Promise<Element[]> {
type StringifiedElement = Record<keyof Element, string>
return addDBOperation(async () => {
return addDBOperation("list", async () => {
const sheet = await getGSheet(sheetName)
// Load sheet into an array of objects
@ -57,7 +57,7 @@ export async function setList<Element extends ElementWithId>(
sheetName: string,
elements: Element[]
): Promise<true | undefined> {
return addDBOperation(async () => {
return addDBOperation("listSet", async () => {
const sheet = await getGSheet(sheetName)
// Load sheet into an array of objects
@ -117,7 +117,7 @@ export async function set<Element extends ElementWithId>(
if (!element) {
return undefined
}
return addDBOperation(async () => {
return addDBOperation("set", async () => {
const sheet = await getGSheet(sheetName)
// Load sheet into an array of objects
@ -148,7 +148,7 @@ export async function add<ElementNoId extends object, Element extends ElementNoI
if (!partialElement) {
return undefined
}
return addDBOperation(async () => {
return addDBOperation("add", async () => {
const sheet = await getGSheet(sheetName)
// Load sheet into an array of objects

View File

@ -1,30 +0,0 @@
export default function sequentialDBOperations<OperationReturn>(): any {
interface Operation {
task: () => Promise<OperationReturn>
resolve: (value: OperationReturn) => void
reject: (reason: unknown) => void
}
const operations: Operation[] = []
async function addDBOperation(task: () => Promise<OperationReturn>) {
return new Promise(
(resolve: (value: OperationReturn) => void, reject: (reason: unknown) => void) => {
operations.push({ task, resolve, reject })
if (operations.length === 1) {
task().then(resolve).catch(reject).finally(runNextDBOperation)
}
}
)
}
function runNextDBOperation(): void {
operations.shift()
if (operations[0]) {
const { task, resolve, reject } = operations[0]
task().then(resolve).catch(reject).finally(runNextDBOperation)
}
}
return addDBOperation
}