Skip to content

Commit 5c8c123

Browse files
Apply PR #17878: refactor(snapshot): effectify SnapshotService
2 parents 0660575 + ab89f84 commit 5c8c123

File tree

5 files changed

+800
-651
lines changed

5 files changed

+800
-651
lines changed
Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
import { ServiceMap } from "effect"
2-
import type { Project } from "@/project/project"
1+
import { ServiceMap } from "effect";
2+
import type { Project } from "@/project/project";
33

44
export declare namespace InstanceContext {
5-
export interface Shape {
6-
readonly directory: string
7-
readonly project: Project.Info
8-
}
5+
export interface Shape {
6+
readonly directory: string;
7+
readonly worktree: string;
8+
readonly project: Project.Info;
9+
}
910
}
1011

11-
export class InstanceContext extends ServiceMap.Service<InstanceContext, InstanceContext.Shape>()(
12-
"opencode/InstanceContext",
13-
) {}
12+
export class InstanceContext extends ServiceMap.Service<
13+
InstanceContext,
14+
InstanceContext.Shape
15+
>()("opencode/InstanceContext") {}
Lines changed: 74 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,83 @@
1-
import { Effect, Layer, LayerMap, ServiceMap } from "effect"
2-
import { registerDisposer } from "./instance-registry"
3-
import { InstanceContext } from "./instance-context"
4-
import { ProviderAuthService } from "@/provider/auth-service"
5-
import { QuestionService } from "@/question/service"
6-
import { PermissionService } from "@/permission/service"
7-
import { FileWatcherService } from "@/file/watcher"
8-
import { VcsService } from "@/project/vcs"
9-
import { FileTimeService } from "@/file/time"
10-
import { FormatService } from "@/format"
11-
import { FileService } from "@/file"
12-
import { SkillService } from "@/skill/skill"
13-
import { Instance } from "@/project/instance"
1+
import { Effect, Layer, LayerMap, ServiceMap } from "effect";
2+
import { FileService } from "@/file";
3+
import { FileTimeService } from "@/file/time";
4+
import { FileWatcherService } from "@/file/watcher";
5+
import { FormatService } from "@/format";
6+
import { PermissionService } from "@/permission/service";
7+
import { Instance } from "@/project/instance";
8+
import { VcsService } from "@/project/vcs";
9+
import { ProviderAuthService } from "@/provider/auth-service";
10+
import { QuestionService } from "@/question/service";
11+
import { SkillService } from "@/skill/skill";
12+
import { SnapshotService } from "@/snapshot";
13+
import { InstanceContext } from "./instance-context";
14+
import { registerDisposer } from "./instance-registry";
1415

15-
export { InstanceContext } from "./instance-context"
16+
export { InstanceContext } from "./instance-context";
1617

1718
export type InstanceServices =
18-
| QuestionService
19-
| PermissionService
20-
| ProviderAuthService
21-
| FileWatcherService
22-
| VcsService
23-
| FileTimeService
24-
| FormatService
25-
| FileService
26-
| SkillService
19+
| QuestionService
20+
| PermissionService
21+
| ProviderAuthService
22+
| FileWatcherService
23+
| VcsService
24+
| FileTimeService
25+
| FormatService
26+
| FileService
27+
| SkillService
28+
| SnapshotService;
2729

28-
function lookup(directory: string) {
29-
const project = Instance.project
30-
const ctx = Layer.sync(InstanceContext, () => InstanceContext.of({ directory, project }))
31-
return Layer.mergeAll(
32-
Layer.fresh(QuestionService.layer),
33-
Layer.fresh(PermissionService.layer),
34-
Layer.fresh(ProviderAuthService.layer),
35-
Layer.fresh(FileWatcherService.layer).pipe(Layer.orDie),
36-
Layer.fresh(VcsService.layer),
37-
Layer.fresh(FileTimeService.layer).pipe(Layer.orDie),
38-
Layer.fresh(FormatService.layer),
39-
Layer.fresh(FileService.layer),
40-
Layer.fresh(SkillService.layer),
41-
).pipe(Layer.provide(ctx))
30+
// NOTE: LayerMap only passes the key (directory string) to lookup, but we need
31+
// the full instance context (directory, worktree, project). We read from the
32+
// legacy Instance ALS here, which is safe because lookup is only triggered via
33+
// runPromiseInstance -> Instances.get, which always runs inside Instance.provide.
34+
// This should go away once the old Instance type is removed and lookup can load
35+
// the full context directly.
36+
function lookup(_key: string) {
37+
const ctx = Layer.sync(InstanceContext, () =>
38+
InstanceContext.of(Instance.current),
39+
);
40+
return Layer.mergeAll(
41+
Layer.fresh(QuestionService.layer),
42+
Layer.fresh(PermissionService.layer),
43+
Layer.fresh(ProviderAuthService.layer),
44+
Layer.fresh(FileWatcherService.layer).pipe(Layer.orDie),
45+
Layer.fresh(VcsService.layer),
46+
Layer.fresh(FileTimeService.layer).pipe(Layer.orDie),
47+
Layer.fresh(FormatService.layer),
48+
Layer.fresh(FileService.layer),
49+
Layer.fresh(SkillService.layer),
50+
Layer.fresh(SnapshotService.layer),
51+
).pipe(Layer.provide(ctx));
4252
}
4353

44-
export class Instances extends ServiceMap.Service<Instances, LayerMap.LayerMap<string, InstanceServices>>()(
45-
"opencode/Instances",
46-
) {
47-
static readonly layer = Layer.effect(
48-
Instances,
49-
Effect.gen(function* () {
50-
const layerMap = yield* LayerMap.make(lookup, { idleTimeToLive: Infinity })
51-
const unregister = registerDisposer((directory) => Effect.runPromise(layerMap.invalidate(directory)))
52-
yield* Effect.addFinalizer(() => Effect.sync(unregister))
53-
return Instances.of(layerMap)
54-
}),
55-
)
54+
export class Instances extends ServiceMap.Service<
55+
Instances,
56+
LayerMap.LayerMap<string, InstanceServices>
57+
>()("opencode/Instances") {
58+
static readonly layer = Layer.effect(
59+
Instances,
60+
Effect.gen(function* () {
61+
const layerMap = yield* LayerMap.make(lookup, {
62+
idleTimeToLive: Infinity,
63+
});
64+
const unregister = registerDisposer((directory) =>
65+
Effect.runPromise(layerMap.invalidate(directory)),
66+
);
67+
yield* Effect.addFinalizer(() => Effect.sync(unregister));
68+
return Instances.of(layerMap);
69+
}),
70+
);
5671

57-
static get(directory: string): Layer.Layer<InstanceServices, never, Instances> {
58-
return Layer.unwrap(Instances.use((map) => Effect.succeed(map.get(directory))))
59-
}
72+
static get(
73+
directory: string,
74+
): Layer.Layer<InstanceServices, never, Instances> {
75+
return Layer.unwrap(
76+
Instances.use((map) => Effect.succeed(map.get(directory))),
77+
);
78+
}
6079

61-
static invalidate(directory: string): Effect.Effect<void, never, Instances> {
62-
return Instances.use((map) => map.invalidate(directory))
63-
}
80+
static invalidate(directory: string): Effect.Effect<void, never, Instances> {
81+
return Instances.use((map) => map.invalidate(directory));
82+
}
6483
}

0 commit comments

Comments
 (0)