diff --git a/apps/desktop/src/shell/DesktopShellEnvironment.test.ts b/apps/desktop/src/shell/DesktopShellEnvironment.test.ts index 79344567fcd6c..b5bde775927f3 100644 --- a/apps/desktop/src/shell/DesktopShellEnvironment.test.ts +++ b/apps/desktop/src/shell/DesktopShellEnvironment.test.ts @@ -4,6 +4,7 @@ import { assert, describe, it } from "@effect/vitest"; import * as HostProcess from "@t3tools/shared/HostProcess"; import * as Effect from "effect/Effect"; import * as Deferred from "effect/Deferred"; +import * as Fiber from "effect/Fiber"; import * as FileSystem from "effect/FileSystem"; import * as Layer from "effect/Layer"; import * as Logger from "effect/Logger"; @@ -164,6 +165,10 @@ describe("DesktopShellEnvironment", () => { const startup = yield* service.installIntoProcess.pipe(Effect.forkChild); yield* Deferred.await(started); assert.isDefined(startup.pollUnsafe()); + assert.isFalse( + yield* Fiber.join(startup), + "nothing was installed yet, so the server must hydrate PATH itself", + ); yield* Deferred.succeed(release, undefined); return yield* service.awaitDiscovery; }), @@ -231,7 +236,7 @@ describe("DesktopShellEnvironment", () => { }), use: (service) => Effect.gen(function* () { - yield* service.installIntoProcess; + assert.isTrue(yield* service.installIntoProcess); yield* service.installIntoProcess; assert.equal(env.PATH, "/old/bin:/usr/bin:/launcher/bin"); assert.equal(env.SSH_AUTH_SOCK, "/current-session.sock"); diff --git a/apps/desktop/src/shell/DesktopShellEnvironment.ts b/apps/desktop/src/shell/DesktopShellEnvironment.ts index 556f7090b422e..dff70213ca74d 100644 --- a/apps/desktop/src/shell/DesktopShellEnvironment.ts +++ b/apps/desktop/src/shell/DesktopShellEnvironment.ts @@ -75,7 +75,8 @@ export class DesktopShellEnvironmentCommandTimeoutError extends Schema.TaggedErr export class DesktopShellEnvironment extends Context.Service< DesktopShellEnvironment, { - // Desktop owns discovery, including on cache misses; the backend receives updates over fd4. + // Yields true only when a cached environment was applied; on a miss the backend hydrates + // PATH itself until desktop discovery arrives over fd4. readonly installIntoProcess: Effect.Effect; readonly awaitDiscovery: Effect.Effect; readonly updates: Stream.Stream; @@ -622,7 +623,8 @@ export const make = Effect.gen(function* () { const cache = yield* fileSystem .readFileString(cachePath) .pipe(Effect.flatMap(decodeCache), Effect.option); - if (Option.isSome(cache) && cache.value.key === key) { + const hit = Option.isSome(cache) && cache.value.key === key; + if (hit) { const cached = Object.fromEntries( CACHED_ENV_NAMES.flatMap((name) => { const value = cache.value.environment[name]; @@ -648,7 +650,7 @@ export const make = Effect.gen(function* () { ); } yield* Effect.forkIn(refresh, scope); - return true; + return hit; }).pipe(Effect.withSpan("desktop.shellEnvironment.installIntoProcess")), ); const updates = Stream.unwrap(