Skip to content

Commit 6b7e31d

Browse files
committed
add tutorials code, fix markdown
1 parent b3fb745 commit 6b7e31d

19 files changed

+274
-28
lines changed

_includes/cl-bunny/tutorials/tutorial-five-cl.md

+5-3
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1414
See the License for the specific language governing permissions and
1515
limitations under the License.
1616
-->
17+
1718
# RabbitMQ tutorial - Topics
1819

1920
## Topics
21+
2022
### (using [cl-bunny](http://cl-rabbit.io/cl-bunny))
2123

22-
In the [previous tutorial](tutorial-four-cl.md) we improved our
24+
In the [previous tutorial](tutorial-four-cl.html) we improved our
2325
logging system. Instead of using a `fanout` exchange only capable of
2426
dummy broadcasting, we used a `direct` one, and gained a possibility
2527
of selectively receiving the logs.
@@ -114,7 +116,7 @@ start off with a working assumption that the routing keys of logs will
114116
have two words: "`<facility>.<severity>`".
115117

116118
The code is almost the same as in the
117-
[previous tutorial](tutorial-four-cl.md).
119+
[previous tutorial](tutorial-four-cl.html).
118120

119121
The code for `emit_log_topic.lisp`:
120122

@@ -178,4 +180,4 @@ with more than two routing key parameters.
178180
(Full source code for [emit_log_topic.lisp](code/emit_log_topic.lisp)
179181
and [receive_logs_topic.lisp](code/receive_logs_topic.lisp))
180182

181-
Next, find out how to do a round trip message as a remote procedure call in [tutorial 6](tutorial-six-cl.md)
183+
Next, find out how to do a round trip message as a remote procedure call in [tutorial 6](tutorial-six-cl.html)

_includes/cl-bunny/tutorials/tutorial-four-cl.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1414
See the License for the specific language governing permissions and
1515
limitations under the License.
1616
-->
17+
1718
# RabbitMQ tutorial - Routing
1819

1920
## Routing
21+
2022
### (using [cl-bunny](http://cl-rabbit.io/cl-bunny))
2123

22-
In the [previous tutorial](tutorial-three-cl.md) we built a
24+
In the [previous tutorial](tutorial-three-cl.html) we built a
2325
simple logging system. We were able to broadcast log messages to many
2426
receivers.
2527

@@ -187,5 +189,5 @@ And, for example, to emit an `error` log message just type:
187189
(Full source code for [(emit_log_direct.lisp source)](code/emit_log_direct.lisp)
188190
and [(receive_logs_direct.lisp source)](code/receive_logs_direct.lisp))
189191

190-
Move on to [tutorial 5](tutorial-five-cl.md) to find out how to listen
192+
Move on to [tutorial 5](tutorial-five-cl.html) to find out how to listen
191193
for messages based on a pattern.

_includes/cl-bunny/tutorials/tutorial-one-cl.md

+19-17
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ RabbitMQ, and messaging in general, uses some jargon.
4747
Note that the producer, consumer, and broker do not have to reside on
4848
the same machine; indeed in most applications they don't.
4949

50-
## "Hello World"
50+
51+
## "Hello World"
52+
5153
### (using the cl-bunny Common Lisp Client)
5254

