import stampit from 'stampit';
import _ from 'lodash';
import Request from './request';
/**
* Manager for handling batch requests to the platform. Supported actions are 'create', 'update', 'delete'. Meant to be used directly form the {@link Syncano} instance.
*
* @constructor
* @type {BatchManager}
*
* @example {@lang javascript}
* const connection = Syncano();
* const manager = connection.BatchManager({instanceName});
* manager.addObjects({ object: DataObject({data}), action: 'save' }, { object: DataObject({other_data}), action: 'create' });
* manager.batch().then(() => {
* // success
* })
*
* @example {@lang javascript}
* const connection = Syncano();
* const manager = connection.BatchManager({instanceName});
* manager.addSingleObject(DataObject({data}), 'create');
* manager.batch().then(() => {
* // success
* })
*/
const BatchManager = stampit()
.compose(Request)
.props({
objects: [],
batchUrl: '/v1.1/instances/{instance}/batch/',
maxBatchObjects: 50
})
.init(function() {
if(!_.has(this, 'instanceName') && !_.has(this.getDefaultProperties(), 'instanceName')) {
throw new Error('No instance name specified.');
}
this.instanceName = this.instanceName || this.getDefaultProperties().instanceName;
this.batchUrl = _.replace(this.batchUrl, '{instance}', this.instanceName);
})
.methods({
addObjects(...objects) {
this.validateObjectsLength(_.size(_.flatten(objects)));
_.each(objects, (object) => {
this.objects = _.concat(this.objects, object);
});
this.objects = _.flatten(this.objects);
if(!_.every(this.objects, (object) => {
return _.has(object, 'object._meta') && _.has(object, 'action');
})) {
this.removeObjects();
throw new Error('The Batch Manager only accepts properly formatted objects.');
}
return this;
},
addObjectsFromArray(objects, action) {
this.validateObjectsLength(objects.length);
_.each(objects, (object) => {
this.objects = _.concat(this.objects, { object, action });
});
return this;
},
addSingleObject(object, action) {
if(!_.has(object, '_meta')) {
throw new Error('The supplied object is not a valid object.');
}
this.validateObjectsLength(1);
this.objects = _.concat(this.objects, { object, action });
return this;
},
batch() {
if(_.isEmpty(this.objects)) {
throw new Error('No objects provided for batching.');
}
const requests = _.map(this.objects, (batch) => batch.object.toBatchObject(batch.action));
return this.makeRequest('POST', this.batchUrl, { payload: {requests}});
},
validateObjectsLength(length) {
const existingLength = _.size(this.objects);
if(_.add(existingLength, length) > this.maxBatchObjects) {
throw new Error('Only 50 objects can be batched at once.');
}
},
removeObjects() {
this.objects = [];
return this;
},
getObjects() {
return this.objects;
}
});
export default BatchManager;