refine config provider and full replacement flow

This commit is contained in:
Shantur Rathore
2025-11-19 14:43:47 +00:00
parent 7aa94e7a88
commit 7e95005d8c
11 changed files with 296 additions and 266 deletions

View File

@@ -4,21 +4,58 @@ import { cliEvents } from "./cli-events"
export type ConfigData = AppConfig
function isDeepEqual(a: unknown, b: unknown): boolean {
if (a === b) {
return true
}
if (typeof a === "object" && a !== null && typeof b === "object" && b !== null) {
try {
return JSON.stringify(a) === JSON.stringify(b)
} catch (error) {
console.warn("Failed to compare config objects", error)
}
}
return false
}
export class ServerStorage {
private configChangeListeners: Set<() => void> = new Set()
private configChangeListeners: Set<(config: ConfigData) => void> = new Set()
private configCache: ConfigData | null = null
private loadPromise: Promise<ConfigData> | null = null
constructor() {
cliEvents.on("config.appChanged", () => this.notifyConfigChanged())
cliEvents.on("config.appChanged", (event) => {
if (event.type !== "config.appChanged") return
this.setConfigCache(event.config)
})
}
async loadConfig(): Promise<ConfigData> {
const config = await cliApi.fetchConfig()
return config
if (this.configCache) {
return this.configCache
}
if (!this.loadPromise) {
this.loadPromise = cliApi
.fetchConfig()
.then((config) => {
this.setConfigCache(config)
return config
})
.finally(() => {
this.loadPromise = null
})
}
return this.loadPromise
}
async saveConfig(config: ConfigData): Promise<void> {
await cliApi.updateConfig(config)
async updateConfig(next: ConfigData): Promise<ConfigData> {
const nextConfig = await cliApi.updateConfig(next)
this.setConfigCache(nextConfig)
return nextConfig
}
async loadInstanceData(instanceId: string): Promise<InstanceData> {
@@ -33,14 +70,26 @@ export class ServerStorage {
await cliApi.deleteInstanceData(instanceId)
}
onConfigChanged(listener: () => void): () => void {
onConfigChanged(listener: (config: ConfigData) => void): () => void {
this.configChangeListeners.add(listener)
if (this.configCache) {
listener(this.configCache)
}
return () => this.configChangeListeners.delete(listener)
}
private notifyConfigChanged() {
private setConfigCache(config: ConfigData) {
if (this.configCache && isDeepEqual(this.configCache, config)) {
this.configCache = config
return
}
this.configCache = config
this.notifyConfigChanged(config)
}
private notifyConfigChanged(config: ConfigData) {
for (const listener of this.configChangeListeners) {
listener()
listener(config)
}
}
}