1
0
Fork 0
mirror of synced 2024-07-08 15:56:23 +12:00

Fix concurrent saves

This commit is contained in:
Adria Navarro 2023-12-21 17:14:34 +01:00
parent c0a19c2a7e
commit 0c77cf2b40
3 changed files with 31 additions and 13 deletions

View file

@ -5,8 +5,8 @@ import {
processFormulas, processFormulas,
} from "../../../utilities/rowProcessor" } from "../../../utilities/rowProcessor"
import { FieldTypes, FormulaTypes } from "../../../constants" import { FieldTypes, FormulaTypes } from "../../../constants"
import { context } from "@budibase/backend-core" import { context, locks } from "@budibase/backend-core"
import { Table, Row } from "@budibase/types" import { Table, Row, LockType, LockName } from "@budibase/types"
import * as linkRows from "../../../db/linkedRows" import * as linkRows from "../../../db/linkedRows"
import sdk from "../../../sdk" import sdk from "../../../sdk"
import isEqual from "lodash/isEqual" import isEqual from "lodash/isEqual"
@ -149,12 +149,22 @@ export async function finaliseRow(
await db.put(table) await db.put(table)
} catch (err: any) { } catch (err: any) {
if (err.status === 409) { if (err.status === 409) {
const updatedTable = await sdk.tables.getTable(table._id!) // Some conflicts with the autocolumns occurred, we need to refetch the table and recalculate
let response = processAutoColumn(null, updatedTable, row, { await locks.doWithLock(
reprocessing: true, {
}) type: LockType.AUTO_EXTEND,
await db.put(response.table) name: LockName.PROCESS_AUTO_COLUMNS,
row = response.row resource: table._id,
},
async () => {
const latestTable = await sdk.tables.getTable(table._id!)
let response = processAutoColumn(null, latestTable, row, {
reprocessing: true,
})
await db.put(response.table)
row = response.row
}
)
} else { } else {
throw err throw err
} }

View file

@ -189,25 +189,32 @@ describe("sdk >> rows >> internal", () => {
}) })
await config.doInContext(config.appId, async () => { await config.doInContext(config.appId, async () => {
for (const row of makeRows(30)) { for (const row of makeRows(5)) {
await internalSdk.save(table._id!, row, config.user._id) await internalSdk.save(table._id!, row, config.user._id)
} }
await Promise.all( await Promise.all(
makeRows(200).map(row => makeRows(10).map(row =>
internalSdk.save(table._id!, row, config.user._id) internalSdk.save(table._id!, row, config.user._id)
) )
) )
for (const row of makeRows(20)) { for (const row of makeRows(5)) {
await internalSdk.save(table._id!, row, config.user._id) await internalSdk.save(table._id!, row, config.user._id)
} }
}) })
const persistedRows = await config.getRows(table._id!) const persistedRows = await config.getRows(table._id!)
expect(persistedRows).toHaveLength(250) expect(persistedRows).toHaveLength(20)
expect(persistedRows).toEqual(
expect.arrayContaining(
Array.from({ length: 20 }).map((_, i) =>
expect.objectContaining({ id: i + 1 })
)
)
)
const persistedTable = await config.getTable(table._id) const persistedTable = await config.getTable(table._id)
expect((table as any).schema.id.lastID).toBe(0) expect((table as any).schema.id.lastID).toBe(0)
expect(persistedTable.schema.id.lastID).toBe(250) expect(persistedTable.schema.id.lastID).toBe(20)
}) })
}) })
}) })

View file

@ -21,6 +21,7 @@ export enum LockName {
PERSIST_WRITETHROUGH = "persist_writethrough", PERSIST_WRITETHROUGH = "persist_writethrough",
QUOTA_USAGE_EVENT = "quota_usage_event", QUOTA_USAGE_EVENT = "quota_usage_event",
APP_MIGRATION = "app_migrations", APP_MIGRATION = "app_migrations",
PROCESS_AUTO_COLUMNS = "process_auto_columns",
} }
export type LockOptions = { export type LockOptions = {