5355
In this part of the tutorial we'll write two small programs in Lisp; a
@@ -66,7 +68,7 @@ on behalf of the consumer.
6668
> RabbitMQ speaks AMQP 0.9.1, which is an open,
6769
> general-purpose protocol for messaging. There are a number of clients
6870
> for RabbitMQ in [many different
69-
> languages](/devtools.html). We'll
71+
> languages](http://www.rabbitmq.com/devtools.html). We'll
7072
> use the cl-bunny client in this tutorial.
7173
>
7274
> First, install cl-bunny using [official webpage](http://cl-rabbit.io/cl-bunny)
@@ -117,11 +119,11 @@ things done resides:
117119
To send, we must declare a queue for us to send to; then we can publish a message
118120
to the queue:
119121

120-
(with-connection ("amqp://")
121-
(with-channel ()
122-
(let ((x (default-exchange)))
123-
(publish x "Hello world!" :routing-key "hello")
124-
(format t " [x] Sent 'Hello World!'~%"))))
122+
(with-connection ("amqp://")
123+
(with-channel ()
124+
(let ((x (default-exchange)))
125+
(publish x "Hello world!" :routing-key "hello")
126+
(format t " [x] Sent 'Hello World!'~%"))))
125127

126128
Declaring a queue is idempotent - it will only be created if it doesn't
127129
exist already. The message content is a byte array, so you can encode
@@ -177,15 +179,15 @@ queue. Since it will push us messages asynchronously, we provide a
177179
callback that will be executed when RabbitMQ pushes messages to
178180
our consumer. This is what `subscribe` does.
179181

180-
(with-connection ("amqp://")
181-
(with-channel ()
182-
(let ((q (queue.declare "hello" :auto-delete t)))
183-
(format t " [*] Waiting for messages in queue 'hello'. To exit type (exit)~%")
184-
(subscribe q (lambda (message)
185-
(let ((body (babel:octets-to-string (message-body message))))
186-
(format t " [x] Received ~a~%" body)))
187-
:type :sync)
188-
(consume :one-shot t))))
182+
(with-connection ("amqp://")
183+
(with-channel ()
184+
(let ((q (queue.declare "hello" :auto-delete t)))
185+
(format t " [*] Waiting for messages in queue 'hello'. To exit type (exit)~%")
186+
(subscribe q (lambda (message)
187+
(let ((body (babel:octets-to-string (message-body message))))
188+
(format t " [x] Received ~a~%" body)))
189+
:type :sync)
190+
(consume :one-shot t))))
189191

190192
`subscribe` is used with the `:type :sync` option that makes it
191193
block the calling thread (we don't want the script to finish running immediately!).
@@ -210,4 +212,4 @@ If you want to check on the queue, try using `rabbitmqctl list_queues`.
210212

211213
Hello World!
212214

213-
Time to move on to [part 2](tutorial-two-cl.md) and build a simple _work queue_.
215+
Time to move on to [part 2](tutorial-two-cl.html) and build a simple _work queue_.

_includes/cl-bunny/tutorials/tutorial-six-cl.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1414
See the License for the specific language governing permissions and
1515
limitations under the License.
1616
-->
17+
1718
# RabbitMQ tutorial - Remote procedure call (RPC)
1819

1920
## Remote procedure call (RPC)
21+
2022
### (using [cl-bunny](http://cl-rabbit.io/cl-bunny))
2123

22-
In the [second tutorial](tutorial-two-cl.md) we learned how to
24+
In the [second tutorial](tutorial-two-cl.html) we learned how to
2325
use _Work Queues_ to distribute time-consuming tasks among multiple
2426
workers.
2527

_includes/cl-bunny/tutorials/tutorial-three-cl.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1414
See the License for the specific language governing permissions and
1515
limitations under the License.
1616
-->
17+
1718
# RabbitMQ tutorial - Publish/Subscribe
1819

1920
## Publish/Subscribe
21+
2022
### (using [cl-bunny](http://cl-rabbit.io/cl-bunny))
2123

22-
In the [previous tutorial](tutorial-two-cl.md) we created a work
24+
In the [previous tutorial](tutorial-two-cl.html) we created a work
2325
queue. The assumption behind a work queue is that each task is
2426
delivered to exactly one worker. In this part we'll do something
2527
completely different -- we'll deliver a message to multiple
@@ -246,4 +248,4 @@ exchange `logs` goes to two queues with server-assigned names. And
246248
that's exactly what we intended.
247249

248250
To find out how to listen for a subset of messages, let's move on to
249-
[tutorial 4](tutorial-four-cl.md)
251+
[tutorial 4](tutorial-four-cl.html)

_includes/cl-bunny/tutorials/tutorial-two-cl.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,16 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1414
See the License for the specific language governing permissions and
1515
limitations under the License.
1616
-->
17+
1718
# RabbitMQ tutorial - Work Queues
1819

1920
## Work Queues
21+
2022
### (using [cl-bunny](http://cl-rabbit.io/cl-bunny))
2123

2224
![](http://i.imgur.com/Tf7ltsH.png)
2325

24-
In the [first tutorial](tutorial-one-cl.md) we
26+
In the [first tutorial](tutorial-one-cl.html) we
2527
wrote programs to send and receive messages from a named queue. In this
2628
one we'll create a _Work Queue_ that will be used to distribute
2729
time-consuming tasks among multiple workers.
@@ -323,5 +325,5 @@ RabbitMQ is restarted.
323325
For more information on functions and message properties, you can browse the
324326
[cl-bunny reference](http://cl-rabbit.io/cl-bunny/reference).
325327

326-
Now we can move on to [tutorial 3](tutorial-three-cl.md) and learn how
328+
Now we can move on to [tutorial 3](tutorial-three-cl.html) and learn how
327329
to deliver the same message to many consumers.

_layouts/default.html

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
<link rel="stylesheet" type="text/css" href="/style/style.css">
1111

1212

13-
<link href='https://yastatic.net/highlightjs/8.2/styles/github.min.css' rel='stylesheet'>
13+
<!-- <link href='https://yastatic.net/highlightjs/8.2/styles/github.min.css' rel='stylesheet'> -->
14+
<link href='https://yastatic.net/highlightjs/8.2/styles/googlecode.min.css' rel='stylesheet'>
1415
<script src='https://yastatic.net/highlightjs/8.2/highlight.min.js'></script>
1516
<script src='https://yastatic.net/highlightjs/8.2/languages/lisp.min.js'></script>
1617

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
(ql:quickload :cl-bunny.examples)
2+
3+
(in-package :cl-bunny.examples)
4+
5+
(with-connection ("amqp://")
6+
(with-channel ()
7+
(let* ((args (cdr sb-ext:*posix-argv*))
8+
(severity (if (car args) (car args) "info"))
9+
(msg (format nil "~{~a ~}" (cdr args)))
10+
(x (amqp-exchange-declare "direct_logs" :type "direct")))
11+
(publish x msg :routing-key severity)
12+
(format t " [x] Sent '~a'" msg)
13+
(sleep 1))))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
(ql:quickload :cl-bunny.examples)
2+
3+
(in-package :cl-bunny.examples)
4+
5+
(with-connection ("amqp://")
6+
(with-channel ()
7+
(let* ((args (cdr sb-ext:*posix-argv*))
8+
(severity (if (car args) (car args) "anonimous.info"))
9+
(msg (format nil "~{~a ~}" (cdr args)))
10+
(x (amqp-exchange-declare "topic_logs" :type "topic")))
11+
(publish x msg :routing-key severity)
12+
(format t " [x] Sent ~a:'~a'" severity msg)
13+
(sleep 1))))
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
(ql:quickload :cl-bunny.examples)
2+
3+
(in-package :cl-bunny.examples)
4+
5+
(with-connection ("amqp://")
6+
(with-channel ()
7+
(let ((msg (format nil "~{~a ~}" (cdr sb-ext:*posix-argv*)))
8+
(x (amqp-exchange-declare "logs" :type "fanout")))
9+
(publish x msg)
10+
(format t " [x] Sent '~a'~%" msg)
11+
(sleep 1))))

cl-bunny/tutorials/code/new_task.lisp

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
(ql:quickload :cl-bunny.examples)
2+
3+
(in-package :cl-bunny.examples)
4+
5+
(with-connection ("amqp://")
6+
(with-channel ()
7+
(let ((x (default-exchange))
8+
(msg (format nil "~{~a ~}" (cdr sb-ext:*posix-argv*))))
9+
(publish x msg :routing-key "task_queue"
10+
:properties `((:persistent . ,t)))
11+
(format t " [x] Sent '~a'~%" msg)
12+
(sleep 1))))

cl-bunny/tutorials/code/receive.lisp

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
(ql:quickload :cl-bunny.examples)
2+
3+
(in-package :cl-bunny.examples)
4+
5+
(with-connection ("amqp://")
6+
(with-channel ()
7+
(let ((q (queue.declare "hello" :auto-delete t)))
8+
(format t " [*] Waiting for messages in queue 'hello'. To exit type (exit)~%")
9+
(subscribe q (lambda (message)
10+
(let ((body (babel:octets-to-string (message-body message))))
11+
(format t " [x] Received ~a~%" body)))
12+
:type :sync)
13+
(consume :one-shot t))))
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
(ql:quickload :cl-bunny.examples)
2+
3+
(in-package :cl-bunny.examples)
4+
5+
(with-connection ("amqp://")
6+
(with-channel ()
7+
(let ((n 1)
8+
(x (amqp-exchange-declare "logs" :type "fanout"))
9+
(q (queue.declare "" :auto-delete t)))
10+
(amqp-queue-bind q :exchange x)
11+
(format t " [*] Waiting for logs. To exit type (exit)~%")
12+
(subscribe q (lambda (message)
13+
(let ((body (babel:octets-to-string (message-body message))))
14+
(format t " [x] #~a~%" body)))
15+
:type :sync)
16+
(consume))))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
(ql:quickload :cl-bunny.examples)
2+
3+
(in-package :cl-bunny.examples)
4+
5+
(let ((args (cdr sb-ext:*posix-argv*)))
6+
(if args
7+
(with-connection ("amqp://")
8+
(with-channel ()
9+
(let ((args (cdr sb-ext:*posix-argv*))
10+
(q (queue.declare "" :auto-delete t)))
11+
(loop for severity in args do
12+
(amqp-queue-bind q :exchange "direct_logs" :routing-key severity))
13+
(format t " [*] Waiting for logs. To exit type (exit)~%")
14+
(subscribe q (lambda (message)
15+
(let ((body (babel:octets-to-string (message-body message))))
16+
(format t " [x] #~a~%" body)))
17+
:type :sync)
18+
(consume))))
19+
(error "Usage: #{$0} [info] [warning] [error]")))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
(ql:quickload :cl-bunny.examples)
2+
3+
(in-package :cl-bunny.examples)
4+
5+
(let ((args (cdr sb-ext:*posix-argv*)))
6+
(if args
7+
(with-connection ("amqp://")
8+
(with-channel ()
9+
(let ((args (cdr sb-ext:*posix-argv*))
10+
(q (queue.declare "" :auto-delete t)))
11+
(loop for severity in args do
12+
(amqp-queue-bind q :exchange "topic_logs" :routing-key severity))
13+
(format t " [*] Waiting for logs. To exit type (exit)~%")
14+
(subscribe q (lambda (message)
15+
(let ((body (babel:octets-to-string (message-body message))))
16+
(format t " [x] #~a~%" body)))
17+
:type :sync)
18+
(consume))))
19+
(error "Usage: #{$0} [binding key]")))
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
(ql:quickload :cl-bunny.examples)
2+
(ql:quickload :nibbles)
3+
4+
(in-package :cl-bunny.examples)
5+
6+
(defun int32-to-octet(val)
7+
(declare (type (signed-byte 32) val)
8+
(optimize (sb-c::insert-debug-catch 0)
9+
(speed 3)
10+
(compilation-speed 0)
11+
(safety 0)))
12+
(let ((array (make-array 4 :element-type '(unsigned-byte 8))))
13+
(setf (aref array 0) (ldb (byte 8 0) val))
14+
(setf (aref array 1) (ldb (byte 8 8) val))
15+
(setf (aref array 2) (ldb (byte 8 16) val))
16+
(setf (aref array 3) (ldb (byte 8 24) val))
17+
array))
18+
19+
(defun start-client (n)
20+
(with-connection ("amqp://")
21+
(with-channel ()
22+
(let ((x (default-exchange))
23+
(server-queue "rpc_queue")
24+
(reply-queue (queue.declare "" :auto-delete t))
25+
(lock (bt:make-lock))
26+
(condition (bt:make-condition-variable))
27+
(result nil))
28+
(format t " [x] Requesting fib(~a)~%" n)
29+
(bt:with-lock-held (lock)
30+
(subscribe reply-queue (lambda (message)
31+
(bt:with-lock-held (lock)
32+
(setf result (nibbles:sb32ref/le (coerce (message-body message) '(vector (unsigned-byte 8))) 0))
33+
(bt:condition-notify condition))))
34+
(publish x
35+
(int32-to-octet n)
36+
:routing-key server-queue
37+
:properties `((:correlation-id . ,(format nil "~a~a~a" (random 100) (random 100) (random 100)))
38+
(:reply-to . ,reply-queue)))
39+
(bt:condition-wait condition lock)
40+
(format t " [.] Got ~a~%" result)
41+
result)))))
42+
43+
(start-client 0)
44+
(start-client 1)
45+
(start-client 2)
46+
(start-client 3)
47+
(start-client 4)
48+
(start-client 5)
49+

0 commit comments

Comments
 (0)