Description of erroneous behaviour
In a multi-tenant HANA application, the first batch of concurrent requests for a cold tenant (no existing connection pool) causes ResourceRequest timed out errors from generic-pool.
https://github.com/cap-js/cds-dbs/blob/db-service-v2.10.0/db-service/lib/common/DatabaseService.js#L63:
this.pool = this.pools[tenant] ??= new ConnectionPool(this.pools._factory, tenant)
When the pool is new and empty, generic-pool calls factory.create() for each pending acquire(). In HANAService.js, each create() https://github.com/cap-js/cds-dbs/blob/hana-v2.7.1/hana/lib/HANAService.js#L59:
await require('@sap/cds-mtxs/lib').xt.serviceManager.get(tenant, { disableCache: false })
The credential cache (_bindings4.cached in @sap/cds-mtxs/srv/plugins/hana/srv-mgr.js) is empty for the first request, and there is no deduplication of concurrent fetches. If 10 requests arrive before the first serviceManager.get() resolves, all 10 hit the Service Manager API independently. The API responds slowly under this burst, and acquireTimeoutMillis (default 1000ms) expires before connections are
established.
Typical error output:
[ERROR] Unhandled Rejection at: Promise ResourceRequest timed out
[ERROR] Unhandled Rejection at: Promise ResourceRequest timed out
[ERROR] Unhandled Rejection at: Promise ResourceRequest timed out
Coalescing concurrent serviceManager.get() calls for the same tenant into a single Promise (e.g. a pendingFetches: Map<string, Promise> in _bindings4()) would prevent the thundering herd. Alternatively, the pool could serialize the first create() before spawning the rest.
Detailed steps to reproduce
- Deploy a multi-tenant CAP HANA application with default pool settings
- Subscribe a new tenant (or restart the server so in-memory pool/cache state is cleared)
- Open a Fiori Elements list page that triggers 5-10+ parallel OData requests for that tenant
- Observe
ResourceRequest timed out errors in logs
This is most reliably triggered on the very first page load after a fresh server start or new tenant subscription, when no credential cache or connection pool exists yet.
Details about your project
Description of erroneous behaviour
In a multi-tenant HANA application, the first batch of concurrent requests for a cold tenant (no existing connection pool) causes
ResourceRequest timed outerrors from generic-pool.https://github.com/cap-js/cds-dbs/blob/db-service-v2.10.0/db-service/lib/common/DatabaseService.js#L63:
When the pool is new and empty, generic-pool calls
factory.create()for each pendingacquire(). InHANAService.js, eachcreate()https://github.com/cap-js/cds-dbs/blob/hana-v2.7.1/hana/lib/HANAService.js#L59:The credential cache (
_bindings4.cachedin@sap/cds-mtxs/srv/plugins/hana/srv-mgr.js) is empty for the first request, and there is no deduplication of concurrent fetches. If 10 requests arrive before the firstserviceManager.get()resolves, all 10 hit the Service Manager API independently. The API responds slowly under this burst, and acquireTimeoutMillis (default 1000ms) expires before connections areestablished.
Typical error output:
Coalescing concurrent
serviceManager.get()calls for the same tenant into a single Promise (e.g. apendingFetches: Map<string, Promise>in_bindings4()) would prevent the thundering herd. Alternatively, the pool could serialize the firstcreate()before spawning the rest.Detailed steps to reproduce
ResourceRequest timed out errorsin logsThis is most reliably triggered on the very first page load after a fresh server start or new tenant subscription, when no credential cache or connection pool exists yet.
Details about your project