git.iko.soy/rowtype-yoga/psfp
on 4e7334b help sign in
rowtype-yoga/psfp/server/src/JobQueueSpec.purs
131 lines 5.1 kB history raw
1module JobQueueSpec where
3import Prelude
5import Data.Time.Duration (class Duration, Seconds(..), fromDuration)
6import Effect.Aff (Milliseconds(..), delay)
7import Effect.Class (liftEffect)
8import Effect.Class.Console (log)
9import Effect.Ref (Ref)
10import Effect.Ref as Ref
11import JobQueue (EnqueueResult(..), NewJob(..), QueueParams, ResourcePool(..), mkQueue)
12import JobQueue as Q
13import Main (execCommand)
14import Playground.Playground (Folder(..))
15import Test.Spec (Spec, describe, it)
16import Test.Spec.Assertions (shouldEqual, shouldNotEqual)
18params ∷ QueueParams
19params =
20 { maxSize: 10
21 , timeout: (1.0 # Seconds) # fromDuration
22 }
24mkJob ∷ String -> Number -> NewJob Unit
25mkJob msg ms = NewJob \_ _ -> delay (ms # Milliseconds) *> log msg
27job1 ∷ NewJob Unit
28job1 = mkJob "Job 1" 10.0
30writeRefJob ∷ ∀ a d. Show a => Duration d => Ref a -> a -> d -> NewJob Unit
31writeRefJob ref a d =
32 NewJob \_ _ -> do
33 let
34 millis ∷ Milliseconds
35 millis = fromDuration d
36 delay millis
37 Ref.write a ref # liftEffect
39pool :: ResourcePool Unit
40pool = ResourcePool [unit, unit, unit]
42spec ∷ Spec Unit
43spec = do
44 describe "The Queue" do
45 it "can't enqueue if maxSize is 0" do
46 q <- mkQueue (params { maxSize = 0 }) pool
47 r <- Q.enqueue job1 q # liftEffect
48 r `shouldEqual` QueueFull
49 it "can enqueue if maxSize is 1" do
50 q <- mkQueue (params { maxSize = 1 }) pool
51 r <- Q.enqueue job1 q # liftEffect
52 r `shouldNotEqual` QueueFull
53 it "runsJobs" do
54 q <- mkQueue (params { maxSize = 1 }) pool
55 ref <- Ref.new false # liftEffect
56 r <- Q.enqueue (writeRefJob ref true (0.0 # Seconds)) q # liftEffect
57 r `shouldNotEqual` QueueFull
58 delay (5.0 # Milliseconds # fromDuration)
59 res <- Ref.read ref # liftEffect
60 res `shouldEqual` true
61 it "kills slow jobs" do
62 q <- mkQueue (params { maxSize = 1, timeout = (3.0 # Milliseconds) }) pool
63 ref <- Ref.new false # liftEffect
64 r <- Q.enqueue (writeRefJob ref true (4.0 # Milliseconds)) q # liftEffect
65 r `shouldNotEqual` QueueFull
66 res <- Ref.read ref # liftEffect
67 delay (9.0 # Milliseconds)
68 res `shouldEqual` false
69 it "runs multiple jobs" do
70 q <- mkQueue (params { maxSize = 3, timeout = (2.0 # Seconds # fromDuration) }) (ResourcePool [unit])
71 ref <- Ref.new 0 # liftEffect
72 let
73 enq n delay = Q.enqueue (writeRefJob ref n delay) q # liftEffect
74 r₁ <- enq 1 (0.1 # Seconds)
75 r₁ `shouldNotEqual` QueueFull
76 r₂ <- enq 2 (0.2 # Seconds)
77 r₂ `shouldNotEqual` QueueFull
78 r₃ <- enq 3 (0.3 # Seconds)
79 r₃ `shouldNotEqual` QueueFull
80 Ref.read ref # liftEffect >>= shouldEqual 0 -- ~0ms
81 delay (0.1 # Seconds # fromDuration)
82 Ref.read ref # liftEffect >>= shouldEqual 1 -- ~150ms
83 delay (0.2 # Seconds # fromDuration)
84 Ref.read ref # liftEffect >>= shouldEqual 2 -- ~250ms
85 delay (0.3 # Seconds # fromDuration)
86 Ref.read ref # liftEffect >>= shouldEqual 3 -- ~350ms
87 it "respects pool size" do
88 q <- mkQueue (params { maxSize = 3, timeout = (2.0 # Seconds # fromDuration) }) (ResourcePool [unit])
89 ref <- Ref.new 0 # liftEffect
90 let
91 enq n delay = Q.enqueue (writeRefJob ref n delay) q # liftEffect
92 r₁ <- enq 1 (0.1 # Seconds)
93 r₁ `shouldNotEqual` QueueFull
94 r₂ <- enq 2 (0.1 # Seconds)
95 r₂ `shouldNotEqual` QueueFull
96 r₃ <- enq 3 (0.1 # Seconds)
97 r₃ `shouldNotEqual` QueueFull
98 Ref.read ref # liftEffect >>= shouldEqual 0 -- ~0ms
99 delay (0.1 # Seconds # fromDuration)
100 Ref.read ref # liftEffect >>= shouldEqual 1 -- ~150ms
101 delay (0.2 # Seconds # fromDuration)
102 Ref.read ref # liftEffect >>= shouldEqual 2 -- ~250ms
103 delay (0.3 # Seconds # fromDuration)
104 Ref.read ref # liftEffect >>= shouldEqual 3 -- ~350ms
105 it "respects pool size (2)" do
106 q <- mkQueue (params { maxSize = 3, timeout = (2.0 # Seconds # fromDuration) }) (ResourcePool [unit, unit, unit])
107 ref <- Ref.new 0 # liftEffect
108 let
109 enq n delay = Q.enqueue (writeRefJob ref n delay) q # liftEffect
110 r₁ <- enq 1 (0.1 # Seconds)
111 r₂ <- enq 2 (0.1 # Seconds)
112 r₃ <- enq 3 (0.1 # Seconds)
113 r₁ `shouldNotEqual` QueueFull
114 r₂ `shouldNotEqual` QueueFull
115 r₃ `shouldNotEqual` QueueFull
116 Ref.read ref # liftEffect >>= shouldEqual 0 -- ~0ms
117 delay (0.15 # Seconds # fromDuration)
118 Ref.read ref # liftEffect >>= shouldEqual 3 -- ~150ms
119 it "can kill processes" do
120 q <- mkQueue (params { maxSize = 1, timeout = (1.0 # Seconds # fromDuration) }) (ResourcePool [unit])
121 resultRef <- Ref.new false # liftEffect
122 let
123 job =
124 NewJob \_ _ -> do
125 res <- execCommand (Folder ".") "sleep 2"
126 Ref.write true resultRef # liftEffect
127 r₁ <- Q.enqueue job q # liftEffect
128 r₁ `shouldNotEqual` QueueFull
129 delay (1.3 # Seconds # fromDuration)
130 result <- Ref.read resultRef # liftEffect
131 result `shouldEqual` false