Skip to content
This repository was archived by the owner on Jan 26, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions src/MutationBatch.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,26 @@ import type { ParseRequestOptions } from './MutationExecutor';
class MutationBatch {
static maxBatchSize: number;

_aborted: boolean;
_dispatched: boolean;
_requests: Array<ParseRequestOptions>;
_promises: Array<Parse.Promise>;
addRequest: (options: ParseRequestOptions) => Parse.Promise;

constructor() {
this._aborted = false;
this._dispatched = false;
this._requests = [];
this._promises = [];
this.addRequest = this.addRequest.bind(this);
}

getNumberOfRequests(): number {
return this._requests.length;
}

addRequest(options: ParseRequestOptions): Parse.Promise {
if (this._aborted || this._dispatched) {
throw new Error('Cannot add a request to aborted or dispatched batch.');
}
if (this.getNumberOfRequests() === MutationBatch.maxBatchSize) {
throw new Error('Cannot batch more than ' + MutationBatch.maxBatchSize +
' requests at a time.');
Expand All @@ -56,6 +61,10 @@ class MutationBatch {
}

dispatch(): Parse.Promise {
if (this._aborted || this._dispatched) {
throw new Error('Cannot dispatch an already dispatched or aborted batch.');
}
this._dispatched = true;
var requests = this._requests.map((req) => {
var path = '/1/' + req.route;
if (req.className) {
Expand Down Expand Up @@ -90,6 +99,12 @@ class MutationBatch {
return Parse.Promise.error(error);
});
}

abort() {
this._aborted = true;
var error = new Error('Batch was aborted.');
this._promises.forEach((promise) => promise.reject(error));
}
}
MutationBatch.maxBatchSize = 50;

Expand Down
2 changes: 1 addition & 1 deletion src/MutationExecutor.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ function execute(
var className = (typeof target === 'string') ? target : target.className;
var objectId = (typeof target === 'string') ? '' : target.objectId;
var payload;
var request = batch ? batch.addRequest : sendRequest;
var request = batch ? batch.addRequest.bind(batch) : sendRequest;
switch (mutation.action) {
case 'CREATE':
return request({
Expand Down
49 changes: 48 additions & 1 deletion src/__tests__/MutationBatch-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,13 @@ describe('MutationBatch', function() {
expect(thirdPromiseResult).toBe(null);
expect(thirdPromiseError).toEqual(expectedThirdError);
expect(batchPromiseResolved).toBe(true);

// Once dispatched, the batch cannot be dispatched or aborted anymore.
expect(function() { batch.dispatch(); }).toThrow();
expect(function() { batch.abort(); }).toThrow();
});

it('resolves promises even when request fails', function() {
it('rejects promises when the entire request fails', function() {
Parse.XMLHttpRequest = testXHR(
function() {},
function() {},
Expand Down Expand Up @@ -189,6 +193,49 @@ describe('MutationBatch', function() {
expect(firstPromiseError).toBe(secondPromiseError);
expect(batchPromiseError).toBe(firstPromiseError);
expect(batchPromiseSuccess).toBe(false);

// Once dispatched, the batch cannot be dispatched or aborted anymore.
expect(function() { batch.dispatch(); }).toThrow();
expect(function() { batch.abort(); }).toThrow();
});

it('rejects promises when the mutation is aborted', function() {
var batch = new MutationBatch();
var firstPromise = batch.addRequest({
method: 'DELETE',
route: 'classes',
className: 'MadeUpClassName',
objectId: 'randomId',
});
var secondPromise = batch.addRequest({
method: 'CREATE',
route: 'classes',
className: 'MadeUpClassName',
data: {some: 'fields', and: 'stuff'},
});

var firstPromiseResult = null;
var firstPromiseError = null;
var secondPromiseResult = null;
var secondPromiseError = null;
firstPromise.then(
function(result) { firstPromiseResult = result; },
function(error) { firstPromiseError = error; }
);
secondPromise.then(
function(result) { secondPromiseResult = result; },
function(error) { secondPromiseError = error; }
);
batch.abort()

expect(firstPromiseResult).toBe(null);
expect(secondPromiseResult).toBe(null);
expect(firstPromiseError instanceof Error).toBe(true);
expect(secondPromiseError instanceof Error).toBe(true);

// Once aborted, the batch cannot be dispatched or aborted anymore.
expect(function() { batch.dispatch(); }).toThrow();
expect(function() { batch.abort(); }).toThrow();
});

});