Files
kami-parse-server/src/ParseServerRESTController.js
Antonio Davi Macedo Coelho de Castro 8b97c1380b Batch transaction (#5849)
* Batch transaction boilerplate

* Refactoring transaction boilerplate

* Independent sessions test

* Transactions - partial

* Missing only one test

* All tests passing for mongo db

* Tests on Travis

* Transactions on postgres

* Fix travis to restart mongodb

* Remove mongodb service and keep only mongodb runner

* MongoDB service back

* Initialize replicaset

* Remove mongodb runner again

* Again only with mongodb-runner and removing cache

* Trying with pretest and posttest

* WiredTiger

* Pretest and posttest again

* Removing inexistent scripts

* wiredTiger

* One more attempt

* Trying another way to run mongodb-runner

* Fixing tests

* Include batch transaction on direct access

* Add tests to direct access
2019-07-31 02:41:07 -07:00

150 lines
4.1 KiB
JavaScript

const Config = require('./Config');
const Auth = require('./Auth');
const RESTController = require('parse/lib/node/RESTController');
const URL = require('url');
const Parse = require('parse/node');
function getSessionToken(options) {
if (options && typeof options.sessionToken === 'string') {
return Promise.resolve(options.sessionToken);
}
return Promise.resolve(null);
}
function getAuth(options = {}, config) {
const installationId = options.installationId || 'cloud';
if (options.useMasterKey) {
return Promise.resolve(
new Auth.Auth({ config, isMaster: true, installationId })
);
}
return getSessionToken(options).then(sessionToken => {
if (sessionToken) {
options.sessionToken = sessionToken;
return Auth.getAuthForSessionToken({
config,
sessionToken: sessionToken,
installationId,
});
} else {
return Promise.resolve(new Auth.Auth({ config, installationId }));
}
});
}
function ParseServerRESTController(applicationId, router) {
function handleRequest(method, path, data = {}, options = {}, config) {
// Store the arguments, for later use if internal fails
const args = arguments;
if (!config) {
config = Config.get(applicationId);
}
const serverURL = URL.parse(config.serverURL);
if (path.indexOf(serverURL.path) === 0) {
path = path.slice(serverURL.path.length, path.length);
}
if (path[0] !== '/') {
path = '/' + path;
}
if (path === '/batch') {
let initialPromise = Promise.resolve();
if (data.transaction === true) {
initialPromise = config.database.createTransactionalSession();
}
return initialPromise.then(() => {
const promises = data.requests.map(request => {
return handleRequest(
request.method,
request.path,
request.body,
options,
config
).then(
response => {
return Promise.resolve({ success: response });
},
error => {
if (data.transaction === true) {
return Promise.reject(error);
}
return Promise.resolve({
error: { code: error.code, error: error.message },
});
}
);
});
return Promise.all(promises)
.catch(error => {
if (data.transaction === true) {
return config.database.abortTransactionalSession().then(() => {
throw error;
});
} else {
throw error;
}
})
.then(result => {
if (data.transaction === true) {
return config.database.commitTransactionalSession().then(() => {
return result;
});
} else {
return result;
}
});
});
}
let query;
if (method === 'GET') {
query = data;
}
return new Promise((resolve, reject) => {
getAuth(options, config).then(auth => {
const request = {
body: data,
config,
auth,
info: {
applicationId: applicationId,
sessionToken: options.sessionToken,
},
query,
};
return Promise.resolve()
.then(() => {
return router.tryRouteRequest(method, path, request);
})
.then(
response => {
resolve(response.response, response.status, response);
},
err => {
if (
err instanceof Parse.Error &&
err.code == Parse.Error.INVALID_JSON &&
err.message == `cannot route ${method} ${path}`
) {
RESTController.request.apply(null, args).then(resolve, reject);
} else {
reject(err);
}
}
);
}, reject);
});
}
return {
request: handleRequest,
ajax: RESTController.ajax,
};
}
export default ParseServerRESTController;
export { ParseServerRESTController };