daemon/entry.bend
cswap-bend-cli@0.1.0.0 · 179 lines · 32 definitions
1import Base
2import cswap-bend-cli@0.1.0.0/fs.bend as Fs
3import cswap-bend-cli@0.1.0.0/act.bend as Act
4import cswap-bend-cli@0.1.0.0/clock.bend as Clock
5import cswap-bend-cli@0.1.0.0/store.bend as Store
6import cswap-bend-cli@0.1.0.0/cmd.bend as Cmd
7import cswap-bend-cli@0.1.0.0/store/base.bend as SBase
8import cswap-bend-cli@0.1.0.0/store/seq.bend as SSeq
9import cswap-bend-cli@0.1.0.0/swlive.bend as L
10import cswap-bend-cli@0.1.0.0/daemon/config.bend as Cfg
11import cswap-bend-cli@0.1.0.0/fmt/out.bend as O
12import cswap-bend-cli@0.1.0.0/daemon/live.bend as Lv
13import cswap-bend-cli@0.1.0.0/profflag.bend as Profflag
14import cswap-bend-cli@0.1.0.0/daemon/auto.bend as Auto
15import cswap-bend-cli@0.1.0.0/policy/types.bend as PT
16import cswap-bend-cli@0.1.0.0/daemon/pidlock.bend as Pid
17import cswap-bend-cli@0.1.0.0/daemon/shadowcli.bend as ShC
18
19
20
21
22
23def ActM(-A: Type) -> Type:
24 Act.of(A)
25
26def ActM.pure(-A: Type, x: A) -> Act.of(A):
27 Act.pure(A, x)
28
29def ActM.bind(-A: Type, -B: Type, m: Act.of(A), f: A -> Act.of(B)) -> Act.of(B):
30 Act.bind(A, B, m, f)
31
32def env_or(r: Result<&1, &1, U32 & String, String>, +d: String) -> String:
33 match r:
34 case Fail{e}:
35 d
36 case Done{s}:
37 s
38
39def oracle_of(r: Result<&1, &1, U32 & String, String>) -> L.Oracle:
40 match r:
41 case Fail{e}:
42 L.OHttp{}
43 case Done{p}:
44 L.OFile{p}
45
46
47
48
49def switch_opts(d: Result<&1, &1, U32 & String, String>, o: Result<&1, &1, U32 & String, String>) -> L.Opts:
50 L.Opts{Maybe.default(&2, U32, U32.read(env_or(d, "2000")), 2000), oracle_of(o)}
51
52def settings_text(r: Fs.Res(String)) -> String:
53 match r:
54 case Fail{e}:
55 ""
56 case Done{t}:
57 t
58
59def settings_io(+ctx: SBase.Ctx) -> IO(String):
60 IO.bind(Fs.Res(String), String, Fs.read_file(SBase.root_of(ctx) ++ "/settings.json"), r => IO.pure(String, settings_text(r)))
61
62def tick_body(+r: Auto.Run, +once: Bool) -> Act.of(U32):
63 Act.cond(U32, once, Auto.once(r), Auto.forever(r, PT.fresh_mem(), False{}))
64
65
66def body(+r: Auto.Run, +once: Bool) -> Act.of(U32):
67 do ActM<U32>:
68 Act.lift(Unit, IO.write(O.stream_head(Auto.run_fmt(r))))
69 tick_body(r, once)
70
71def flag_dry(+f: Cfg.Flags) -> Bool:
72 match f:
73 case Cfg.Flags{o, j, d, th, iv, cd, st, md, ia}:
74 d
75
76def flag_fmt(+f: Cfg.Flags) -> O.Fmt:
77 match f:
78 case Cfg.Flags{o, j, d, th, iv, cd, st, md, ia}:
79 O.of_code(j)
80
81def flag_once(+f: Cfg.Flags) -> Bool:
82 match f:
83 case Cfg.Flags{o, j, d, th, iv, cd, st, md, ia}:
84 o
85
86def started(+ctx: SBase.Ctx, +f: Cfg.Flags, +state_dir: String, +opts: L.Opts, +version: String, +cfg: Cfg.Cfg, +pid: U32, +ts: String, +lv: Lv.Live) -> Act.of(U32):
87 Pid.with_pidlock(U32, state_dir, body(Auto.Run{ctx, state_dir, cfg, flag_fmt(f), flag_dry(f), opts, ts, version, pid, lv}, flag_once(f)))
88
89def go3(+ctx: SBase.Ctx, +f: Cfg.Flags, +state_dir: String, +opts: L.Opts, +version: String, +text: String, +over: Maybe<&2, String>) -> Act.of(U32):
90 do ActM<U32>:
91 pid : U32 <- Act.lift(U32, Pid.my_pid())
92 t : U32 <- Act.lift(U32, Clock.now_s())
93 started(ctx, f, state_dir, opts, version, Lv.cfg_for(text, f, over), pid, Clock.iso8601_utc(t), Lv.live_for(text, f, over))
94
95
96def go2(+bad: Maybe<&2, String>, +ctx: SBase.Ctx, +f: Cfg.Flags, +state_dir: String, +opts: L.Opts, +version: String, +text: String, +over: Maybe<&2, String>) -> Act.of(U32):
97 match bad:
98 case Some{n}:
99 Act.fail(U32, 2, "cswap auto: error: unknown profile '" ++ n ++ "'; `cswap profile list` shows the profiles")
100 case None{}:
101 go3(ctx, f, state_dir, opts, version, text, over)
102
103def go(+ctx: SBase.Ctx, +f: Cfg.Flags, +state_dir: String, +opts: L.Opts, +version: String, +over: Maybe<&2, String>) -> Act.of(U32):
104 do ActM<U32>:
105 +text : String <- Act.lift(String, settings_io(ctx))
106 go2(Lv.unknown(text, over), ctx, f, state_dir, opts, version, text, over)
107
108def with_flags(+ctx: SBase.Ctx, +state_dir: String, +opts: L.Opts, +version: String, +over: Maybe<&2, String>, r: Result<&2, &2, String, Cfg.Flags>) -> Act.of(U32):
109 match r:
110 case Fail{msg}:
111 Act.fail(U32, 2, "cswap auto: error: " ++ msg)
112 case Done{f}:
113 go(ctx, f, state_dir, opts, version, over)
114
115
116
117def plain3(+ok: Bool, +ctx: SBase.Ctx, +state_dir: String, +opts: L.Opts, +version: String, +over: Maybe<&2, String>, +rest: List<&2, String>, +err: String) -> Act.of(U32):
118 match ok:
119 case True{}:
120 with_flags(ctx, state_dir, opts, version, over, Cfg.parse_flags(rest))
121 case False{}:
122 Act.fail(U32, 2, "cswap auto: error: " ++ err)
123
124def plain2(+ctx: SBase.Ctx, +state_dir: String, +opts: L.Opts, +version: String, +sp: Profflag.Split) -> Act.of(U32):
125 match sp:
126 case Profflag.Split{rest, over, err, pending}:
127 plain3(String.is_empty(err), ctx, state_dir, opts, version, over, rest, err)
128
129def plain(+ctx: SBase.Ctx, +args: List<&2, String>, +state_dir: String, +opts: L.Opts, +version: String) -> Act.of(U32):
130 plain2(ctx, state_dir, opts, version, Profflag.split(args))
131
132def routed(+ctx: SBase.Ctx, +sp: ShC.Split, +state_dir: String, +opts: L.Opts, +version: String) -> Act.of(U32):
133 Act.cond(U32, ShC.sp_shadow(sp), ShC.run(ctx, opts, sp), plain(ctx, ShC.sp_rest(sp), state_dir, opts, version))
134
135def auto(+ctx: SBase.Ctx, +args: List<&2, String>, +state_dir: String, +opts: L.Opts, +version: String) -> Act.of(U32):
136 routed(ctx, ShC.split(Cfg.normalize(args), False{}), state_dir, opts, version)
137
138
139
140
141def code_for(+code: U32) -> U32:
142 SSeq.sel.u(U32.is_eq(code, 2), 2, 1)
143
144def finish(r: Fs.Res(U32)) -> IO(Unit):
145 match r:
146 case Done{code}:
147 IO.exit(code)
148 case Fail{(code, msg)}:
149 IO.bind(Unit, Unit, IO.print_err(msg), u => IO.exit(code_for(code)))
150
151
152
153def cmd_of(r: Fs.Res(U32)) -> IO(Cmd.Out):
154 match r:
155 case Done{code}:
156 IO.pure(Cmd.Out, Cmd.Out{code, "", ""})
157 case Fail{(code, msg)}:
158 IO.pure(Cmd.Out, Cmd.Out{code_for(code), "", msg ++ "\n"})
159
160def run2(+ctx: SBase.Ctx, +args: List<&2, String>, +version: String, st: Result<&1, &1, U32 & String, String>, d: Result<&1, &1, U32 & String, String>, o: Result<&1, &1, U32 & String, String>) -> IO(Fs.Res(U32)):
161 auto(ctx, args, env_or(st, SBase.root_of(ctx)), switch_opts(d, o), version)
162
163def run1(+ctx: SBase.Ctx, +args: List<&2, String>, +version: String, st: Result<&1, &1, U32 & String, String>, d: Result<&1, &1, U32 & String, String>) -> IO(Fs.Res(U32)):
164 IO.bind(Result<&1, &1, U32 & String, String>, Fs.Res(U32), IO.get_env("CSWAP_SWITCH_ORACLE_FILE"), o => run2(ctx, args, version, st, d, o))
165
166def run0(+ctx: SBase.Ctx, +args: List<&2, String>, +version: String, st: Result<&1, &1, U32 & String, String>) -> IO(Fs.Res(U32)):
167 IO.bind(Result<&1, &1, U32 & String, String>, Fs.Res(U32), IO.get_env("CSWAP_SWITCH_VERIFY_DELAY_MS"), d => run1(ctx, args, version, st, d))
168
169
170def run(+args: List<&2, String>, +version: String) -> IO(Fs.Res(U32)):
171 IO.bind(SBase.Ctx, Fs.Res(U32), Store.ctx_env(), ctx => IO.bind(Result<&1, &1, U32 & String, String>, Fs.Res(U32), IO.get_env("CSWAP_STATE_DIR"), st => run0(ctx, args, version, st)))
172
173
174def auto_main(+args: List<&2, String>, +version: String) -> IO(Unit):
175 IO.bind(Fs.Res(U32), Unit, run(args, version), finish)
176
177
178def auto_cmd(+args: List<&2, String>, +version: String) -> IO(Cmd.Out):
179 IO.bind(Fs.Res(U32), Cmd.Out, run(args, version), cmd_of)