fix: db lock operations (#2479)

* fix: advisory lock for page move

* fix: lock role count check
This commit is contained in:
Philip Okugbe
2026-09-08 13:16:56 +01:00
committed by GitHub
parent 949072744d
commit 5792fc7ca2
6 changed files with 348 additions and 205 deletions
@@ -161,6 +161,22 @@ export class PageRepo {
return result;
}
async lockPageHierarchySpaces(
spaceIds: string[],
trx: KyselyTransaction,
): Promise<void> {
const sortedSpaceIds = [...new Set(spaceIds)].sort();
for (const spaceId of sortedSpaceIds) {
await sql`
SELECT pg_advisory_xact_lock(
hashtext('page-hierarchy'),
hashtext(${spaceId})
)
`.execute(trx);
}
}
async insertPage(
insertablePage: InsertablePage,
trx?: KyselyTransaction,
@@ -489,9 +505,9 @@ export class PageRepo {
async getPageAndDescendants(
parentPageId: string,
opts: { includeContent: boolean },
opts: { includeContent: boolean; trx?: KyselyTransaction },
) {
return this.db
return dbOrTx(this.db, opts.trx)
.withRecursive('page_hierarchy', (db) =>
db
.selectFrom('pages')
@@ -535,6 +551,36 @@ export class PageRepo {
.execute();
}
async isPageDescendant(
ancestorPageId: string,
descendantPageId: string,
trx?: KyselyTransaction,
): Promise<boolean> {
const result = await dbOrTx(this.db, trx)
.withRecursive('page_ancestors', (db) =>
db
.selectFrom('pages')
.select(['id', 'parentPageId'])
.where('id', '=', descendantPageId)
.union((exp) =>
exp
.selectFrom('pages as parent')
.select(['parent.id', 'parent.parentPageId'])
.innerJoin(
'page_ancestors as ancestor',
'ancestor.parentPageId',
'parent.id',
),
),
)
.selectFrom('page_ancestors')
.select('id')
.where('id', '=', ancestorPageId)
.executeTakeFirst();
return Boolean(result);
}
/**
* Get page and all descendants, excluding restricted pages and their subtrees.
* More efficient than getPageAndDescendants + filtering because: