Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

issue #1300 TxManagerImpl.nextTxNumber(): Repeat attempt on racing condition #1343

Merged
merged 1 commit into from
Jul 2, 2024
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
10 changes: 5 additions & 5 deletions arangodb-foxx-services/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]
```

---
Expand Down
61 changes: 39 additions & 22 deletions arangodb-foxx-services/src/main/services/txm/tx-manager-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import { TxManager } from './tx-manager'
import {TxManager} from './tx-manager'
import {
AuxCollectionName,
CollectionName,
Expand All @@ -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<Counter> = 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<Counter> = 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 {
Expand Down
Loading