dify/cli/src/cache/nudge-store.ts
Yunlu Wen c0ee821d45
refactor: use absolute path for inter dir importing (#36822)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-01 01:32:16 +00:00

72 lines
2.2 KiB
TypeScript

import type { Store } from '@/store/store'
import { CACHE_NUDGE, getCache } from '@/store/manager'
export const WARN_INTERVAL_MS = 24 * 60 * 60 * 1000
// Single top-level key holding host→ISO map. Hosts contain dots
// (cloud.dify.ai), so we cannot use them as Store paths directly —
// `doSet` would split on dots and create nested objects.
const WARNED_KEY = { key: 'warned', default: {} as Record<string, string> } as const
export type NudgeStore = {
readonly canWarn: (host: string, now?: Date) => boolean
readonly markWarned: (host: string, now?: Date) => Promise<void>
}
export type NudgeStoreOptions = {
readonly store?: Store
readonly now?: () => Date
readonly intervalMs?: number
}
export async function loadNudgeStore(opts: NudgeStoreOptions = {}): Promise<NudgeStore> {
const store = opts.store ?? getCache(CACHE_NUDGE)
const intervalMs = opts.intervalMs ?? WARN_INTERVAL_MS
const clock = opts.now ?? (() => new Date())
const memory = readWarned(store)
return {
canWarn: (host, now) => {
const last = memory.get(host)
if (last === undefined)
return true
const elapsed = Math.max(0, (now ?? clock()).getTime() - last)
return elapsed >= intervalMs
},
markWarned: async (host, now) => {
const stamp = (now ?? clock()).getTime()
memory.set(host, stamp)
// Re-read disk inside the write cycle so concurrent processes touching
// different hosts don't clobber each other's stamps. Same-host writers
// converge on a near-identical timestamp, so order doesn't matter.
const onDisk = readWarned(store)
onDisk.set(host, stamp)
writeWarned(store, onDisk)
},
}
}
function readWarned(store: Store): Map<string, number> {
const out = new Map<string, number>()
let raw: Record<string, string>
try {
raw = store.get(WARNED_KEY)
}
catch {
return out
}
for (const [host, iso] of Object.entries(raw)) {
const t = Date.parse(iso)
if (!Number.isNaN(t))
out.set(host, t)
}
return out
}
function writeWarned(store: Store, state: Map<string, number>): void {
const warned: Record<string, string> = {}
for (const [host, t] of state)
warned[host] = new Date(t).toISOString()
store.set(WARNED_KEY, warned)
}