Makes all gSheet calls sequential

This commit is contained in:
forceoranj 2021-11-16 16:33:01 +01:00
parent bf62510d0a
commit db3dba7a40
2 changed files with 142 additions and 96 deletions

View File

@ -3,6 +3,10 @@ import _ from "lodash"
import { promises as fs } from "fs"
import { GoogleSpreadsheet, GoogleSpreadsheetWorksheet } from "google-spreadsheet"
import sequentialDBOperations from "./sequentialDBOperations"
const addDBOperation = sequentialDBOperations()
const SCOPES = ["https://www.googleapis.com/auth/spreadsheets"]
const CRED_PATH = path.resolve(process.cwd(), "access/gsheets.json")
@ -13,6 +17,7 @@ export async function listGet<Element extends ElementWithId>(
specimen: Element
): Promise<Element[]> {
type StringifiedElement = Record<keyof Element, string>
return addDBOperation(async () => {
const sheet = await getGSheet(sheetName)
// Load sheet into an array of objects
@ -35,6 +40,7 @@ export async function listGet<Element extends ElementWithId>(
})
return elements
})
}
export async function get<Element extends ElementWithId>(
@ -42,6 +48,7 @@ export async function get<Element extends ElementWithId>(
membreId: number,
specimen: Element
): Promise<Element | undefined> {
// No need to addDBOperation here, since listGet does it already
const list = await listGet<Element>(sheetName, specimen)
return list.find((element) => element.id === membreId)
}
@ -50,6 +57,7 @@ export async function setList<Element extends ElementWithId>(
sheetName: string,
elements: Element[]
): Promise<true | undefined> {
return addDBOperation(async () => {
const sheet = await getGSheet(sheetName)
// Load sheet into an array of objects
@ -57,7 +65,10 @@ export async function setList<Element extends ElementWithId>(
if (!rows[0]) {
throw new Error(`No column types defined in sheet ${sheetName}`)
}
const types = _.pick(rows[0], Object.keys(elements[0] || {})) as Record<keyof Element, string>
const types = _.pick(rows[0], Object.keys(elements[0] || {})) as Record<
keyof Element,
string
>
// Update received rows
let rowid = 1
@ -96,6 +107,7 @@ export async function setList<Element extends ElementWithId>(
}
return true
})
}
export async function set<Element extends ElementWithId>(
@ -105,6 +117,7 @@ export async function set<Element extends ElementWithId>(
if (!element) {
return undefined
}
return addDBOperation(async () => {
const sheet = await getGSheet(sheetName)
// Load sheet into an array of objects
@ -124,6 +137,7 @@ export async function set<Element extends ElementWithId>(
Object.assign(row, stringifiedRow)
await row.save()
return element
})
}
// eslint-disable-next-line @typescript-eslint/ban-types
@ -134,6 +148,7 @@ export async function add<ElementNoId extends object, Element extends ElementNoI
if (!partialElement) {
return undefined
}
return addDBOperation(async () => {
const sheet = await getGSheet(sheetName)
// Load sheet into an array of objects
@ -159,6 +174,7 @@ export async function add<ElementNoId extends object, Element extends ElementNoI
await sheet.addRow(stringifiedRow)
return element
})
}
async function getGSheet(sheetName: string): Promise<GoogleSpreadsheetWorksheet> {

View File

@ -0,0 +1,30 @@
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
}