Skip to content

Commit

Permalink
queued transaction can be also rollbacked
Browse files Browse the repository at this point in the history
Summary: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 from `getStatus()`, 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 :-).
Closes #646

Reviewed By: josephsavona

Differential Revision: D3021199

Pulled By: yungsters

fb-gh-sync-id: 2ee1d2849d8bd5081ef57a42c136d644b61e95bd
shipit-source-id: 2ee1d2849d8bd5081ef57a42c136d644b61e95bd
  • Loading branch information
jardakotesovec authored and Facebook Github Bot 7 committed Mar 8, 2016
1 parent c63365e commit 5ca0607
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 2 deletions.
13 changes: 13 additions & 0 deletions src/mutation/RelayMutationQueue.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,19 @@ class RelayMutationQueue {

rollback(id: ClientMutationID): void {
const transaction = this._get(id);
const collisionKey = transaction.getCollisionKey();
if (collisionKey) {
const collisionQueue = this._collisionQueueMap[collisionKey];
if (collisionQueue) {
const index = collisionQueue.indexOf(transaction);
if (index !== -1) {
collisionQueue.splice(index, 1);
}
if (collisionQueue.length === 0) {
delete this._collisionQueueMap[collisionKey];
}
}
}
this._handleRollback(transaction);
}

Expand Down
6 changes: 4 additions & 2 deletions src/mutation/RelayMutationTransaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,11 @@ class RelayMutationTransaction {
invariant(
status === RelayMutationTransactionStatus.UNCOMMITTED ||
status === RelayMutationTransactionStatus.COMMIT_FAILED ||
status === RelayMutationTransactionStatus.COLLISION_COMMIT_FAILED,
status === RelayMutationTransactionStatus.COLLISION_COMMIT_FAILED ||
status === RelayMutationTransactionStatus.COMMIT_QUEUED,
'RelayMutationTransaction: Only transactions with status `UNCOMMITTED` ' +
'`COMMIT_FAILED` or `COLLISION_COMMIT_FAILED` can be rolledback.'
'`COMMIT_FAILED`, `COLLISION_COMMIT_FAILED`, or `COMMIT_QUEUED` can be ' +
'rolled back.'
);

this._mutationQueue.rollback(this._id);
Expand Down
64 changes: 64 additions & 0 deletions src/mutation/__tests__/RelayMutationQueue-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -515,4 +515,68 @@ describe('RelayMutationQueue', () => {
expect(successCallback1).toBeCalled();
});
});

describe('rollback', () => {
var fatQuery;
var mockMutation1;
var mutationNode;

beforeEach(() => {
fatQuery = Relay.QL`fragment on Comment @relay(pattern: true) {
... on Comment {
doesViewerLike
}
}`;
mutationNode = Relay.QL`mutation{commentCreate(input:$input)}`;
RelayMutation.prototype.getFatQuery.mockReturnValue(fatQuery);
RelayMutation.prototype.getMutation.mockReturnValue(mutationNode);
RelayMutation.prototype.getCollisionKey.mockReturnValue('key');
RelayMutation.prototype.getVariables.mockReturnValue({});
RelayMutation.prototype.getConfigs.mockReturnValue('configs');

mockMutation1 = new RelayMutation();
mockMutation1.getCollisionKey.mockReturnValue('key');
});

it('rollback queued transaction', () => {
var transaction1 = mutationQueue.createTransaction(mockMutation1);
transaction1.commit();

expect(transaction1.getStatus()).toBe(
RelayMutationTransactionStatus.COMMITTING
);

var transaction2 = mutationQueue.createTransaction(mockMutation1);
transaction2.commit();

expect(transaction2.getStatus()).toBe(
RelayMutationTransactionStatus.COMMIT_QUEUED
);

var transaction3 = mutationQueue.createTransaction(mockMutation1);
transaction3.commit();

expect(transaction3.getStatus()).toBe(
RelayMutationTransactionStatus.COMMIT_QUEUED
);

expect(networkLayer.sendMutation.mock.calls.length).toBe(1);

transaction2.rollback();

expect(() => transaction2.getStatus()).toFailInvariant(
'RelayMutationQueue: `1` is not a valid pending transaction ID.'
);

var request = networkLayer.sendMutation.mock.calls[0][0];
request.resolve({response: {'res': 'ponse'}});
jest.runAllTimers();

expect(networkLayer.sendMutation.mock.calls.length).toBe(2);

expect(transaction3.getStatus()).toBe(
RelayMutationTransactionStatus.COMMITTING
);
});
});
});

0 comments on commit 5ca0607

Please sign in to comment.