Skip to content

Commit 5c2ed2f

Browse files
committed
perf(file): cache external session search results
1 parent b3d35f7 commit 5c2ed2f

File tree

1 file changed

+30
-12
lines changed

1 file changed

+30
-12
lines changed

packages/opencode/src/file/index.ts

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ import { Session } from "../session"
1515

1616
export namespace File {
1717
const log = Log.create({ service: "file" })
18+
type SearchResult = { files: string[]; dirs: string[] }
19+
type ExternalCache = { key: string; time: number; value: SearchResult }
20+
const EXTERNAL_CACHE_TTL = 2_000
21+
const externalCache = new Map<string, ExternalCache>()
22+
23+
function empty(): SearchResult {
24+
return { files: [], dirs: [] }
25+
}
1826

1927
export const Info = z
2028
.object({
@@ -333,13 +341,12 @@ export namespace File {
333341
}
334342

335343
const state = Instance.state(async () => {
336-
type Entry = { files: string[]; dirs: string[] }
337-
let cache: Entry = { files: [], dirs: [] }
344+
let cache: SearchResult = empty()
338345
let fetching = false
339346

340347
const isGlobalHome = Instance.directory === Global.Path.home && Instance.project.id === "global"
341348

342-
const fn = async (result: Entry) => {
349+
const fn = async (result: SearchResult) => {
343350
// Disable scanning if in root of file system
344351
if (Instance.directory === path.parse(Instance.directory).root) return
345352
fetching = true
@@ -401,10 +408,7 @@ export namespace File {
401408
return {
402409
async files() {
403410
if (!fetching) {
404-
fn({
405-
files: [],
406-
dirs: [],
407-
})
411+
fn(empty())
408412
}
409413
return cache
410414
},
@@ -620,10 +624,13 @@ export namespace File {
620624
}
621625

622626
async function external(sessionID?: string) {
623-
if (!sessionID) return { files: [], dirs: [] }
627+
if (!sessionID) return empty()
624628

625629
const session = await Session.get(sessionID).catch(() => undefined)
626-
if (!session?.permission) return { files: [], dirs: [] }
630+
if (!session?.permission) {
631+
externalCache.delete(sessionID)
632+
return empty()
633+
}
627634

628635
const dirs = Array.from(
629636
new Set(
@@ -632,9 +639,18 @@ export namespace File {
632639
.map((rule) => externalDirectory(rule.pattern))
633640
.filter((rule): rule is string => Boolean(rule)),
634641
),
635-
)
642+
).toSorted()
636643

637-
if (!dirs.length) return { files: [], dirs: [] }
644+
const key = dirs.join("\0")
645+
const now = Date.now()
646+
const cached = externalCache.get(sessionID)
647+
if (cached && cached.key === key && now - cached.time < EXTERNAL_CACHE_TTL) return cached.value
648+
649+
if (!dirs.length) {
650+
const value = empty()
651+
externalCache.set(sessionID, { key, time: now, value })
652+
return value
653+
}
638654

639655
const files: string[] = []
640656
const folders = new Set<string>()
@@ -663,10 +679,12 @@ export namespace File {
663679
}
664680
}
665681

666-
return {
682+
const value = {
667683
files: Array.from(new Set(files)),
668684
dirs: Array.from(folders),
669685
}
686+
externalCache.set(sessionID, { key, time: now, value })
687+
return value
670688
}
671689

672690
export async function search(input: {

0 commit comments

Comments
 (0)