DatabaseEventBusStore: 500ms → 2000ms for the performance threshold
when cleaning 100k rows — this is intentionally a perf test so a real
time assertion is correct, it just needs more headroom for CI.
DatabaseKeyStore: replace fixed 500ms sleep with waitForExpect polling
so the test adapts to however long the async deletion actually takes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
The field was accidentally kept from master during the rebase
conflict resolution but doesn't belong in this PR's version of
the file.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
The Azure SDK monorepo upgrade (storage-blob 12.26→12.31, identity
4.5→4.9) adds "type": "module" to package.json, making jest.mock()
unable to intercept imports from production code.
- AzureBlobStorageUrlReader: accept createContainerClient as an
optional dependency, letting tests pass a mock directly instead
of trying to mock the @azure/storage-blob module
- AzureUrlReader: provide PAT credentials in all test cases so
DefaultAzureCredential is never instantiated — the Bearer auth
flow is already covered by the integration package's own tests
- DefaultAzureDevOpsCredentialsProvider: use expect.any() for
mock instance comparison instead of new DefaultAzureCredential()
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
The built-in rate limiter derived its key directly from `req.ip`, which
express-rate-limit 8.x rejects with an ERR_ERL_KEY_GEN_IPV6 validation
error. A raw IPv6 address used as a rate limiting key would let a client
bypass the limit by rotating through addresses in its allotted block, so
the library now requires its `ipKeyGenerator` helper to normalize the
address. Wrap the resolved client address in that helper so the limiter
starts cleanly and groups IPv6 clients by their address block.
Signed-off-by: Asish Kumar <officialasishkumar@gmail.com>
Only delete the cache entry on error if the map still holds the same
promise, preventing a stale rejection from evicting a newer entry.
Also switch the test to createDeferred for readability.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
The permission backend previously resolved userInfo and minted a plugin
request token sequentially for every authorize request with user
credentials. On high-traffic endpoints this meant two serial internal
HTTP round-trips per request, even when the same user made many
requests in quick succession.
This change:
1. Adds a 5-second TTL cache to DefaultUserInfoService so that repeated
getUserInfo() calls for the same user return the cached result
without an HTTP call to the auth backend.
2. Parallelises the getUserInfo() and getPluginRequestToken() calls in
the permission backend's handleRequest via Promise.all, saving one
sequential round-trip on cache misses.
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
The mock credentials created by mockCredentials.none(), .user(), and
.service() were missing the internal version: 'v1' field. This caused
toInternalBackstageCredentials() to throw when used with mock
credentials in tests.
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
Refactors all test files that use TestDatabases/TestCaches with
it.each(databases.eachSupportedId()) to instead use describe.each at
the outer level. This ensures that all tests for one database engine
complete before moving to the next, rather than interleaving engines
across individual tests. This reduces the number of concurrent database
connections and should help with test timeout issues in CI.
The TestDatabases.create() call is hoisted to module scope so the
describe.each can iterate over supported IDs at the top level.
40 files changed across packages/backend-defaults,
packages/backend-test-utils, and multiple plugins.
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
The "respects initialDelayDuration per worker" test had only a 50ms
margin (350ms total sleep vs 300ms initial delay) for the worker to
complete its internal DB roundtrips before asserting. Under CI load
this frequently wasn't enough. Replace the fixed sleep with
waitForExpect, consistent with the rest of the test file.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
The uuid package dropped its CommonJS entry point in v14, making it
incompatible with Backstage's CJS build output and Jest test runner.
Rather than working around the ESM-only issue, replace all usage with
the built-in crypto.randomUUID() which has been available in Node.js
since v16.7 and in all major browsers since March 2022.
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Node.js setTimeout uses a 32-bit signed integer for the delay, so
values larger than 2^31-1 ms (~24.8 days) cause the callback to fire
immediately. Fix by chunking the wait into segments of at most 2^30 ms.
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Several packages had the same dependency listed in both `dependencies`
and `devDependencies`. This removes the duplicate from whichever section
is incorrect based on actual usage in the source code.
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Made-with: Cursor
Remove the `export` keyword from functions that are only used within
their own file and are not part of any package's public API:
- `parseStringsParam` and `isOrder` in notifications-backend
- `toWeb` in backend-defaults urlReader
- `resolvePublicPath` in app-backend
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
- Make ExtensionPointFactoryMiddleware an opaque type via new
@internal/backend package using OpaqueType from @internal/opaque
- Use options object for createExtensionPointFactoryMiddleware
- Make middleware function async (returns Promise<T>)
- Remove extensionPointFactoryMiddleware from createBackend, keep only
on createSpecializedBackend
- Export defaultServiceFactories from @backstage/backend-defaults
Signed-off-by: Jack Palmer <jackpalmer@spotify.com>
Refactor the postgres database creation retry loop to avoid an
unnecessary sleep after the final failed attempt, and improve
readability by using named variables.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>