prevent double apply of transactions (#5990)

Signed-off-by: Vyacheslav Tumanov <me@slavatumanov.me>
This commit is contained in:
Vyacheslav Tumanov 2024-07-10 16:14:30 +05:00 committed by GitHub
parent 2d8f0ebfec
commit 55af032065
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 28 additions and 14 deletions

View File

@ -96,6 +96,7 @@ class ClientImpl implements AccountClient, BackupClient {
notify?: (...tx: Tx[]) => void
hierarchy!: Hierarchy
model!: ModelDb
private readonly appliedModelTransactions = new Set<Ref<Tx>>()
constructor (private readonly conn: ClientConnection) {}
setModel (hierarchy: Hierarchy, model: ModelDb): void {
@ -147,6 +148,7 @@ class ClientImpl implements AccountClient, BackupClient {
if (tx.objectSpace === core.space.Model) {
this.hierarchy.tx(tx)
await this.model.tx(tx)
this.appliedModelTransactions.add(tx._id)
}
// We need to handle it on server, before performing local live query updates.
return await this.conn.tx(tx)
@ -156,8 +158,13 @@ class ClientImpl implements AccountClient, BackupClient {
for (const t of tx) {
try {
if (t.objectSpace === core.space.Model) {
this.hierarchy.tx(t)
await this.model.tx(t)
const hasTx = this.appliedModelTransactions.has(t._id)
if (!hasTx) {
this.hierarchy.tx(t)
await this.model.tx(t)
} else {
this.appliedModelTransactions.delete(t._id)
}
}
} catch (err) {
console.error('failed to apply model transaction, skipping', t)

View File

@ -281,13 +281,17 @@ describe('query', () => {
const expectedLength = 2
let attempt = 0
let x: undefined | ((s: any) => void)
const y = new Promise((resolve) => (x = resolve))
const pp = new Promise((resolve) => {
liveQuery.query<Space>(core.class.Space, { private: false }, (result) => {
expect(result).toHaveLength(expectedLength - attempt)
if (attempt === 0) x?.(null)
if (attempt++ === expectedLength) resolve(null)
})
})
await y
const spaces = await liveQuery.findAll(core.class.Space, {})
for (const space of spaces) {
await factory.removeDoc(space._class, space.space, space._id)
@ -298,13 +302,16 @@ describe('query', () => {
it('remove with limit', async () => {
const { liveQuery, factory } = await getClient()
const expectedLength = 1
const expectedLength = 2
let attempt = 0
let x: undefined | ((s: any) => void)
const y = new Promise((resolve) => (x = resolve))
const pp = new Promise((resolve) => {
liveQuery.query<Space>(
core.class.Space,
{ private: false },
(result) => {
if (attempt === 0) x?.(null)
expect(result).toHaveLength(attempt++ === expectedLength ? 0 : 1)
if (attempt === expectedLength) resolve(null)
},
@ -312,6 +319,7 @@ describe('query', () => {
)
})
await y
const spaces = await liveQuery.findAll(core.class.Space, {})
for (const space of spaces) {
await factory.removeDoc(space._class, space.space, space._id)
@ -415,6 +423,14 @@ describe('query', () => {
} else {
expect(comment.$lookup?.space).toBeUndefined()
attempt++
void factory.createDoc(
core.class.Space,
futureSpace.space,
{
...futureSpace
},
futureSpace._id
)
}
}
},
@ -422,14 +438,6 @@ describe('query', () => {
)
})
await factory.createDoc(
core.class.Space,
futureSpace.space,
{
...futureSpace
},
futureSpace._id
)
await pp
})
@ -580,6 +588,7 @@ describe('query', () => {
} else {
expect((comment.$lookup?.space as Doc)?._id).toEqual(futureSpace)
attempt++
void factory.removeDoc(core.class.Space, core.space.Model, futureSpace)
}
}
},
@ -587,8 +596,6 @@ describe('query', () => {
)
})
await factory.removeDoc(core.class.Space, core.space.Model, futureSpace)
await pp
})