refactor daemon state

This commit is contained in:
JOLIMAITRE Matthieu 2024-02-03 21:01:39 +01:00
parent 6f92727bb3
commit a20745f38d

View file

@ -9,21 +9,11 @@ const log = log_from("daemon");
if (import.meta.main) await main(); if (import.meta.main) await main();
async function main() { async function main() {
const state = await create_state(); const state = await State.load();
const server = await daemon_listen(socket_path()); const server = await daemon_listen(socket_path());
log("listening to", socket_path()); log("listening to", socket_path());
async function finish() { const finish = termination_function(state, server.server);
log("stopping");
server.server.close();
for (const runner of state.enabled.values()) {
try {
await runner.stop();
} catch (_) { /* on s'en fou */ }
}
await Deno.remove(socket_path());
Deno.exit(0);
}
Deno.addSignalListener("SIGINT", finish); Deno.addSignalListener("SIGINT", finish);
for await (const { cmd, respond } of server) { for await (const { cmd, respond } of server) {
@ -87,43 +77,67 @@ async function main() {
} }
} }
async function create_state() { class State {
const self = { enabled;
enabled: new Map<string, Runner>(),
async enable(name: string) { constructor() {
if (self.enabled.has(name)) throw new Error("Container already enabled"); this.enabled = new Map<string, Runner>();
log("loading container", name); }
const config = await ContainerConfig.load(name); // TODO
if (config === null) throw new Error("can't read config"); static async load() {
log("starting container", name); const result = new State();
const runner = new Runner(config); try {
runner.start(); log("trying to recover state from", state_path());
self.enabled.set(name, runner); const loaded = JSON.parse(await Deno.readTextFile(state_path()));
log("container", name, "started"); for (const name of loaded.enabled ?? []) {
}, await result.enable(name);
async disable(name: string) { }
const container = self.enabled.get(name); log("successfully loaded from", state_path());
if (container === undefined) throw new Error("Container not found"); } catch (error) {
await container.stop(); log("experienced failure", error);
self.enabled.delete(name); }
}, return result;
list() { }
return Array.from(self.enabled.keys());
}, async enable(name: string) {
async save() { if (this.enabled.has(name)) throw new Error("Container already enabled");
const content = JSON.stringify({ enabled: self.list() }); log("loading container", name);
await Deno.writeTextFile(state_path(), content); const config = await ContainerConfig.load(name); // TODO
}, if (config === null) throw new Error("can't read config");
}; log("starting container", name);
try { const runner = new Runner(config);
log("trying to recover state from", state_path()); runner.start();
const loaded = JSON.parse(await Deno.readTextFile(state_path())); this.enabled.set(name, runner);
for (const name of loaded.enabled ?? []) { log("container", name, "started");
await self.enable(name); }
}
log("successfully loaded from", state_path()); async disable(name: string) {
} catch (error) { const container = this.enabled.get(name);
log("experienced failure", error); if (container === undefined) throw new Error("Container not found");
await container.stop();
this.enabled.delete(name);
}
list() {
return Array.from(this.enabled.keys());
}
async save() {
const content = JSON.stringify({ enabled: this.list() });
await Deno.writeTextFile(state_path(), content);
} }
return self; }
function termination_function(state: State, server: Deno.Listener<Deno.Conn>) {
return async function finish() {
log("stopping");
server.close();
for (const runner of state.enabled.values()) {
try {
await runner.stop();
} catch (_) { /* on s'en fou */ }
}
await Deno.remove(socket_path());
Deno.exit(0);
};
} }