fix(core): use file times for tool output cleanup (#42450)
Co-authored-by: Aiden Cline <rekram1-node@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
28f6968dda
commit
49d07ffe5f
@@ -2,7 +2,7 @@ export * as ToolOutput from "./tool-output.js"
|
||||
|
||||
import path from "path"
|
||||
import type { Tool } from "@opencode-ai/schema/tool"
|
||||
import { Context, Duration, Effect, Layer, Schedule } from "effect"
|
||||
import { Context, Duration, Effect, Layer, Option, Schedule } from "effect"
|
||||
import { makeGlobalNode, makeLocationNode } from "@opencode-ai/util/effect/app-node"
|
||||
import { FSUtil } from "@opencode-ai/util/fs-util"
|
||||
import { Global } from "@opencode-ai/util/global"
|
||||
@@ -24,15 +24,23 @@ export interface Interface {
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/ToolOutput") {}
|
||||
|
||||
const cleanup = Effect.fn("ToolOutput.cleanup")(function* (fs: FSUtil.Interface, directory: string) {
|
||||
const cutoff = Identifier.timestamp(Identifier.create("tool", "ascending", Date.now() - Duration.toMillis(RETENTION)))
|
||||
const cutoff = Date.now() - Duration.toMillis(RETENTION)
|
||||
const entries = yield* fs.readDirectory(directory).pipe(
|
||||
Effect.map((entries) => entries.filter((entry) => /^tool_[0-9a-f]{12}/.test(entry))),
|
||||
Effect.catch(() => Effect.succeed([])),
|
||||
)
|
||||
for (const entry of entries) {
|
||||
if (Identifier.timestamp(entry) >= cutoff) continue
|
||||
yield* fs.remove(path.join(directory, entry)).pipe(Effect.catch(() => Effect.void))
|
||||
}
|
||||
yield* Effect.forEach(
|
||||
entries,
|
||||
(entry) =>
|
||||
Effect.gen(function* () {
|
||||
const file = path.join(directory, entry)
|
||||
const info = yield* fs.stat(file).pipe(Effect.catch(() => Effect.succeed(undefined)))
|
||||
const mtime = info && Option.getOrUndefined(info.mtime)
|
||||
if (!mtime || mtime.getTime() >= cutoff) return
|
||||
yield* fs.remove(file).pipe(Effect.catch(() => Effect.void))
|
||||
}),
|
||||
{ concurrency: 8, discard: true },
|
||||
)
|
||||
})
|
||||
|
||||
const layer = Layer.effect(
|
||||
|
||||
@@ -143,15 +143,16 @@ describe("ToolOutput", () => {
|
||||
),
|
||||
)
|
||||
|
||||
it.live("removes expired managed files", () =>
|
||||
it.live("uses file modification time when IDs wrap", () =>
|
||||
withStore((output, fs, root) =>
|
||||
Effect.gen(function* () {
|
||||
const directory = path.join(root, ToolOutput.DIRECTORY)
|
||||
const old = path.join(directory, Identifier.create("tool", "ascending", Date.now() - 8 * 24 * 60 * 60 * 1_000))
|
||||
const recent = path.join(directory, Identifier.ascending("tool"))
|
||||
const old = path.join(directory, Identifier.create("tool", "ascending", 2 ** 36 - 1))
|
||||
const recent = path.join(directory, Identifier.create("tool", "ascending", 2 ** 36 + 1))
|
||||
yield* fs.ensureDir(directory)
|
||||
yield* fs.writeFileString(old, "old")
|
||||
yield* fs.writeFileString(recent, "recent")
|
||||
yield* fs.utimes(old, new Date(), new Date(Date.now() - 8 * 24 * 60 * 60 * 1_000))
|
||||
yield* output.cleanup()
|
||||
expect(yield* fs.exists(old)).toBe(false)
|
||||
expect(yield* fs.exists(recent)).toBe(true)
|
||||
|
||||
Reference in New Issue
Block a user