-
Notifications
You must be signed in to change notification settings - Fork 13
/
README
231 lines (180 loc) · 7.98 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
django-sqs
==========
Author: Maciej Pasternacki <maciej@pasternacki.net>
Date: 2010-01-15 Fri
Maintainer: Adrien Lemaire <lemaire.adrien@gmail.com>
Integrate Amazon Simple Queue Service in your Django project
Table of Contents
=================
1 Setup
2 Receivers
2.1 Register using a decorator
2.2 Register manually
2.3 Example receiver
3 Receiving
4 Sending
4.1 Using decorated function
4.2 Manually
5 Custom message classes
5.1 ModelInstanceMessage class
6 Management
6.1 manage.py sqs_status
6.2 manage.py sqs_clear
6.3 manage.py sqs_wait
7 Views
8 FIXME
8.1 Sensible forking/threading or multiplexing instead of the fork hack?
8.2 Autoimporting receivers.py from apps
8.3 docstrings
8.4 Minimize polling
8.5 Custom exception to leave message in queue
1 Setup
~~~~~~~~
Boto library for accessing Amazon Web Services is required.
1. Add `django_sqs' to your Python path
2. Add `django_sqs' to INSTALLED_APPS setting
3. Set AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
4. Optionally set SQS_QUEUE_PREFIX to prefix your queues and avoid
clashes with other developers, production/staging env and so on.
SQS_QUEUE_PREFIX is required when DEBUG is true, and recommended
even in production mode.
5. Optionally set SQS_DEFAULT_VISIBILITY_TIMEOUT (default is 60 seconds)
6. Optionally set SQS_POLL_PERIOD (default is 10 seconds)
7. Optionally set AWS_REGION (default to "us-east-1")
2 Receivers
~~~~~~~~~~~~
Create receiver function that accepts one argument, which will be an
instance of `boto.sqs.message.Message' or its custom subclass.
Then, register it as queue receiver:
2.1 Register using a decorator
===============================
Decorate receiver function with:
django_sqs.receiver([queue_name=None, visibility_timeout=None, message_class=None, delete_on_start=False, close_database=False, suffixes=()])
Decorated function will become an instance of
`django_sqs.registered_queue.RegisteredQueue.ReceiverProxy' class.
Instance is callable - you may call it with an instance of
appropriate message class, or its constructor's keyword arguments,
and the message will be added to the queue. Instance provides also
attributes `direct' with original decorated function, and
`registered_queue' with appropriate
`django_sqs.registered_queue.RegisteredQueue' instance.
If `queue_name' is omitted or false, function's `__module__' and
`__name__' is used, with dots converted to double underscores.
The `suffixes' argument is a tuple of known queue name suffixes. If
an unknown suffix is used, a warning will be issued.
If `delete_on_start' is true, received message will be deleted from
queue right after it's been received, before receiver function is
called. If it is false (which is the default), it will be deleted
after receiver function has finished, when message has been fully
processed.
If `close_database' is true, all database connections will be
closed after processing each message to prevent pending unclosed
transactions.
Queue name suffixes can be used to split processing similar items
to multiple queues (e.g. use separate queue for big input items to
distribute load).
2.2 Register manually
======================
Alternatively, you can avoid decoration, and register a receiver
manually by calling:
django_sqs.register(queue_name, [fn=None, visibility_timeout=None, message_class=None, delete_on_start=False, suffixes=()])
If `fn' is None or not given, no handler is assigned: messages can
be sent, but won't be received.
Create function in modules that will be imported by default
(recommendation: use `receivers.py' and import them in `models.py',
autoimporting TBD).
2.3 Example receiver
=====================
@receiver("test")
def receive_message(msg):
print 'received:', msg.get_body()
3 Receiving
~~~~~~~~~~~~
python manage.py runreceiver [--message-limit=N] [--suffix=SUFFIX] [queue_name [queue_name [...]]]
If no `queue_name' parameters are given, receive from all configured
queues.
If more than one queue is registered, a new process is forked for
each queue.
For each message received on the queue, registered receiver function
is called with the message instance as argument. If receiver
function returns successfully, message is then deleted from queue.
If receiver message raises an exception, exception traceback is
logged using logging module, and message is deleted. If receiver
sees a restartable error and wants to keep message in queue, it
should raise `django_sqs.RestartLater' exception - this exception will
leave the message in queue.
Options:
`--message-limit=N': exit after receiving `N' messages
`--suffix=SUFFIX': Use queue name suffix
4 Sending
~~~~~~~~~~
4.1 Using decorated function
=============================
You can simply call function decorated with `@receiver' decorator,
providing a message instance or keyword arguments (like for `send'
function described below).
4.2 Manually
=============
To send a message manually, use following function:
django_sqs.send(queue_name, message=None, suffix=None, **kwargs)
`message' should be an instance of `message_class' configured with
`receiver' decorator or `register' function for the queue (or
`boto.sqs.message.Message').
When `message' is omitted or `None', new instance of queue's message
class will be instantiated using `**kwargs'. With default message
class, `boto.sqs.message.Message', we can simply provide body:
django_sqs.send("a_queue", body='Lorem ipsum dolor sit amet')
`suffix' is a queue name suffix to use.
5 Custom message classes
~~~~~~~~~~~~~~~~~~~~~~~~~
For sending other values than raw, non-unicode strings, any of
classes provided in `boto.sqs.message' or their subclasses may be
used. The module is well commented (much better than this one), so
go ahead and read the fine source!
5.1 ModelInstanceMessage class
===============================
The `django_sqs.message.ModelInstanceMessage' class is provided for
convenience. It encodes a single model instance, using Django's
ContentType framework (as app/model/primary key triple). It
accepts `instance' keyword parameter in constructor, and provides
`get_instance()' method.
There is no support for passing additional information except the
instance yet.
6 Management
~~~~~~~~~~~~~
6.1 manage.py sqs_status
=========================
Prints the (approximate) count of messages in the queue.
6.2 manage.py sqs_clear
========================
Clears all queues (by default), or queues named as arguments.
Prints number of messages deleted.
If queue receivers are running or were running recently, some
messages may be still locked and won't be deleted. Command may
need to be re-run.
6.3 manage.py sqs_wait
=======================
Waits until specified (or all) queues are empty.
7 Views
~~~~~~~~
A single view, `django_sqs.views.status', is provided for simple,
plain text queue status report (same as `manage.py sqs_status').
8 FIXME
~~~~~~~~
8.1 TODO Sensible forking/threading or multiplexing instead of the fork hack?
==============================================================================
8.2 TODO Autoimporting receivers.py from apps
==============================================
8.3 TODO docstrings
====================
8.4 TODO Minimize polling
==========================
Amazon charges for every call. Less polling, lower invoice. Some
exponential backoff + out-of-band signal (view?) to wake up a running
receiver process may be a good thing.
8.5 TODO Custom exception to leave message in queue
====================================================
Provide a custom exception class that won't be handled by receive
loop (i.e. no backtrace) that can be used by receiver function to
explicitly leave message in queue without printing backtrace and
alarming everyone.