-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
queued transaction can be also rollbacked #646
queued transaction can be also rollbacked #646
Conversation
Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have you on file. In order for us to review and merge your code, please sign up at https://code.facebook.com/cla - and if you have received this in error or have any questions, please drop us a line at cla@fb.com. Thanks! |
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks! |
@@ -133,6 +133,20 @@ class RelayMutationQueue { | |||
|
|||
rollback(id: ClientMutationID): void { | |||
const transaction = this._get(id); | |||
|
|||
const collisionKey = transaction.getCollisionKey(); | |||
var collisionQueue = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: use let
here and for index
:)
Can I ask for feedback here? |
const collisionKey = transaction.getCollisionKey(); | ||
const collisionQueue = | ||
collisionKey && this._collisionQueueMap[collisionKey]; | ||
if (collisionQueue) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (collisionKey && collisionQueue) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per @josephsavona, doing the check here makes it so you don't have to do it on line 144. Better yet, you can avoid the redundancy by doing:
if (collisionKey) {
const collisionQueue = this._collisionQueueMap[collisionKey];
if (collisionQueue) {
// Flow now knows that both `collisionKey` and `collisionQueue` are truthy.
}
}
@jardakotesovec Thanks for your contribution. I definitely want to see this fix land, but I have some feedback. |
if (collisionKey && collisionQueue.length === 0) { | ||
delete this._collisionQueueMap[collisionKey]; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To reduce the number of code paths that rollback follows (which just makes the code slightly easier to reason about), what do you think about moving all of this logic into _clearPendingTransaction
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yungsters Thanks a lot for feedback.
collisionQueue
is managed in commit
, _advanceCollisionQueue
, _failCollisionQueue
. So If I move it to _clearPendingTransaction
than both _failCollisionQueue
and _clearPendingTransaction
will try to remove it for certain code path (its necessary to slice() queue in _failCollisionQueue
to iterate it correctly) from the collisionQueue
.
And its not possible just move this responsibility only to _clearPendingTransaction
since its necessary to clean collisionQueue
also for situations when its commited again (not rollbacked).
But if you still prefer it I will move it there and adjust _failCollisionQueue
to deal with that by using slice
and iterating on copy:
_failCollisionQueue(transaction: PendingTransaction): void {
const collisionKey = transaction.getCollisionKey();
if (collisionKey) {
const collisionQueue = nullthrows(this._collisionQueueMap[collisionKey]);
// Remove the transaction that called this function.
collisionQueue.shift();
collisionQueue.slice().forEach(
transaction => this._handleCommitFailure(transaction, null)
);
delete this._collisionQueueMap[collisionKey];
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jardakotesovec Ahh... makes sense. You clearly understand this code better than I do, haha. I'll test this internally and land it. Thanks again!
@facebook-github-bot import |
@yungsters Thanks a lot. Do you have some thoughts on getStatus issue I mentioned in my initial comment? Would be handy if getStatus would return something when its processed instead of exception. |
Thanks for importing. If you are an FB employee go to Phabricator to review. |
Indeed, but the difficultly is in differentiating between completed and invalid IDs. One solution would be to keep around the map of IDs that have been successfully committed, but that will continue to leak memory into the future. Another solution would be to change @josephsavona Do you remember the reason for why we chose to use IDs instead of exposing a public form of the pending transaction (which would have all the methods like |
This is follow up to #607 that adds posibility to rollback transaction with status
COMMIT_QUEUED
.There is one more missing piece for this use case that I was not sure how to approach.
To replace transaction that is queued I need to first check if its status is still
COMMIT_QUEUED
. Issue is that transaction is removed from pendingTransactionMap once its successfully committed. So I can easily end up with exception fromgetStatus()
, which is bit overreaction :-).So maybe return some status like
FINISHED
instead of throwing if its not in pending queue? I am of course very opened about naming :-).