nginx.clojure.core
achannel
(achannel)
create an asynchronous socket channal.
AsynchronousChannel
protocol
Only works on non-threadpool mode, viz. coroutine mode or default mode.
members
aconnect!
(aconnect! ch url attachment on-err on-done)
Connect to the remote url.
`url can be "192.168.2.34:80" , "www.bing.com:80", or unix domain socket "unix:/var/mytest/server.sock"
`on-err and `on-done are functions which have the form (fn[status,attachment]
when passed to `on-err, `status is an error code which range from
NginxClojureAsynSocket.NGX_HTTP_CLOJURE_SOCKET_ERR to NGX_HTTP_CLOJURE_SOCKET_ERR_OUTOFMEMORY
when passed to `on-done `status is always 0.
aget-context
(aget-context ch)
arecv!
(arecv! ch buf attachment on-err on-done)
receive data from the channel.
`buf can be byte[] or ByteBuffer
`on-err and `on-done are functions which have the form (fn[status,attachment]
when passed to `on-err, `status is an error code which is eof (0) or range from
NginxClojureAsynSocket.NGX_HTTP_CLOJURE_SOCKET_ERR to NGX_HTTP_CLOJURE_SOCKET_ERR_OUTOFMEMORY
when passed to `on-done `status is always > 0 and means number of bytes received.
asend!
(asend! ch data attachment on-err on-done)
send data to the channel.
`data can be String, byte[] or ByteBuffer
`on-err and `on-done are functions which have the form (fn[status,attachment]
when passed to `on-err, `status is an error code which is eof (0) or range from
NginxClojureAsynSocket.NGX_HTTP_CLOJURE_SOCKET_ERR to NGX_HTTP_CLOJURE_SOCKET_ERR_OUTOFMEMORY
when passed to `on-done `status is always > 0 and means number of bytes sent.
aset-context!
(aset-context! ch ctx)
aset-timeout!
(aset-timeout! ch connect-timeout read-timeout write-timeout)
The timeout unit is millisecond.
if timeout < 0 it will be ignored, if timeout = 0 it means no timeout settings
ashutdown!
(ashutdown! ch how)
shutdown some kind of events trigger of the socket
`how can be :soft-read :soft-write :soft-both :read :write :both. If we use :soft-xxx it won't
shutdown the physical socket and just turn off the events trigger for better performance.
Otherwise it will shutdown the physical socket, more details can be found from http://linux.die.net/man/2/shutdown
error-str
(error-str ch code)
return the error string message from the error code
broadcast!
(broadcast! event)
Broadcast a event to all nginx worker processes.
This function can be used to notify all subscribers in different nginx
worker processes from the same nginx instance.
`event has the form {:data data} or {:tag tag, :data data}
`data can be Long, String, byte[]. If it is long integer it must be less than 0x0100000000000000L
If it is string or bytes, it must be less than PIPE_BUF - 8, generally on Linux/Windows is 4088,
on MacosX is 504
`data will be truncated if its length exceeds this limitation.
If `tag is given, `data can also be long integer which means this event is
very simple and only has a event id without any body or body is stored externally.
The default tag value is 0x20 when `msg is Long otherwise the default value is 0x80.
Here is a list of `tag values range:
* System Event :0x00 ~ 0x1f -- Application should not use them
* Application Event : 0x20 ~ 0xff
* Simple Event : 0x00 ~ 0x7f, only event id (7Byte), no message body
* Complex Event : 0x80 ~ 0xff
build-topic!
(build-topic! name)
co-pcalls
(co-pcalls & fns)
Executes the no-arg fns in parallel coroutines, returning a sequence of their values
If there's no coroutine support, it will turn to use thread pool to make testing with lein-ring easy.
e.g. fetch two services in parallel:
(let [[r1, r2] (co-pcalls (fn[] (client/get "http://page1-url")) (fn[] (client/get "http://page2-url")))]
;println bodies of two remote responses
(println (str (:body r1) "====\n" (:body r2) ))
co-pvalues
macro
(co-pvalues & exprs)
Returns a sequence of the values of the exprs, which are evaluated in parallel coroutines.
If there's no coroutine support, it will turn to use thread pool to make testing with lein-ring easy.
e.g. fetch two services in parallel:
(let [[r1, r2] (co-pvalues (client/get "http://page1-url") (client/get "http://page2-url"))]
;println bodies of two remote responses
(println (str (:body r1) "====\n" (:body r2) ))
get-ngx-var
(get-ngx-var req name)
hijack!
(hijack! req ignore-nginx-filter?)
Hijack a nginx request and return a server channel.
After being hijacked, the ring handler's result will be ignored.
If ignore-nginx-filter? is true all data output to channel won't be filtered
by any nginx HTTP header/body filters such as gzip filter, chucked filter, etc.
We can use this function to implement long polling / Server Sent Events (SSE) easily.
HttpServerChannel
protocol
members
add-aggregated-listener!
(add-aggregated-listener! ch max-message-size callbacks-map)
Add an aggregated message listener.
callbacks-map is a map whose key can be either of :on-open,:on-message,:on-close,:on-error
the value of :on-open is a function like (fn[ch]...)
the value of :on-message is a function like (fn[ch message]...)
the value of :on-close is a function like (fn[ch reason]...)
the value of :on-error is a function like (fn[ch status])
add-listener!
(add-listener! ch callbacks-map)
Add a channel event listener.
callbacks-map is a map whose key can be either of :on-open,:on-message,:on-close,:on-error
the value of :on-open is a function like (fn[ch]...)
the value of :on-message is a function like (fn[ch message remaining?]...)
the value of :on-close is a function like (fn[ch reason]...)
the value of :on-error is a function like (fn[ch status])
close!
(close! ch)
Asynchronously close the channel. If there's remaining data to send it won't block
current thread and will flush data on the background asynchronously and later close the channel safely
get-context
(get-context ch)
on-close!
(on-close! ch attachment listener)
Add a close event listener.
`attachement is a object which will be passed to listener when close event happens
`listener is a function like (fn[attachement] ... )
A close event will happen immediately when a channel is closed by either of these three cases:
(1) channel close function/method is invoked on this channel, e.g. (close! ch)
(2) inner unrecoverable error happens with this channel, e.g. not enough memory to read/write
(3) remote client connection is closed or broken.
send!
(send! ch data flush? last?)
Asynchronously send data to channel without blocking current thread.
data can be byte[], String, or ByteBuffer
If flush? is false it will put data into buffers chain eitherwise it will write data to network.
If close? is true it will close channel after all data are sent.
send-response!
(send-response! ch resp)
Asynchronously send a complete HTTP response to channel and close channel after all data are sent.
resp is a ring Response Map, e.g. {:status 200, headers {"Content-Type" "text/html"}, :body "Hello, Nginx-Clojure!" } .
set-context!
(set-context! ch ctx)
websocket-upgrade!
(websocket-upgrade! ch send-err-for-nonwebsocekt?)
Send upgrade headers and return true if upgrade success
If `send-err-for-nonwebsocekt?` is true it will send error response.
on-broadcast!
(on-broadcast! f)
Add a broadcasted event listener and return a removal function to delete the listener
Function f is like (fn[event] ... ) and event has the form {:tag tag, :data `bytes or long`, :offset offset :length length }
`offset & `length are meamingless if data is a long integer.
on-broadcast-event-decode!
(on-broadcast-event-decode! tester decoder)
Add a pair of tester & decoder to broadcast event decoder chain
and return a removal function to delete the decoder.
Decoders will be called one by one and the current decode result will be past to the next decoder.
Decoders should return decoded event which has the form {:tag tag, :data `any type of data`, :offset offset :length length }
offset & `length are meamingless if data is a long integer.
Function tester is a checker and only if it return true the decoder will be invoked.
PubSubTopic
protocol
members
pub!
(pub! topic message)
Publishs a message to the topic
sub!
(sub! topic att callback)
Subscribes to a topic and returns an unsubscribing function.
When a message comes the callback function will be invoked. e.g.
(def my-topic (build-topic! "my-topic"))
(sub! my-topic (atomic 0)
(function [message counter]
(println "received :" message ", times=" (swap counter inc)))
set-ngx-var!
(set-ngx-var! req name val)
without-coroutine
(without-coroutine f)
wrap a handler `f` to a new handler which will keep away the coroutine context