From 0906e227d57c12672a0c8b23cbb20b7b937ae394 Mon Sep 17 00:00:00 2001 From: Ivan Yuriev Date: Fri, 13 Dec 2024 18:12:55 +0300 Subject: [PATCH] improved shutdown --- src/forest.gleam | 29 +++++++++++++++++--------- src/tree_events.gleam | 4 +++- src/treevault.gleam | 47 +++++++++++++++++++++++++++++-------------- 3 files changed, 54 insertions(+), 26 deletions(-) diff --git a/src/forest.gleam b/src/forest.gleam index 1b974d6..2a17e04 100644 --- a/src/forest.gleam +++ b/src/forest.gleam @@ -2,6 +2,7 @@ import gleam/dict.{type Dict} import gleam/erlang/process.{type Subject} import gleam/list import gleam/otp/actor +import gleam/string import gleam/result.{try} import json_serde @@ -9,7 +10,7 @@ import query import simplifile import tree import tree_events.{ - type TreeEvents, GetEvent, RecursiveGetEvent, SetEvent, Shutdown, + type TreeEvents, GetEvent, RecursiveGetEvent, SetEvent, Shutdown, Snapshot, } pub type Message { @@ -95,8 +96,8 @@ fn handle_message(event: TreeEvents, tree) { SetEvent(path, data, client) -> { let res = query.set(tree, path, data) case res { - Error(_) -> { - actor.send(client, res |> result.map(fn(_) { "Ok" })) + Error(err) -> { + actor.send(client, res |> result.map(fn(_) { err |> string.inspect })) actor.continue(tree) } Ok(tree) -> { @@ -105,13 +106,21 @@ fn handle_message(event: TreeEvents, tree) { } } } - Shutdown(filepath) -> { - let json = tree |> json_serde.serialize() - case simplifile.write(filepath, json) { - Error(err) -> - actor.Stop(process.Abnormal(err |> simplifile.describe_error)) - Ok(_) -> actor.Stop(process.Normal) - } + Snapshot(filepath, client) -> { + actor.send(client, snapshot(tree, filepath)) + actor.continue(tree) + } + + Shutdown -> { + actor.Stop(process.Normal) } } } + +fn snapshot(tree, filepath) { + let json = tree |> json_serde.serialize() + case simplifile.write(filepath, json) { + Error(err) -> Error(err |> simplifile.describe_error) + Ok(_) -> Ok("Ok") + } +} diff --git a/src/tree_events.gleam b/src/tree_events.gleam index 20b32da..823204d 100644 --- a/src/tree_events.gleam +++ b/src/tree_events.gleam @@ -16,5 +16,7 @@ pub type TreeEvents { reply_with: Subject(Result(String, QueryError)), ) - Shutdown(filepath: String) + Snapshot(filepath: String, reply_with: Subject(Result(String, String))) + + Shutdown } diff --git a/src/treevault.gleam b/src/treevault.gleam index 771a276..268ae45 100644 --- a/src/treevault.gleam +++ b/src/treevault.gleam @@ -12,13 +12,18 @@ import gleam/otp/actor import gleam/string import gleam_community/ansi import glisten +import query +import query_error import spinner import tree_events -import query -import query_error - pub fn main() { + init() + + process.sleep_forever() +} + +fn init() { let config = config.load("./config.json") |> io.debug let forest = case forest.load(config.snapshots_path, config.forest) { Error(err) -> { @@ -63,7 +68,6 @@ pub fn main() { } } } - actor.continue(state) }) |> glisten.serve(config.port) @@ -90,19 +94,14 @@ fn read_next(forest) { case term { "exit\n" -> { graceful(forest) - let spinner = - spinner.new("Shutting down...") - |> spinner.with_colour(ansi.pink) - |> spinner.start - process.sleep(5000) - "Bye" |> io.println - spinner |> spinner.stop } "help\n" -> { - "Available commands: " |> io.println - "exit" |> io.println + "Available commands:\n" |> io.println + "help\n" |> io.println + "exit\n" |> io.println read_next(forest) } + _ -> { "Unknown command" |> io.println read_next(forest) @@ -113,13 +112,31 @@ fn read_next(forest) { } fn graceful(forest: forest.Forest) { + let spinner = + spinner.new("Shutting down...") + |> spinner.with_colour(ansi.pink) + |> spinner.start + forest.trees |> dict.to_list - |> list.map(fn(tree) { + |> list.each(fn(tree) { let ps = tree.1.1 let path = tree.1.0 - ps |> process.send(tree_events.Shutdown(path)) { "Exiting: " <> tree.0 } |> io.println + let res = + ps + |> process.call_forever(fn(actor) { tree_events.Snapshot(path, actor) }) + case res { + Ok(ok) -> ok + Error(err) -> err + } + |> io.println + + ps |> process.send(tree_events.Shutdown) }) + + process.sleep(1000) + "Bye" |> io.println + spinner |> spinner.stop }