Skip to content

Commit 95ea37d

Browse files
committed
Change maxSockets behavior/defaults
Fixes #702.
1 parent 13b60b7 commit 95ea37d

File tree

3 files changed

+59
-19
lines changed

3 files changed

+59
-19
lines changed

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,23 @@ This driver uses semantic versioning:
2424
sockets expiring, especially with larger connection pools and infrequent
2525
requests.
2626

27+
- Removed `keepAlive`-specific throughput optimization
28+
29+
Previously arangojs would allow `agentOptions.maxSockets * 2` concurrent
30+
requests, to optimize socket reuse by avoiding idle time. This behavior
31+
could trigger deadlocks when attempting to perform multiple transactions
32+
in parallel and only marginally improved throughput in some high-load
33+
scenarios. The connection pool size now always reflects the value set in
34+
`agentOptions.maxSockets` regardless of whether `keepAlive` is enabled.
35+
36+
- Changed `agentOptions.maxSockets` default value when using `ROUND_ROBIN`
37+
38+
As the connection pool is shared across all server connections when using
39+
`ROUND_ROBIN` load balancing, the default value of `3` is too limiting for
40+
most scenarios involving multiple coordinators. When passing multiple URLs
41+
via the `url` option and specifying `ROUND_ROBIN` load balancing, arangojs
42+
will now default this value to `url.length * 3` instead.
43+
2744
## [7.2.0] - 2020-12-02
2845

2946
### Added

README.md

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ The official ArangoDB JavaScript client for Node.js and the browser.
99

1010
## Links
1111

12-
* [API Documentation](https://arangodb.github.io/arangojs/latest/modules/_index_.html)
12+
- [API Documentation](https://arangodb.github.io/arangojs/latest/modules/_index_.html)
1313

14-
* [Changelog](https://arangodb.github.io/arangojs/CHANGELOG)
14+
- [Changelog](https://arangodb.github.io/arangojs/CHANGELOG)
1515

16-
* [Migration Guide](http://arangodb.github.io/arangojs/MIGRATING)
16+
- [Migration Guide](http://arangodb.github.io/arangojs/MIGRATING)
1717

1818
## Install
1919

@@ -321,7 +321,7 @@ HTTPS certificate validation entirely, but note this has
321321
When using arangojs in the browser, self-signed HTTPS certificates need to
322322
be trusted by the browser or use a trusted root certificate.
323323

324-
### Streaming transactions
324+
### Streaming transactions leak
325325

326326
When using the `transaction.step` method it is important to be aware of the
327327
limitations of what a callback passed to this method is allowed to do.
@@ -343,6 +343,22 @@ await trx.step(() => collection.save(doc2));
343343

344344
Please refer to the documentation of this method for additional examples.
345345

346+
### Streaming transactions timeout in cluster
347+
348+
Transactions have
349+
[different guarantees](https://www.arangodb.com/docs/stable/transactions-limitations.html#in-clusters)
350+
in a cluster.
351+
352+
When using arangojs in a cluster with load balancing, you may need to adjust
353+
the value of `agentOptions.maxSockets` to accommodate the number of transactions
354+
you need to be able to run in parallel. The default value is likely to be too
355+
low for most cluster scenarios involving frequent streaming transactions.
356+
357+
**Note**: When using a high value for `agentOptions.maxSockets` you may have
358+
to adjust the maximum number of threads in the ArangoDB configuration using
359+
[the `server.maximal-threads` option](https://www.arangodb.com/docs/3.7/programs-arangod-server.html#server-threads)
360+
to support larger numbers of concurrent transactions on the server side.
361+
346362
## License
347363

348364
The Apache License, Version 2.0. For more information, see the accompanying

src/connection.ts

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -432,10 +432,16 @@ export type Config = {
432432
* module when using arangojs in the browser). This will be ignored if
433433
* `agent` is also provided.
434434
*
435-
* The option `maxSockets` can also be used to limit how many requests
435+
* The option `maxSockets` is also used to limit how many requests
436436
* arangojs will perform concurrently. The maximum number of requests is
437-
* equal to `maxSockets * 2` with `keepAlive: true` or equal to `maxSockets`
438-
* with `keepAlive: false` (or in the browser).
437+
* equal to `maxSockets`.
438+
*
439+
* **Note:** arangojs will limit the number of concurrent requests based on
440+
* this value even if an `agent` is provided.
441+
*
442+
* **Note:** when using `ROUND_ROBIN` load balancing and passing an array of
443+
* URLs in the `url` option, the default value of `maxSockets` will be set
444+
* to `3 * url.length` instead of `3`.
439445
*
440446
* Default (Node.js): `{ maxSockets: 3, keepAlive: true, keepAliveMsecs: 1000 }`
441447
*
@@ -509,40 +515,41 @@ export class Connection {
509515
* @hidden
510516
*/
511517
constructor(config: Omit<Config, "databaseName"> = {}) {
518+
const URLS = config.url
519+
? Array.isArray(config.url)
520+
? config.url
521+
: [config.url]
522+
: ["http://localhost:8529"];
523+
const MAX_SOCKETS =
524+
3 * (config.loadBalancingStrategy === "ROUND_ROBIN" ? URLS.length : 1);
525+
512526
if (config.arangoVersion !== undefined) {
513527
this._arangoVersion = config.arangoVersion;
514528
}
515529
this._agent = config.agent;
516530
this._agentOptions = isBrowser
517-
? { maxSockets: 3, ...config.agentOptions }
531+
? { maxSockets: MAX_SOCKETS, ...config.agentOptions }
518532
: {
519-
maxSockets: 3,
533+
maxSockets: MAX_SOCKETS,
520534
keepAlive: true,
521535
keepAliveMsecs: 1000,
522536
scheduling: "lifo",
523537
...config.agentOptions,
524538
};
525539
this._maxTasks = this._agentOptions.maxSockets;
526-
if (this._agentOptions.keepAlive) this._maxTasks *= 2;
527-
528540
this._headers = { ...config.headers };
529-
this._loadBalancingStrategy = config.loadBalancingStrategy || "NONE";
541+
this._loadBalancingStrategy = config.loadBalancingStrategy ?? "NONE";
530542
this._useFailOver = this._loadBalancingStrategy !== "ROUND_ROBIN";
531543
this._precaptureStackTraces = Boolean(config.precaptureStackTraces);
532544
if (config.maxRetries === false) {
533545
this._shouldRetry = false;
534546
this._maxRetries = 0;
535547
} else {
536548
this._shouldRetry = true;
537-
this._maxRetries = config.maxRetries || 0;
549+
this._maxRetries = config.maxRetries ?? 0;
538550
}
539551

540-
const urls = config.url
541-
? Array.isArray(config.url)
542-
? config.url
543-
: [config.url]
544-
: ["http://localhost:8529"];
545-
this.addToHostList(urls);
552+
this.addToHostList(URLS);
546553

547554
if (config.auth) {
548555
if (isBearerAuth(config.auth)) {

0 commit comments

Comments
 (0)