diff --git a/arangodb-foxx-services/README.md b/arangodb-foxx-services/README.md index a338b05c5..5becff815 100644 --- a/arangodb-foxx-services/README.md +++ b/arangodb-foxx-services/README.md @@ -13,19 +13,19 @@ mvn clean install ```shell # Deploy the "/spline" service to the "foo" database on the given ArangoDB server # (http://some.server:1234/_db/foo/spline/) -npm foxx:deploy --database=foo --server=http://some.server:1234 +npm run foxx:deploy --database=foo --server=http://some.server:1234 # If the "--server" option is omitted, the local server is used # (http://localhost:8529/_db/foo/spline/) -npm foxx:deploy --database=foo +npm run foxx:deploy --database=foo # Use "foxx:deploy-dev" to deploy the service in development mode (https://www.arangodb.com/docs/stable/foxx-guides-development-mode.html) -npm foxx:deploy-dev --database=foo +npm run foxx:deploy-dev --database=foo # If needed, in addition to the "foxx:deploy" script that executes build, uninstall and install steps, # you can also use individual "foxx:install" or "foxx:uninstall" scripts with the same arguments. -npm foxx:uninstall --database=NAME [--server=URL] -npm foxx:install --database=NAME [--server=URL] +npm run foxx:uninstall --database=NAME [--server=URL] +npm run foxx:install --database=NAME [--server=URL] ``` --- diff --git a/arangodb-foxx-services/src/main/services/txm/tx-manager-impl.ts b/arangodb-foxx-services/src/main/services/txm/tx-manager-impl.ts index 4de93e40f..9e34f4c8d 100644 --- a/arangodb-foxx-services/src/main/services/txm/tx-manager-impl.ts +++ b/arangodb-foxx-services/src/main/services/txm/tx-manager-impl.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { TxManager } from './tx-manager' +import {TxManager} from './tx-manager' import { AuxCollectionName, CollectionName, @@ -27,35 +27,52 @@ import { TxParams, WriteTxInfo } from '../../persistence/model' -import { store } from '../store' -import { aql, db } from '@arangodb' +import {store} from '../store' +import {aql, db} from '@arangodb' import * as Logger from '../../utils/logger' import UpdateResult = ArangoDB.UpdateResult +/** + * Max attempts to atomically increment the counter + */ +const MAX_GET_TX_NUM_ATTEMPTS = 50 + export class TxManagerImpl implements TxManager { private nextTxNumber(): TxNum { - const curCnt: Counter = store.getDocByKey(CollectionName.Counter, 'tx') - - // as of time of writing the '@types/arangodb:3.5.13' was the latest version, - // and it was not up-to-date with ArangoDB 3.10+ JavaScript API - // @ts-ignore - const updResult: UpdateResult = db._update( - curCnt, - { - curVal: curCnt.curVal + 1 - }, - // @ts-ignore - { - overwrite: false, // check _rev - returnNew: true // return an updated document in the `new` attribute + let attempts = MAX_GET_TX_NUM_ATTEMPTS + while (attempts-- > 0) { + try { + const curCnt: Counter = store.getDocByKey(CollectionName.Counter, 'tx') + + // as of time of writing the '@types/arangodb:3.5.13' was the latest version, + // and it was not up-to-date with ArangoDB 3.10+ JavaScript API + // @ts-ignore + const updResult: UpdateResult = db._update( + curCnt._id, + { + curVal: curCnt.curVal + 1 + }, + // @ts-ignore + { + overwrite: false, // check _rev + returnNew: true // return an updated document in the `new` attribute + } + ) + + const newCnt: Counter = updResult.new + + return newCnt.curVal } - ) - - const newCnt: Counter = updResult.new - - return newCnt.curVal + catch (e) { + const errNum = e.errorNum + if (errNum !== 1200) { + throw new Error(`Failed to obtain a new Tx number.\nUnderlying error ${errNum}: ${e.message}`) + } + } + } + throw new Error(`Failed to obtain a new Tx number after ${MAX_GET_TX_NUM_ATTEMPTS} attempts.`) } startWrite(txParams: TxParams = {}): WriteTxInfo {