From 4c46845d82dfa36c32d75749aef05c850fa89dcb Mon Sep 17 00:00:00 2001 From: bourgeoa Date: Sun, 30 Aug 2026 19:10:34 +0200 Subject: [PATCH 1/2] fix: port CSS lock/sweep hardening - scope the 4 expiring-storage sweeps to their own containers - bound lock-acquisition retries (attemptSettings) - guard proper-lockfile updateLock race via patch-package - add adapter storage @id (patch-package) for the sweep override - fix SafeBaseLoginAccountStorage build (TS2415, generator types) --- config/pivot-overrides.json | 87 +++++++++++++++++++ package-lock.json | 24 +++++ package.json | 1 + patches/@solid+community-server+7.2.0.patch | 12 +++ patches/proper-lockfile+4.1.2.patch | 18 ++++ .../util/SafeBaseLoginAccountStorage.ts | 47 ++++++++++ src/index.ts | 1 + 7 files changed, 190 insertions(+) create mode 100644 patches/@solid+community-server+7.2.0.patch create mode 100644 patches/proper-lockfile+4.1.2.patch create mode 100644 src/identity/interaction/account/util/SafeBaseLoginAccountStorage.ts diff --git a/config/pivot-overrides.json b/config/pivot-overrides.json index 0abcd00..1f85474 100644 --- a/config/pivot-overrides.json +++ b/config/pivot-overrides.json @@ -61,6 +61,93 @@ "templateEngine": { "@id": "urn:solid-server:default:TemplateEngine" }, "template": "./templates/main.html.ejs" } + }, + { + "@type": "Override", + "overrideInstance": { "@id": "urn:solid-server:default:AccountStorage" }, + "overrideParameters": { + "@type": "SafeBaseLoginAccountStorage", + "storage": { "@id": "urn:solid-server:default:IndexedStorage" } + } + }, + { + "comment": "Bound the lock acquisition retries so a contended lock fails fast instead of spinning the event loop and filesystem threadpool forever (~30s max wait).", + "@type": "Override", + "overrideInstance": { "@id": "urn:solid-server:default:FileSystemResourceLocker" }, + "overrideParameters": { + "@type": "FileSystemResourceLocker", + "attemptSettings_retryCount": 600, + "attemptSettings_retryDelay": 50, + "attemptSettings_retryJitter": 30 + } + }, + { + "comment": "Scope the cookie sweep to its own container so entries()/sweeps do not walk the entire /.internal/ tree (sustained high CPU with many accounts).", + "@type": "Override", + "overrideInstance": { "@id": "urn:solid-server:default:CookieStorage" }, + "overrideParameters": { + "@type": "WrappedExpiringStorage", + "source": { + "@type": "MaxKeyLengthStorage", + "source": { + "@type": "JsonResourceStorage", + "source": { "@id": "urn:solid-server:default:ResourceStore_Backend" }, + "baseUrl": { "@id": "urn:solid-server:default:variable:baseUrl" }, + "container": "/.internal/accounts/cookies/" + } + } + } + }, + { + "comment": "Scope the forgot-password sweep to its own container.", + "@type": "Override", + "overrideInstance": { "@id": "urn:solid-server:default:ForgotPasswordStorage" }, + "overrideParameters": { + "@type": "WrappedExpiringStorage", + "source": { + "@type": "MaxKeyLengthStorage", + "source": { + "@type": "JsonResourceStorage", + "source": { "@id": "urn:solid-server:default:ResourceStore_Backend" }, + "baseUrl": { "@id": "urn:solid-server:default:variable:baseUrl" }, + "container": "/.internal/accounts/forgot-password/" + } + } + } + }, + { + "comment": "Scope the token sweep to its own container.", + "@type": "Override", + "overrideInstance": { "@id": "urn:solid-server:default:ExpiringTokenStorage" }, + "overrideParameters": { + "@type": "WrappedExpiringStorage", + "source": { + "@type": "MaxKeyLengthStorage", + "source": { + "@type": "JsonResourceStorage", + "source": { "@id": "urn:solid-server:default:ResourceStore_Backend" }, + "baseUrl": { "@id": "urn:solid-server:default:variable:baseUrl" }, + "container": "/.internal/idp/tokens/" + } + } + } + }, + { + "comment": "Scope the adapter sweep to its own container. Requires the @id added to the installed CSS adapter-factory.json by the patch-package override.", + "@type": "Override", + "overrideInstance": { "@id": "urn:solid-server:default:ExpiringAdapterStorage" }, + "overrideParameters": { + "@type": "WrappedExpiringStorage", + "source": { + "@type": "MaxKeyLengthStorage", + "source": { + "@type": "JsonResourceStorage", + "source": { "@id": "urn:solid-server:default:ResourceStore_Backend" }, + "baseUrl": { "@id": "urn:solid-server:default:variable:baseUrl" }, + "container": "/.internal/idp/adapter/" + } + } + } } ] } diff --git a/package-lock.json b/package-lock.json index 3d53390..2ee345f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "": { "name": "@solid/pivot", "version": "1.8.2", + "hasInstallScript": true, "license": "MIT", "dependencies": { "@inrupt/solid-client-authn-core": "^3.1.1", @@ -3132,6 +3133,7 @@ "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, "license": "ISC", "dependencies": { "string-width": "^5.1.2", @@ -3149,6 +3151,7 @@ "version": "6.2.2", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -3161,6 +3164,7 @@ "version": "6.2.3", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -3173,12 +3177,14 @@ "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, "license": "MIT" }, "node_modules/@isaacs/cliui/node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", @@ -3196,6 +3202,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^6.2.2" @@ -3211,6 +3218,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", @@ -3804,6 +3812,7 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, "license": "MIT", "optional": true, "engines": { @@ -5765,6 +5774,7 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", + "dev": true, "funding": [ { "type": "github", @@ -6484,6 +6494,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, "license": "MIT" }, "node_modules/ee-first": { @@ -7234,6 +7245,7 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, "license": "ISC", "dependencies": { "cross-spawn": "^7.0.6", @@ -7250,6 +7262,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, "license": "ISC", "engines": { "node": ">=14" @@ -7478,6 +7491,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", @@ -7510,6 +7524,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -7519,6 +7534,7 @@ "version": "9.0.9", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^2.0.2" @@ -8309,6 +8325,7 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" @@ -9087,6 +9104,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, "license": "MIT" }, "node_modules/json-schema-traverse": { @@ -9920,6 +9938,7 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, "license": "BlueOak-1.0.0", "engines": { "node": ">=16 || 14 >=14.17" @@ -12160,6 +12179,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, "license": "BlueOak-1.0.0" }, "node_modules/package-json-path": { @@ -12455,6 +12475,7 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^10.2.0", @@ -14080,6 +14101,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -14106,6 +14128,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -14884,6 +14907,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", diff --git a/package.json b/package.json index 8b445c0..828ee0b 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "build:components": "componentsjs-generator -s src -c dist/components -i .componentsignore -r pivot", "build:ts": "tsc", "prepare": "npm run build", + "postinstall": "patch-package", "test": "jest" }, "files": [ diff --git a/patches/@solid+community-server+7.2.0.patch b/patches/@solid+community-server+7.2.0.patch new file mode 100644 index 0000000..0307c59 --- /dev/null +++ b/patches/@solid+community-server+7.2.0.patch @@ -0,0 +1,12 @@ +diff --git a/node_modules/@solid/community-server/config/identity/handler/base/adapter-factory.json b/node_modules/@solid/community-server/config/identity/handler/base/adapter-factory.json +index c2b9890..c406ba6 +--- a/node_modules/@solid/community-server/config/identity/handler/base/adapter-factory.json ++++ b/node_modules/@solid/community-server/config/identity/handler/base/adapter-factory.json +@@ -13,6 +13,7 @@ + "source": { + "@type": "ExpiringAdapterFactory", + "storage": { ++ "@id": "urn:solid-server:default:ExpiringAdapterStorage", + "@type": "WrappedExpiringStorage", + "source": { + "@type": "ContainerPathStorage", diff --git a/patches/proper-lockfile+4.1.2.patch b/patches/proper-lockfile+4.1.2.patch new file mode 100644 index 0000000..e2a8b2d --- /dev/null +++ b/patches/proper-lockfile+4.1.2.patch @@ -0,0 +1,18 @@ +diff --git a/node_modules/proper-lockfile/lib/lockfile.js b/node_modules/proper-lockfile/lib/lockfile.js +index 97b6637..25bd0a2 100644 +--- a/node_modules/proper-lockfile/lib/lockfile.js ++++ b/node_modules/proper-lockfile/lib/lockfile.js +@@ -99,6 +99,13 @@ function removeLock(file, options, callback) { + function updateLock(file, options) { + const lock = locks[file]; + ++ // Guard against a renewal timer racing with lock release: ++ // `locks[file]` may already be deleted when an in-flight fs callback recurses. ++ /* istanbul ignore if */ ++ if (!lock) { ++ return; ++ } ++ + // Just for safety, should never happen + /* istanbul ignore if */ + if (lock.updateTimeout) { diff --git a/src/identity/interaction/account/util/SafeBaseLoginAccountStorage.ts b/src/identity/interaction/account/util/SafeBaseLoginAccountStorage.ts new file mode 100644 index 0000000..05ba222 --- /dev/null +++ b/src/identity/interaction/account/util/SafeBaseLoginAccountStorage.ts @@ -0,0 +1,47 @@ +import { + ACCOUNT_TYPE, + BaseLoginAccountStorage, + createErrorMessage, + getLoggerFor, +} from '@solid/community-server'; + +const LOGIN_COUNT = 'linkedLoginsCount'; + +/** + * A {@link BaseLoginAccountStorage} that prevents the periodic cleanup of accounts + * without login methods from crashing the process when a lock timeout occurs. + * + * The storage is typed as `any` (and the class is not generic) because the + * componentsjs-generator cannot resolve the `IndexedStorage`/`IndexTypeCollection` + * generic types from the installed Community Solid Server `.d.ts` (TS2415-safe + * `logger` is renamed to `safeLogger` for the same reason). + */ +export class SafeBaseLoginAccountStorage extends BaseLoginAccountStorage { + // Renamed (not `logger`) because the base class already declares a private `logger`, + // which cannot be re-declared in a subclass (TS2415). + private readonly safeLogger = getLoggerFor(this); + + private readonly timeout: number; + + public constructor(storage: any, expiration = 30 * 60) { + super(storage, expiration); + this.timeout = expiration * 1000; + } + + protected createAccountTimeout(id: string): void { + // eslint-disable-next-line @typescript-eslint/no-misused-promises + const timer = setTimeout(async(): Promise => { + try { + const account = await this.storage.get(ACCOUNT_TYPE, id); + if (account && account[LOGIN_COUNT] === 0) { + this.safeLogger.debug(`Removing account with no login methods ${id}`); + await this.storage.delete(ACCOUNT_TYPE, id); + } + } catch (error: unknown) { + // Prevent an unhandled rejection (e.g. a lock timeout) from crashing the process. + this.safeLogger.error(`Error during account cleanup of ${id}: ${createErrorMessage(error)}`); + } + }, this.timeout); + timer.unref(); + } +} diff --git a/src/index.ts b/src/index.ts index 2d9b1a8..a36ae93 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,5 +2,6 @@ export * from "./storage/RdfPatchingStore"; export * from "./storage/patch/ThrowingN3Patcher"; export * from './FedcmHttpHandler'; export * from './http/output/PivotResponseWriter'; +export * from './identity/interaction/account/util/SafeBaseLoginAccountStorage'; export * from './identity/interaction/password/MigratedPasswordLoginHandler'; export * from './identity/PivotOidcHttpHandler'; From d5e6428ad491dee536c32198e05c850469d1d801 Mon Sep 17 00:00:00 2001 From: bourgeoa Date: Sun, 30 Aug 2026 19:30:52 +0200 Subject: [PATCH 2/2] fix: move file-locker override out of shared config The FileSystemResourceLocker override targets an instance that only exists in configs using the file resource locker. test.json uses the memory locker, so keeping the override in pivot-overrides.json broke the test suite. Move it to a dedicated file imported only by the file-locker configs. --- config/dev-http-subdomain.json | 3 ++- config/dev-http-suffix.json | 3 ++- config/pivot-file-locker-overrides.json | 20 ++++++++++++++++++++ config/pivot-overrides.json | 11 ----------- config/prod.json | 3 ++- config/suffix.json | 3 ++- 6 files changed, 28 insertions(+), 15 deletions(-) create mode 100644 config/pivot-file-locker-overrides.json diff --git a/config/dev-http-subdomain.json b/config/dev-http-subdomain.json index 19abb8a..599cc0e 100644 --- a/config/dev-http-subdomain.json +++ b/config/dev-http-subdomain.json @@ -36,7 +36,8 @@ "css:config/util/representation-conversion/default.json", "css:config/util/resource-locker/file.json", "css:config/util/variables/default.json", - "pivot:config/pivot-overrides.json" + "pivot:config/pivot-overrides.json", + "pivot:config/pivot-file-locker-overrides.json" ], "@graph": [ { diff --git a/config/dev-http-suffix.json b/config/dev-http-suffix.json index fb5fa89..3b1f8f1 100644 --- a/config/dev-http-suffix.json +++ b/config/dev-http-suffix.json @@ -36,7 +36,8 @@ "css:config/util/representation-conversion/default.json", "css:config/util/resource-locker/file.json", "css:config/util/variables/default.json", - "pivot:config/pivot-overrides.json" + "pivot:config/pivot-overrides.json", + "pivot:config/pivot-file-locker-overrides.json" ], "@graph": [ { diff --git a/config/pivot-file-locker-overrides.json b/config/pivot-file-locker-overrides.json new file mode 100644 index 0000000..5dcb487 --- /dev/null +++ b/config/pivot-file-locker-overrides.json @@ -0,0 +1,20 @@ +{ + "comment": "Overrides specific to configs that use the file-system resource locker. Imported only by prod/dev configs, NOT by test.json (which uses the memory locker).", + "@context": [ + "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^7.0.0/components/context.jsonld", + "https://linkedsoftwaredependencies.org/bundles/npm/@solid/pivot/^1.0.0/components/context.jsonld" + ], + "@graph": [ + { + "comment": "Bound the lock acquisition retries so a contended lock fails fast instead of spinning the event loop and filesystem threadpool forever (~30s max wait).", + "@type": "Override", + "overrideInstance": { "@id": "urn:solid-server:default:FileSystemResourceLocker" }, + "overrideParameters": { + "@type": "FileSystemResourceLocker", + "attemptSettings_retryCount": 600, + "attemptSettings_retryDelay": 50, + "attemptSettings_retryJitter": 30 + } + } + ] +} diff --git a/config/pivot-overrides.json b/config/pivot-overrides.json index 1f85474..99a07e8 100644 --- a/config/pivot-overrides.json +++ b/config/pivot-overrides.json @@ -70,17 +70,6 @@ "storage": { "@id": "urn:solid-server:default:IndexedStorage" } } }, - { - "comment": "Bound the lock acquisition retries so a contended lock fails fast instead of spinning the event loop and filesystem threadpool forever (~30s max wait).", - "@type": "Override", - "overrideInstance": { "@id": "urn:solid-server:default:FileSystemResourceLocker" }, - "overrideParameters": { - "@type": "FileSystemResourceLocker", - "attemptSettings_retryCount": 600, - "attemptSettings_retryDelay": 50, - "attemptSettings_retryJitter": 30 - } - }, { "comment": "Scope the cookie sweep to its own container so entries()/sweeps do not walk the entire /.internal/ tree (sustained high CPU with many accounts).", "@type": "Override", diff --git a/config/prod.json b/config/prod.json index 5e8cf62..78802f5 100644 --- a/config/prod.json +++ b/config/prod.json @@ -35,7 +35,8 @@ "css:config/util/representation-conversion/default.json", "css:config/util/resource-locker/file.json", "css:config/util/variables/default.json", - "pivot:config/pivot-overrides.json" + "pivot:config/pivot-overrides.json", + "pivot:config/pivot-file-locker-overrides.json" ], "@graph": [ { diff --git a/config/suffix.json b/config/suffix.json index cf12ef6..79c6889 100644 --- a/config/suffix.json +++ b/config/suffix.json @@ -35,7 +35,8 @@ "css:config/util/representation-conversion/default.json", "css:config/util/resource-locker/file.json", "css:config/util/variables/default.json", - "pivot:config/pivot-overrides.json" + "pivot:config/pivot-overrides.json", + "pivot:config/pivot-file-locker-overrides.json" ], "@graph": [ {