Skip to content

Commit

Permalink
fix(core): make sure batching finishes if exception is thrown (#3216)
Browse files Browse the repository at this point in the history
incrementing and decrementing transactions need to happen in an atomic operation, no matter what happens in between; if we increment, but never decrement, we will get to a state where transactions can never become zero - we're basically "leaking" an open transaction. This leads to no observers being informed ever again because we think we still have an open transaction

this can be fixed by using try/finally to always decrement the transactions
  • Loading branch information
TkDodo committed Jan 21, 2022
1 parent f5a0cec commit c532d81
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 4 deletions.
12 changes: 8 additions & 4 deletions src/core/notifyManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,15 @@ export class NotifyManager {
}

batch<T>(callback: () => T): T {
let result
this.transactions++
const result = callback()
this.transactions--
if (!this.transactions) {
this.flush()
try {
result = callback()
} finally {
this.transactions--
if (!this.transactions) {
this.flush()
}
}
return result
}
Expand Down
15 changes: 15 additions & 0 deletions src/core/tests/notifyManager.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,19 @@ describe('notifyManager', () => {
expect(callbackBatchLevel2Spy).toHaveBeenCalledTimes(1)
expect(callbackScheduleSpy).toHaveBeenCalledTimes(1)
})

it('should flush if error is thrown', () => {
const notifyManagerTest = new NotifyManager()
const flushSpy = jest.fn()

notifyManagerTest.flush = flushSpy

try {
notifyManagerTest.batch(() => {
throw new Error('Foo')
})
} catch {}

expect(flushSpy).toHaveBeenCalledTimes(1)
})
})

1 comment on commit c532d81

@vercel
Copy link

@vercel vercel bot commented on c532d81 Jan 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.