domain/architecture/system/deployment/ops.bend
near-v-framework@0.3.0.0 · 108 lines · 0 definitions
1import Base
2import near-v-framework@0.3.0.0/domain/architecture/system/deployment/type.bend as D
3
4# ---- what a deploy breaks: compared with what was deployed before (its address and stores) ----
5def address(d: D.Deployment) -> String:
6 match d:
7 case D.Deployment{a, _, _, _}:
8 a
9
10def stores(d: D.Deployment) -> List<&2, String>:
11 match d:
12 case D.Deployment{_, ss, _, _}:
13 ss
14
15def accepted(d: D.Deployment) -> List<&2, D.Break>:
16 match d:
17 case D.Deployment{_, _, acc, _}:
18 acc
19
20def keep_break(present: Bool, +o: String, rest: List<&2, D.Break>) -> List<&2, D.Break>:
21 match present:
22 case True{}:
23 rest
24 case False{}:
25 D.StoreRemoved{o} <> rest
26
27def removed(olds: List<&2, String>, +news: List<&2, String>) -> List<&2, D.Break>:
28 match olds:
29 case []:
30 []
31 case +o <> rest:
32 keep_break(List.contains(~String, ~String.eq, news, o), o, removed(rest, news))
33
34# The address changing, then each store the new deployment drops. A first deploy (no address before) breaks nothing.
35def breaks(+before: String, olds: List<&2, String>, +d: D.Deployment) -> List<&2, D.Break>:
36 List.append(&2, D.Break,
37 Bool.pick(List<&2, D.Break>, String.is_empty(before) || String.eq(before, address(d)), [], [D.AddressChanged{}]),
38 removed(olds, stores(d)))
39
40def break_eq(a: D.Break, b: D.Break) -> Bool:
41 match a b:
42 case D.AddressChanged{} D.AddressChanged{}:
43 True{}
44 case D.StoreRemoved{x} D.StoreRemoved{y}:
45 String.eq(x, y)
46 case _ _:
47 False{}
48
49def breaks_eq(a: List<&2, D.Break>, b: List<&2, D.Break>) -> Bool:
50 match a:
51 case []:
52 List.is_empty(&2, D.Break, b)
53 case x <> xs:
54 match b:
55 case []:
56 False{}
57 case y <> ys:
58 break_eq(x, y) && breaks_eq(xs, ys)
59
60def show_break(b: D.Break) -> String:
61 match b:
62 case D.AddressChanged{}:
63 "the address changes"
64 case D.StoreRemoved{n}:
65 "store " ++ n ++ " is removed"
66
67def shown(bs: List<&2, D.Break>) -> List<&2, String>:
68 match bs:
69 case []:
70 []
71 case b <> rest:
72 show_break(b) <> shown(rest)
73
74def show_breaks(bs: List<&2, D.Break>) -> String:
75 String.join(shown(bs), ", ")
76
77def store_lines(ss: List<&2, String>) -> String:
78 match ss:
79 case []:
80 ""
81 case s <> rest:
82 "store " ++ s ++ "\n" ++ store_lines(rest)
83
84# What a deploy records as deployed: the address, then one store per line.
85def record(+d: D.Deployment) -> String:
86 "address " ++ address(d) ++ "\n" ++ store_lines(stores(d))
87
88def keep_rest(c: Bool, +prefix: String, l: String, rest: List<&2, String>) -> List<&2, String>:
89 match c:
90 case True{}:
91 String.drop(l, String.length(prefix)) <> rest
92 case False{}:
93 rest
94
95# The lines that start with a prefix, without it.
96def after(+prefix: String, ls: List<&2, String>) -> List<&2, String>:
97 match ls:
98 case []:
99 []
100 case +l <> rest:
101 keep_rest(String.starts_with(l, prefix), prefix, l, after(prefix, rest))
102
103# The address and stores in a record ("" and [] when nothing was deployed).
104def recorded_address(+text: String) -> String:
105 Maybe.default(&2, String, List.head(&2, String, after("address ", String.lines(text))), "")
106
107def recorded_stores(+text: String) -> List<&2, String>:
108 after("store ", String.lines(text))