(defn start-request-processor
[request-channel]
(go
(while true
(let [[request response-channel] (! response-channel response))))
nil)
request channel is a
parameter
Slide 32
Slide 32 text
(defn start-request-processor
[request-channel]
(go
(while true
(let [[request response-channel] (! response-channel response))))
nil)
Client sends the request and a
channel for the response
Slide 33
Slide 33 text
(defn start-request-processor
[request-channel]
(go
(while true
(let [[request response-channel] (! response-channel response))))
nil)
timeout is part of core.async
Slide 34
Slide 34 text
(defn start-request-processor
[request-channel]
(go
(while true
(let [[request response-channel] (! response-channel response))))
nil)
Send the response where the client
specified
(defn process-request
[request processor-channel]
(let [response-channel (chan 1)]
(>!! processor-channel [request response-channel])
response-channel))
Buffer for 1 response, to
keep from blocking/parking
Slide 37
Slide 37 text
(defn process-request
[request processor-channel]
(let [response-channel (chan 1)]
(>!! processor-channel [request response-channel])
response-channel))
The API: which channel, what data
Slide 38
Slide 38 text
0ms
1,500ms
3,000ms
4,500ms
6,000ms
7,500ms
9,000ms
10,500ms
12,000ms
13,500ms
15,000ms
1 2 5 10 25
Total Processing Time
Number of processing go blocks
100 Requests 250 Requests
Caution: Very Not
Scientific!
⚠
Slide 39
Slide 39 text
How deep a buffer on the channel?
How many channel processors?
Is the channel buffer lossy or blocking?
Timeout the operation if not fast
enough?
(defn start-request-processor
[request-channel poison-pill-channel]
(go
(loop []
(alt!
poison-pill-channel nil
request-channel ([[request response-channel]]
(let [_ (! response-channel response)
(recur)))
:priority true))))
Destructure the value
taken from channel
Slide 54
Slide 54 text
(defn start-request-processor
[request-channel poison-pill-channel]
(go
(loop []
(alt!
poison-pill-channel nil
request-channel ([[request response-channel]]
(let [_ (! response-channel response)
(recur)))
:priority true))))
Could be a go block, or
function that uses a go block
thread pools
(thread) ➠ async-thread-macro-#
cached thread pool
threads discarded after 60 seconds
(go …) etc ➠ async-dispatch-#
fixed thread pool, 2 * # of processors + 42
All daemon threads
Slide 60
Slide 60 text
thread pools
(go …) blocks should never block (only park)
Use (thread …) for code that might block:
file system access, database access
Slide 61
Slide 61 text
java.lang.AssertionError: Assert failed: No more than 1024 pending puts
are allowed on a single channel. Consider using a windowed buffer.
(< (.size puts) impl/MAX-QUEUE-SIZE)
at
clojure.core.async.impl.channels.ManyToManyChannel.put_BANG_(channels.clj:
95)
at clojure.core.async.impl.ioc_macros$put_BANG_.invoke(ioc_macros.clj:
824)
at poc.async_alts$get_answer
$fn__1764$state_machine__1239__auto____1765.invoke(async_alts.clj:23)
at clojure.core.async.impl.ioc_macros
$run_state_machine.invoke(ioc_macros.clj:812)
at poc.async_alts$get_answer$fn__1764.invoke(async_alts.clj:23)
at clojure.lang.AFn.run(AFn.java:24)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:
1145)
at java.util.concurrent.ThreadPoolExecutor
$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Slide 62
Slide 62 text
Testing
Easy to provide mock channel handlers
alts! may be harder to deal with