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