Skip to content

Commit e2d2284

Browse files
committed
fix(tables): serialize default view demotions
1 parent dac94a3 commit e2d2284

2 files changed

Lines changed: 14 additions & 5 deletions

File tree

apps/sim/lib/table/views/service.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,15 @@ describe('default-view writers share the views lock', () => {
764764
expect(dbChainMockFns.execute).toHaveBeenCalled()
765765
})
766766

767+
it('demoting a view takes the same advisory lock as other default-state writers', async () => {
768+
queueTableRows(tableViews, [{ ...viewRow, isDefault: true }])
769+
dbChainMockFns.returning.mockResolvedValueOnce([{ ...viewRow, isDefault: false }])
770+
771+
await updateTableView({ viewId: 'view-1', tableId: 'table-1', isDefault: false, columns })
772+
773+
expect(dbChainMockFns.execute).toHaveBeenCalled()
774+
})
775+
767776
it('a rename stays a plain transaction, off the lock', async () => {
768777
queueTableRows(tableViews, [{ id: 'view-1' }])
769778
dbChainMockFns.returning.mockResolvedValueOnce([{ ...viewRow, name: 'Renamed' }])

apps/sim/lib/table/views/service.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -541,14 +541,14 @@ export interface UpdateTableViewData {
541541
* the references that row already carries stay writable — see
542542
* {@link normalizeViewConfigForStorage}.
543543
*
544-
* Promotion demotes siblings, so it contends with {@link createTableView}'s
545-
* default-on-create path; both serialize on the same per-table views lock, or
546-
* the partial unique index fails one of two valid writes. Plain patches (layout
547-
* autosave, renames) touch only their own row and skip the lock.
544+
* Every explicit default-state change contends with {@link createTableView}'s
545+
* default-on-create path, so promotions and demotions serialize on the same
546+
* per-table views lock. Plain patches (layout autosave, renames) touch only
547+
* their own row and skip the lock.
548548
*/
549549
export async function updateTableView(data: UpdateTableViewData): Promise<TableView | null> {
550550
const runWrite = <T>(write: (trx: DbTransaction) => Promise<T>): Promise<T> =>
551-
data.isDefault === true ? withTableViewsLock(data.tableId, write) : db.transaction(write)
551+
data.isDefault !== undefined ? withTableViewsLock(data.tableId, write) : db.transaction(write)
552552
const outcome = await runWrite(async (tx) => {
553553
// Confirm the target exists BEFORE demoting. The demotion has to run first —
554554
// the partial unique index rejects a second default — but on a PATCH naming a

0 commit comments

Comments
 (0)