blob: 90c88744c8675fa49d113eeefee457f4a5255652 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
(.module:
[lux #*
["_" test (#+ Test)]
["." io (#+ IO io)]
[control
["M" monad (#+ do Monad)]
["ex" exception]
[concurrency
["." promise ("#/." monad)]]]
[data
["." error]
[text
format]]
[math
["r" random]]]
{1
["." / (#+ actor: message:)]})
(actor: Counter
Nat
((handle message state self)
(do (error.with promise.monad)
[#let [_ (log! "BEFORE")]
output (message state self)
#let [_ (log! "AFTER")]]
(wrap output)))
((stop cause state)
(promise/wrap (log! (if (ex.match? /.poisoned cause)
(format "Counter was poisoned: " (%n state))
cause)))))
(message: #export Counter
(count! {increment Nat} state self Nat)
(let [state' (n/+ increment state)]
(promise/wrap (#error.Success [state' state']))))
(def: #export test
Test
(do r.monad
[_ (wrap [])]
(<| (_.context (%name (name-of /.Actor)))
($_ _.and
(_.test "Can check if an actor is alive."
(io.run (do io.monad
[counter (new@Counter 0)]
(wrap (/.alive? counter)))))
(_.test "Can poison actors."
(io.run (do io.monad
[counter (new@Counter 0)
poisoned? (/.poison counter)]
(wrap (and poisoned?
(not (/.alive? counter)))))))
(_.test "Cannot poison an already dead actor."
(io.run (do io.monad
[counter (new@Counter 0)
first-time (/.poison counter)
second-time (/.poison counter)]
(wrap (and first-time
(not second-time))))))
(:: r.monad wrap
(do promise.monad
[result (do (error.with promise.monad)
[#let [counter (io.run (new@Counter 0))]
output-1 (count! 1 counter)
output-2 (count! 1 counter)
output-3 (count! 1 counter)]
(wrap (and (n/= 1 output-1)
(n/= 2 output-2)
(n/= 3 output-3))))]
(_.assert "Can send messages to actors."
(case result
(#error.Success outcome)
outcome
(#error.Failure error)
#0))))
))))
|