-
-
Notifications
You must be signed in to change notification settings - Fork 626
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Transaction context is lost when running a recursive call in a loop #1996
Comments
To make transaction context kept correctly in async functions, dexie need to schedule context maintainance. This will only be done if the callback to db.transaction is an async function. In this case it seems to be a mix where the root transaction has a non-async callback so it doesnt do the extra care for async context handling and then it enters a sub transaction with an async function. Either mark the root transaction callback as async, or if you are more confident with explicit transaction arguments instead of relying on Dexie.currentTransaction, use the tx argument to your callback: db.transaction('rw', db.nodes, async (tx) => {
const nodes = await tx.nodes.toArray(); // instead of db.nodes.toArray();
}); |
Thanks for the quick reply. this change is available in code sandbox as well |
I found a wired solution but don't know why it is working, here is a video explanation. |
The reason it started working when skipping await is most likely that the little "await" will jump out of the current scope and lose the context unless everything is awaited properly. The forEach loop spawns multiple async tasks in parallell things without awaiting them. If consistently awaiting all spawned promises, it should work. const onClickCall = () => {
// calling all methods in a for loop wrapped in a transaction.
// here there is no await in transaction
db.transaction("rw", db.nodes, async () => {
await Promise.all(
methods.map((met) => {
return met();
})
);
});
}; There might be other places too where promises aren't awaited. But if awaiting these promises are overkill, and you want to have an non-magical control over the current transaction, I recommend to use the tx argument instead. |
Thanks then we have 2 solutions for this.
@dfahlander https://drive.google.com/file/d/1gF5SEehYfGb0cUm5bvMKO3Q_-IqhWhlh/view?usp=sharing |
One more last question I have (just trying to understand how things are working). If I remove the recursive call function getParentNodes, even though I have not awaited properly this works. if you want more context on the question below is a screen recording. https://drive.google.com/file/d/1oj3heM91GTVb9NqTO2WCDtzSXSDHGIy6/view?usp=sharing |
Correct. When using the provided tx argument, the code is keeping the transaction alive by doing work on it. This prevents the transaction from auto-committing. Dexie listens to IDBTransaction event "success" event which will be fired when no more work are put onto the transaction.
The trickiest part with keeping context alive across async calls is when awaiting things that never performs any dexie tasks. This is probably the case when getParentNode falls into returning [] because node is falsy. We schedule context switching in advance to support those situations but this only works when the callback to db.transacation is an async function and when all things are awaited properly. When having a complex setup with recursive sub transactions that you have, this can affect performance and you are probably better of using the provided tx. As soon as this lovely stage 2 TC39 proposal is going public, Dexie will be able to use that API instead to keep contexts between awaits. Until then, transaction context can be lost if not declaring the callback async or not awaiting promises properly. |
@dfahlander |
Transaction context is lost when running a recursive call in a loop.
Below is codesandbox to reproduce this error.
https://codesandbox.io/p/sandbox/dexie-issue-cxkwvj
Also, I have attached below screen recording on how to reproduce this error.
https://drive.google.com/file/d/1U7GpJ-fGLjX01XaikBNrMUB1P2Cn2GFs/view?usp=sharing
I am not able to understand why this error is happening.
The text was updated successfully, but these errors were encountered: