From dba42c3aab9542186b7846e1c13ec26812dea6f0 Mon Sep 17 00:00:00 2001 From: jubnl Date: Thu, 24 Sep 2026 06:18:33 +0200 Subject: [PATCH] =?UTF-8?q?fix(server):=20plan=204=20=E2=80=94=20thread=20?= =?UTF-8?q?the=20discovery=20UnitOfWork=20through=20PluginRuntimeService?= =?UTF-8?q?=20too?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Complements the just-landed discovery atomicity fix (DiscoveryRepos.uow): PluginRuntimeService's own discoveryRepos getter still built the bundle without a uow field. Threads its already-injected, @Optional() uow through so its own onApplicationBootstrap/reload/dev-link discovery calls also get the transactional DI5-DI8 refresh, not just PluginRegistryService's. No throwing guard here, unlike PluginRegistryService's: several hand-built partial-DI-graph test instances of this class (boot-registry-order.test.ts, in a sibling task's held file window) construct it with uow omitted and exercise onApplicationBootstrap's discovery call directly. Discovery must never refuse outright just because a test built a partial graph, so it degrades to the pre-existing untransacted sequence when uow is absent (DiscoveryRepos.uow's own docstring covers this), the same "boot must never block app init" defensiveness this file already applies elsewhere. --- server/src/nest/plugins/plugin-runtime.service.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/server/src/nest/plugins/plugin-runtime.service.ts b/server/src/nest/plugins/plugin-runtime.service.ts index fa360f3ac..6359ba471 100644 --- a/server/src/nest/plugins/plugin-runtime.service.ts +++ b/server/src/nest/plugins/plugin-runtime.service.ts @@ -315,8 +315,17 @@ export class PluginRuntimeService implements OnApplicationBootstrap, OnModuleDes // Plan 3j Task 3: `discoverPlugins` composes `DiscoveryRepos` from the repositories // this class already injects for its own PR-numbered statements — no new params. + // Plan 4 Task 8a: `uow` (already injected, `@Optional()`, for `setOperatorEgressHosts` + // above) is threaded through too, so `upsert`'s DI5–DI8 delete/re-insert pairs run + // in one transaction — `DiscoveryRepos.uow`'s own docstring covers why this is + // optional rather than a throwing guard like `setOperatorEgressHosts`'s: several + // hand-built partial-DI-graph test instances of this class (e.g. + // `boot-registry-order.test.ts`) exercise `onApplicationBootstrap`'s discovery + // call with no `uow`, and discovery — unlike a write an admin is actively waiting + // on — must never refuse outright; it degrades to the pre-existing untransacted + // sequence instead. private get discoveryRepos(): DiscoveryRepos { - return { plugins: this.plugins, actions: this.pluginActions, settingsFields: this.pluginSettingsFields, errorLog: this.pluginErrorLog }; + return { plugins: this.plugins, actions: this.pluginActions, settingsFields: this.pluginSettingsFields, errorLog: this.pluginErrorLog, uow: this.uow }; } // onApplicationBootstrap, NOT onModuleInit: boot activation builds each plugin's