feat(core): improve runtime observability
This commit is contained in:
parent
a9b7bd9e2f
commit
c3d26c4912
6 changed files with 112 additions and 40 deletions
24
packages/core/src/event-logger.ts
Normal file
24
packages/core/src/event-logger.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
export * as EventLogger from "./event-logger"
|
||||
|
||||
import { Effect, Layer } from "effect"
|
||||
import { makeGlobalNode } from "./effect/app-node"
|
||||
import { EventV2 } from "./event"
|
||||
|
||||
const Types = new Set([
|
||||
"agent.updated",
|
||||
"catalog.updated",
|
||||
"command.updated",
|
||||
"config.updated",
|
||||
])
|
||||
|
||||
export const layer = Layer.effectDiscard(
|
||||
Effect.gen(function* () {
|
||||
const events = yield* EventV2.Service
|
||||
const unsubscribe = yield* events.listen((event) =>
|
||||
Types.has(event.type) ? Effect.logInfo("event", { event }) : Effect.void,
|
||||
)
|
||||
yield* Effect.addFinalizer(() => unsubscribe)
|
||||
}),
|
||||
)
|
||||
|
||||
export const node = makeGlobalNode({ name: "event-logger", layer, deps: [EventV2.node] })
|
||||
|
|
@ -34,46 +34,53 @@ const layer = Layer.effect(
|
|||
const fs = yield* FSUtil.Service
|
||||
const git = yield* Git.Service
|
||||
const configService = yield* Config.Service
|
||||
const config = (yield* configService.entries())
|
||||
.filter((entry): entry is Config.Document => entry.type === "document")
|
||||
.flatMap((item) => item.info.watcher?.ignore ?? [])
|
||||
const publish = (update: { type: "create" | "update" | "delete"; path: string }) =>
|
||||
events.publish(FileSystem.Event.Changed, {
|
||||
file: update.path,
|
||||
event: update.type === "create" ? "add" : update.type === "update" ? "change" : "unlink",
|
||||
})
|
||||
|
||||
if (path.resolve(location.directory) !== path.resolve(os.homedir())) {
|
||||
yield* watcher
|
||||
.subscribe({
|
||||
path: location.directory,
|
||||
type: "directory",
|
||||
ignore: [...Ignore.PATTERNS, ...config, ...protecteds(location.directory)],
|
||||
})
|
||||
.pipe(Stream.runForEach(publish), Effect.forkScoped({ startImmediately: true }))
|
||||
} else {
|
||||
yield* Effect.logInfo("location watcher skipped home directory", { directory: location.directory })
|
||||
}
|
||||
yield* Effect.gen(function* () {
|
||||
const config = (yield* configService.entries())
|
||||
.filter((entry): entry is Config.Document => entry.type === "document")
|
||||
.flatMap((item) => item.info.watcher?.ignore ?? [])
|
||||
const home = path.resolve(location.directory) === path.resolve(os.homedir())
|
||||
|
||||
if (location.vcs?.type === "git") {
|
||||
const resolved = (yield* git.repo.discover(location.directory))?.gitDirectory
|
||||
const vcs = resolved ? yield* fs.realPath(resolved).pipe(Effect.catch(() => Effect.succeed(resolved))) : undefined
|
||||
if (vcs && !config.includes(".git") && !config.includes(vcs) && (!resolved || !config.includes(resolved))) {
|
||||
const ignore = (yield* fs.readDirectoryEntries(vcs).pipe(Effect.catch(() => Effect.succeed([])))).flatMap(
|
||||
(entry) => (entry.name === "HEAD" ? [] : [entry.name]),
|
||||
)
|
||||
if (!home) {
|
||||
yield* watcher
|
||||
.subscribe({ path: vcs, type: "directory", ignore })
|
||||
.pipe(Stream.runForEach(publish), Effect.forkScoped({ startImmediately: true }))
|
||||
.subscribe({
|
||||
path: location.directory,
|
||||
type: "directory",
|
||||
ignore: [...Ignore.PATTERNS, ...config, ...protecteds(location.directory)],
|
||||
})
|
||||
.pipe(Stream.runForEach(publish), Effect.forkScoped)
|
||||
}
|
||||
}
|
||||
if (home) {
|
||||
yield* Effect.logInfo("location watcher skipped home directory", { directory: location.directory })
|
||||
}
|
||||
|
||||
if (location.vcs?.type === "git") {
|
||||
const resolved = (yield* git.repo.discover(location.directory))?.gitDirectory
|
||||
const vcs = resolved
|
||||
? yield* fs.realPath(resolved).pipe(Effect.catch(() => Effect.succeed(resolved)))
|
||||
: undefined
|
||||
if (vcs && !config.includes(".git") && !config.includes(vcs) && (!resolved || !config.includes(resolved))) {
|
||||
const ignore = (yield* fs.readDirectoryEntries(vcs).pipe(Effect.catch(() => Effect.succeed([])))).flatMap(
|
||||
(entry) => (entry.name === "HEAD" ? [] : [entry.name]),
|
||||
)
|
||||
yield* watcher
|
||||
.subscribe({ path: vcs, type: "directory", ignore })
|
||||
.pipe(Stream.runForEach(publish), Effect.forkScoped)
|
||||
}
|
||||
}
|
||||
}).pipe(
|
||||
Effect.withSpan("LocationWatcher.start", { attributes: { directory: location.directory } }),
|
||||
Effect.catchCause((cause) => Effect.logError("failed to init location watcher service", { cause })),
|
||||
Effect.forkScoped,
|
||||
)
|
||||
|
||||
return Service.of({})
|
||||
}).pipe(
|
||||
Effect.catchCause((cause) =>
|
||||
Effect.logError("failed to init location watcher service", { cause }).pipe(Effect.as(Service.of({}))),
|
||||
),
|
||||
),
|
||||
}),
|
||||
)
|
||||
|
||||
export const node = makeLocationNode({
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ const layer = Layer.effect(
|
|||
})
|
||||
|
||||
return Service.of({ capture, files, diff, preview, restore, checkout })
|
||||
}),
|
||||
}).pipe(Effect.withSpan("Snapshot.boot")),
|
||||
)
|
||||
|
||||
export const node = makeLocationNode({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue