Skip to content

Commit b605415

Browse files
Merge pull request #88 from cl-rabbit/cl-bunny
Common Lisp tutorials
2 parents bed96f8 + cba1f15 commit b605415

14 files changed

+363
-1
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ venv/*
1717
ruby*/rubygems*
1818

1919
java*/.idea/workspace.xml
20-
java*/.idea/encodings.xml
20+
java*/.idea/encodings.xml
21+
*~

common-lisp/README.md

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Common Lisp code for RabbitMQ tutorials
2+
3+
Here you can find Common Lisp code examples from
4+
[RabbitMQ tutorials](http://cl-rabbit.io/cl-bunny/tutorials/).
5+
6+
## Requirements
7+
8+
To run this code you need [Cl-Bunny](http://cl-rabbit.io/cl-bunny).
9+
10+
You can install it via Quicklisp:
11+
12+
(ql:quickload :cl-bunny)
13+
14+
Note: Cl-Bunny developed and tested using x64 sbcl on GNU/Linux
15+
16+
All our examples are in fact executable sbcl scripts. You can run them from command line
17+
18+
## Code
19+
20+
[Tutorial one: "Hello World!"](http://cl-rabbit.io/cl-bunny/tutorials/tutorial-one-cl.html):
21+
22+
./send.lisp
23+
./receive.lisp
24+
25+
[Tutorial two: Work Queues](http://cl-rabbit.io/cl-bunny/tutorials/tutorial-two-cl.html):
26+
27+
./new-task.lisp
28+
./worker.lisp
29+
30+
[Tutorial three: Publish/Subscribe](http://cl-rabbit.io/cl-bunny/tutorials/tutorial-three-cl.html)
31+
32+
./receive-logs.lisp
33+
./emit-log.lisp
34+
35+
[Tutorial four: Routing](http://cl-rabbit.io/cl-bunny/tutorials/tutorial-four-cl.html)
36+
37+
./receive-logs-direct.lisp
38+
./emit-log-direct.lisp
39+
40+
[Tutorial five: Topics](http://cl-rabbit.io/cl-bunny/tutorials/tutorial-five-cl.html)
41+
42+
./receive-logs-topic.lisp
43+
./emit-log-topic.lisp
44+
45+
[Tutorial six: RPC](http://cl-rabbit.io/cl-bunny/tutorials/tutorial-six-cl.html)
46+
47+
./rpc-server.lisp
48+
./rpc-client.lisp
49+
50+
To learn more, visit [Cl-Bunny documentation](http://cl-rabbit.io/cl-bunny) site.

common-lisp/emit-log-direct.lisp

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/sh
2+
3+
sbcl --noinform --noprint $@ <<EOF
4+
5+
(ql:quickload :cl-bunny.examples)
6+
7+
(in-package :cl-bunny.examples)
8+
9+
(with-connection ()
10+
(with-channel ()
11+
(let* ((args (rest sb-ext:*posix-argv*))
12+
(severity (or (first args) "info"))
13+
(msg (format nil "~{~a~^ ~}" (rest args)))
14+
(x (exchange.direct "direct_logs")))
15+
(publish x msg :routing-key severity)
16+
(format t " [x] Sent '~a'~%" msg))))
17+
18+
EOF

common-lisp/emit-log-topic.lisp

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/sh
2+
3+
sbcl --noinform --noprint $@ <<EOF
4+
5+
(ql:quickload :cl-bunny.examples)
6+
7+
(in-package :cl-bunny.examples)
8+
9+
(with-connection ()
10+
(with-channel ()
11+
(let* ((args (rest sb-ext:*posix-argv*))
12+
(severity (or (first args) "info"))
13+
(msg (format nil "~{~a~^ ~}" (rest args)))
14+
(x (exchange.topic "topic_logs")))
15+
(publish x msg :routing-key severity)
16+
(format t " [x] Sent '~a'~%" msg))))
17+
18+
EOF

common-lisp/emit-log.lisp

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/bin/sh
2+
3+
sbcl --noinform --noprint $@ <<EOF
4+
5+
(ql:quickload :cl-bunny.examples)
6+
7+
(in-package :cl-bunny.examples)
8+
9+
(with-connection ("amqp://")
10+
(with-channel ()
11+
(let ((msg (format nil "~{~a~^ ~}" (cdr sb-ext:*posix-argv*)))
12+
(x (exchange.fanout "logs")))
13+
(publish x msg)
14+
(format t " [x] Sent '~a'~%" msg))))
15+
16+
EOF

common-lisp/new-task.lisp

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/bin/sh
2+
3+
sbcl --noinform --noprint $@ <<EOF
4+
5+
(ql:quickload :cl-bunny.examples)
6+
7+
(in-package :cl-bunny.examples)
8+
9+
(with-connection ()
10+
(with-channel ()
11+
(let ((x (exchange.default))
12+
(msg (format nil "~{~a~^ ~}" (cdr sb-ext:*posix-argv*))))
13+
(publish x msg :routing-key "task_queue"
14+
:properties '(:persistent t))
15+
(format t " [x] Sent '~a'~%" msg))))
16+
17+
EOF

common-lisp/receive-logs-direct.lisp

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/bin/sh
2+
3+
sbcl --noinform --noprint $@ <<EOF
4+
5+
(ql:quickload :cl-bunny.examples)
6+
7+
(in-package :cl-bunny.examples)
8+
9+
(if-let ((args (rest sb-ext:*posix-argv*)))
10+
(with-connection ()
11+
(with-channel ()
12+
(let ((q (queue.declare :auto-delete t))
13+
(x (exchange.direct "direct_logs")))
14+
(loop for severity in args do
15+
(queue.bind q x :routing-key severity))
16+
(format t " [*] Waiting for logs. To exit press CTRL+C~%")
17+
(handler-case
18+
(progn
19+
(subscribe q (lambda (message)
20+
(format t " [x] #~a:~a~%" (message-routing-key message) (message-body-string message)))
21+
:type :sync)
22+
(consume))
23+
(sb-sys:interactive-interrupt ()
24+
(sb-ext:exit))))))
25+
(format t "Usage: $0 [info] [warning] [error]~%"))
26+
27+
EOF

common-lisp/receive-logs-topic.lisp

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/bin/sh
2+
3+
sbcl --noinform --noprint $@ <<EOF
4+
5+
(ql:quickload :cl-bunny.examples)
6+
7+
(in-package :cl-bunny.examples)
8+
9+
(if-let ((args (rest sb-ext:*posix-argv*)))
10+
(with-connection ()
11+
(with-channel ()
12+
(let ((q (queue.declare :auto-delete t))
13+
(x (exchange.topic "topic_logs")))
14+
(loop for severity in args do
15+
(queue.bind q x :routing-key severity))
16+
(format t " [*] Waiting for logs. To exit press CTRL+C~%")
17+
(handler-case
18+
(progn
19+
(subscribe q (lambda (message)
20+
(format t " [x] #~a:~a~%" (message-routing-key message) (message-body-string message)))
21+
:type :sync)
22+
(consume))
23+
(sb-sys:interactive-interrupt ()
24+
(sb-ext:exit))))))
25+
(format t "Usage: $0 [binding key]~%"))
26+
27+
EOF

common-lisp/receive-logs.lisp

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/bin/sh
2+
3+
sbcl --noinform --noprint <<EOF
4+
5+
(ql:quickload :cl-bunny.examples)
6+
7+
(in-package :cl-bunny.examples)
8+
9+
(with-connection ("amqp://")
10+
(with-channel ()
11+
(let ((q (queue.declare-temp)))
12+
(queue.bind q "logs")
13+
(format t " [*] Waiting for logs. To exit press CTRL+C~%")
14+
(handler-case
15+
(progn
16+
(subscribe q (lambda (message)
17+
(format t " [x] #~a~%" (message-body-string message)))
18+
:type :sync)
19+
(consume))
20+
(sb-sys:interactive-interrupt ()
21+
(sb-ext:exit))))))
22+
23+
EOF

common-lisp/receive.lisp

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/bin/sh
2+
3+
sbcl --noinform --noprint <<EOF
4+
5+
(ql:quickload :cl-bunny.examples)
6+
7+
(in-package :cl-bunny.examples)
8+
9+
(with-connection ("amqp://")
10+
(with-channel ()
11+
(let ((q (queue.declare :name "hello")))
12+
(format t " [*] Waiting for messages in queue 'hello'. To exit press CTRL+C~%")
13+
(handler-case
14+
(progn
15+
(subscribe q (lambda (message)
16+
(format t " [x] Received ~a~%" (message-body-string message)))
17+
:type :sync
18+
:no-ack t)
19+
(consume))
20+
(sb-sys:interactive-interrupt ()
21+
(sb-ext:exit))))))
22+
23+
EOF

common-lisp/rpc-client.lisp

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/bin/sh
2+
3+
sbcl --noinform --noprint <<EOF
4+
5+
(ql:quickload :cl-bunny.examples)
6+
(ql:quickload :nibbles)
7+
8+
(in-package :cl-bunny.examples)
9+
10+
(defun int64-to-octets(val)
11+
(let ((obuffer (fast-io:make-output-buffer)))
12+
(fast-io:write64-be val obuffer)
13+
(fast-io:finish-output-buffer obuffer)))
14+
15+
(defun start-client (n)
16+
(with-connection ("amqp://")
17+
(with-channel ()
18+
(let ((x (exchange.default))
19+
(server-queue "rpc_queue")
20+
(reply-queue (queue.declare :auto-delete t))
21+
(lock (bt:make-lock))
22+
(condition (bt:make-condition-variable))
23+
(result nil))
24+
(format t " [x] Requesting fib(~a)~%" n)
25+
(bt:with-lock-held (lock)
26+
(subscribe reply-queue (lambda (message)
27+
(bt:with-lock-held (lock)
28+
(setf result (nibbles:sb64ref/be (message-body message) 0))
29+
(bt:condition-notify condition))))
30+
(publish x
31+
(int64-to-octets n)
32+
:routing-key server-queue
33+
:properties (list :correlation-id (format nil "~a~a~a" (random 100) (random 100) (random 100))
34+
:reply-to reply-queue))
35+
(bt:condition-wait condition lock)
36+
(format t " [.] Got ~a~%" result)
37+
result)))))
38+
39+
(start-client 0)
40+
(start-client 1)
41+
(start-client 22)
42+
(start-client 33)
43+
(start-client 44)
44+
(start-client 55)
45+
46+
EOF

common-lisp/rpc-server.lisp

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/bin/sh
2+
3+
sbcl --noinform --noprint <<EOF
4+
5+
(ql:quickload :cl-bunny.examples)
6+
(ql:quickload :nibbles)
7+
8+
(in-package :cl-bunny.examples)
9+
10+
(defun int64-to-octets(val)
11+
(let ((obuffer (fast-io:make-output-buffer)))
12+
(fast-io:write64-be val obuffer)
13+
(fast-io:finish-output-buffer obuffer)))
14+
15+
;; http://www.cliki.net/fibonacci
16+
(defun fibonacci (n)
17+
"Successive squaring method from SICP"
18+
(check-type n (integer 0 *))
19+
(labels ((fib-aux (a b p q count)
20+
(cond ((= count 0) b)
21+
((evenp count)
22+
(fib-aux a
23+
b
24+
(+ (* p p) (* q q))
25+
(+ (* q q) (* 2 p q))
26+
(/ count 2)))
27+
(t (fib-aux (+ (* b q) (* a q) (* a p))
28+
(+ (* b p) (* a q))
29+
p
30+
q
31+
(- count 1))))))
32+
(fib-aux 1 0 0 1 n)))
33+
34+
(with-connection ()
35+
(with-channel ()
36+
(let ((x (exchange.default))
37+
(q (queue.declare :name "rpc_queue" :auto-delete t)))
38+
(format t " [x] Awaiting RPC requests~%")
39+
(handler-case
40+
(progn
41+
(subscribe q (lambda (message)
42+
(let* ((n (nibbles:sb64ref/be (message-body message) 0))
43+
(r (fibonacci n)))
44+
(format t " [.] fib(~a)~%" r)
45+
(publish x
46+
(int64-to-octets r)
47+
:routing-key (message-reply-to message)
48+
:properties (list :correlation-id (message-correlation-id message)))))
49+
:type :sync)
50+
(consume))
51+
(sb-sys:interactive-interrupt ()
52+
(sb-ext:exit))))))
53+
54+
EOF

common-lisp/send.lisp

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/bin/sh
2+
3+
sbcl --noinform --noprint <<EOF
4+
5+
(ql:quickload :cl-bunny.examples)
6+
7+
(in-package :cl-bunny.examples)
8+
9+
(with-connection ("amqp://")
10+
(with-channel ()
11+
(publish (exchange.default) "Hello world!" :routing-key "hello")
12+
(format t " [x] Sent 'Hello World!'~%")))
13+
14+
EOF

common-lisp/worker.lisp

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/bin/sh
2+
3+
sbcl --noinform --noprint <<EOF
4+
5+
(ql:quickload :cl-bunny.examples)
6+
7+
(in-package :cl-bunny.examples)
8+
9+
(with-connection ()
10+
(with-channel ()
11+
(let ((q (queue.declare :name "task_queue" :durable t)))
12+
(format t " [*] Waiting for messages in queue 'task_queue'. To exit press CTRL+C~%")
13+
(qos :prefetch-count 1)
14+
(handler-case
15+
(progn
16+
(subscribe q (lambda (message)
17+
(let ((body (message-body-string message)))
18+
(format t " [x] Received '~a'~%" body)
19+
;; imitate some work
20+
(sleep (count #\. body))
21+
(message.ack message)
22+
(format t " [x] Done~%")))
23+
:type :sync)
24+
(consume))
25+
(sb-sys:interactive-interrupt ()
26+
(sb-ext:exit))))))
27+
28+
EOF

0 commit comments

Comments
 (0)