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