7.2 KiB
//////////////////////////////////////////////////////////////////////////////// /// @startDocuBlock JSF_post_api_transaction /// @brief execute a server-side transaction /// /// @RESTHEADER{POST /_api/transaction, Execute transaction} /// /// @RESTBODYPARAM{collections,string,required,string} /// contains the array of collections to be used in the /// transaction (mandatory). collections must be a JSON object that can /// have the optional sub-attributes read and write. read /// and write must each be either arrays of collections names or strings /// with a single collection name. /// /// @RESTBODYPARAM{action,string,required,string} /// the actual transaction operations to be executed, in the /// form of stringified JavaScript code. The code will be executed on server /// side, with late binding. It is thus critical that the code specified in /// action properly sets up all the variables it needs. /// If the code specified in action ends with a return statement, the /// value returned will also be returned by the REST API in the result /// attribute if the transaction committed successfully. /// /// @RESTBODYPARAM{waitForSync,boolean,optional,boolean} /// an optional boolean flag that, if set, will force the /// transaction to write all data to disk before returning. /// /// @RESTBODYPARAM{lockTimeout,integer,optional,int64} /// an optional numeric value that can be used to set a /// timeout for waiting on collection locks. If not specified, a default /// value will be used. Setting lockTimeout to 0 will make ArangoDB /// not time out waiting for a lock. /// /// @RESTBODYPARAM{params,string,optional,string} /// optional arguments passed to action. /// /// @RESTDESCRIPTION /// /// Contains the collections and action. /// /// The transaction description must be passed in the body of the POST request. /// /// If the transaction is fully executed and committed on the server, /// HTTP 200 will be returned. Additionally, the return value of the /// code defined in action will be returned in the result attribute. /// /// For successfully committed transactions, the returned JSON object has the /// following properties: /// /// - error: boolean flag to indicate if an error occurred (false /// in this case) /// /// - code: the HTTP status code /// /// - result: the return value of the transaction /// /// If the transaction specification is either missing or malformed, the server /// will respond with HTTP 400. /// /// The body of the response will then contain a JSON object with additional error /// details. The object has the following attributes: /// /// - error: boolean flag to indicate that an error occurred (true in this case) /// /// - code: the HTTP status code /// /// - errorNum: the server error number /// /// - errorMessage: a descriptive error message /// /// If a transaction fails to commit, either by an exception thrown in the /// action code, or by an internal error, the server will respond with /// an error. /// Any other errors will be returned with any of the return codes /// HTTP 400, HTTP 409, or HTTP 500. /// /// @RESTRETURNCODES /// /// @RESTRETURNCODE{200} /// If the transaction is fully executed and committed on the server, /// HTTP 200 will be returned. /// /// @RESTRETURNCODE{400} /// If the transaction specification is either missing or malformed, the server /// will respond with HTTP 400. /// /// @RESTRETURNCODE{404} /// If the transaction specification contains an unknown collection, the server /// will respond with HTTP 404. /// /// @RESTRETURNCODE{500} /// Exceptions thrown by users will make the server respond with a return code of /// HTTP 500 /// /// @EXAMPLES /// /// Executing a transaction on a single collection /// /// @EXAMPLE_ARANGOSH_RUN{RestTransactionSingle} /// var cn = "products"; /// db._drop(cn); /// var products = db._create(cn); /// var url = "/_api/transaction"; /// var body = { /// collections: { /// write : "products" /// }, /// action: "function () { var db = require('internal').db; db.products.save({}); return db.products.count(); }" /// }; /// /// var response = logCurlRequest('POST', url, body); /// assert(response.code === 200); /// /// logJsonResponse(response); /// db._drop(cn); /// @END_EXAMPLE_ARANGOSH_RUN /// /// Executing a transaction using multiple collections /// /// @EXAMPLE_ARANGOSH_RUN{RestTransactionMulti} /// var cn1 = "materials"; /// db._drop(cn1); /// var materials = db._create(cn1); /// var cn2 = "products"; /// db._drop(cn2); /// var products = db._create(cn2); /// products.save({ "a": 1}); /// materials.save({ "b": 1}); /// var url = "/_api/transaction"; /// var body = { /// collections: { /// write : [ "products", "materials" ] /// }, /// action: ( /// "function () {" + /// "var db = require('internal').db;" + /// "db.products.save({});" + /// "db.materials.save({});" + /// "return 'worked!';" + /// "}" /// ) /// }; /// /// var response = logCurlRequest('POST', url, body); /// assert(response.code === 200); /// /// logJsonResponse(response); /// db._drop(cn1); /// db._drop(cn2); /// @END_EXAMPLE_ARANGOSH_RUN /// /// Aborting a transaction due to an internal error /// /// @EXAMPLE_ARANGOSH_RUN{RestTransactionAbortInternal} /// var cn = "products"; /// db._drop(cn); /// var products = db._create(cn); /// var url = "/_api/transaction"; /// var body = { /// collections: { /// write : "products" /// }, /// action : ( /// "function () {" + /// "var db = require('internal').db;" + /// "db.products.save({ _key: 'abc'});" + /// "db.products.save({ _key: 'abc'});" + /// "}" /// ) /// }; /// /// var response = logCurlRequest('POST', url, body); /// assert(response.code === 400); /// /// logJsonResponse(response); /// db._drop(cn); /// @END_EXAMPLE_ARANGOSH_RUN /// /// Aborting a transaction by explicitly throwing an exception /// /// @EXAMPLE_ARANGOSH_RUN{RestTransactionAbort} /// var cn = "products"; /// db._drop(cn); /// var products = db._create(cn, { waitForSync: true }); /// products.save({ "a": 1 }); /// var url = "/_api/transaction"; /// var body = { /// collections: { /// read : "products" /// }, /// action : "function () { throw 'doh!'; }" /// }; /// /// var response = logCurlRequest('POST', url, body); /// assert(response.code === 500); /// /// logJsonResponse(response); /// db._drop(cn); /// @END_EXAMPLE_ARANGOSH_RUN /// /// Referring to a non-existing collection /// /// @EXAMPLE_ARANGOSH_RUN{RestTransactionNonExisting} /// var cn = "products"; /// db._drop(cn); /// var url = "/_api/transaction"; /// var body = { /// collections: { /// read : "products" /// }, /// action : "function () { return true; }" /// }; /// /// var response = logCurlRequest('POST', url, body); /// assert(response.code === 404); /// /// logJsonResponse(response); /// @END_EXAMPLE_ARANGOSH_RUN /// @endDocuBlock ////////////////////////////////////////////////////////////////////////////////