Skip to content

Commit 7cf6df5

Browse files
authored
Merge pull request #34 from thread/upstream-1.0
Upstream 3.0
2 parents 1a0284a + 21b0b6a commit 7cf6df5

28 files changed

+617
-387
lines changed

.circleci/config.yml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
version: 2.1
2+
3+
jobs:
4+
build-test:
5+
docker:
6+
- image: circleci/python:3.5.5
7+
steps:
8+
- checkout
9+
- run:
10+
name: Install Poetry
11+
command: |
12+
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python
13+
- restore_cache:
14+
keys:
15+
- deps-{{ checksum "poetry.lock" }}
16+
- run:
17+
name: Install Dependencies
18+
command: |
19+
source $HOME/.poetry/env
20+
poetry install
21+
- save_cache:
22+
key: deps-{{ checksum "poetry.lock" }}
23+
paths:
24+
- /home/circleci/.cache/pypoetry/virtualenvs
25+
26+
- run:
27+
name: Run Tests
28+
command: |
29+
source $HOME/.poetry/env
30+
poetry run ./runtests
31+
32+
deploy:
33+
docker:
34+
- image: circleci/python:3.5.5
35+
steps:
36+
- checkout
37+
- run:
38+
name: Push to PyPI
39+
command: |
40+
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python
41+
source $HOME/.poetry/env
42+
poetry publish \
43+
--build \
44+
--username "${PYPI_USERNAME}" \
45+
--password "${PYPI_PASSWORD}" \
46+
--no-interaction
47+
48+
workflows:
49+
version: 2.1
50+
51+
build-test:
52+
jobs:
53+
- build-test
54+
55+
build-test-deploy:
56+
jobs:
57+
- build-test:
58+
filters:
59+
tags:
60+
only: /v[0-9]+(\.[0-9]+)*/
61+
branches:
62+
ignore: /.*/
63+
64+
- deploy:
65+
context: thread-pypi
66+
requires:
67+
- build-test
68+
filters:
69+
tags:
70+
only: /v[0-9]+(\.[0-9]+)*/
71+
branches:
72+
ignore: /.*/

.gitignore

Lines changed: 129 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,129 @@
1-
*.pyc
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# C extensions
7+
*.so
8+
9+
# Distribution / packaging
10+
.Python
11+
build/
12+
develop-eggs/
13+
dist/
14+
downloads/
15+
eggs/
16+
.eggs/
17+
lib/
18+
lib64/
19+
parts/
20+
sdist/
21+
var/
22+
wheels/
23+
pip-wheel-metadata/
24+
share/python-wheels/
25+
*.egg-info/
26+
.installed.cfg
27+
*.egg
28+
MANIFEST
29+
30+
# PyInstaller
31+
# Usually these files are written by a python script from a template
32+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
33+
*.manifest
34+
*.spec
35+
36+
# Installer logs
37+
pip-log.txt
38+
pip-delete-this-directory.txt
39+
40+
# Unit test / coverage reports
41+
htmlcov/
42+
.tox/
43+
.nox/
44+
.coverage
45+
.coverage.*
46+
.cache
47+
nosetests.xml
48+
coverage.xml
49+
*.cover
50+
*.py,cover
51+
.hypothesis/
52+
.pytest_cache/
53+
54+
# Translations
55+
*.mo
56+
*.pot
57+
58+
# Django stuff:
59+
*.log
60+
local_settings.py
61+
db.sqlite3
62+
db.sqlite3-journal
63+
64+
# Flask stuff:
65+
instance/
66+
.webassets-cache
67+
68+
# Scrapy stuff:
69+
.scrapy
70+
71+
# Sphinx documentation
72+
docs/_build/
73+
74+
# PyBuilder
75+
target/
76+
77+
# Jupyter Notebook
78+
.ipynb_checkpoints
79+
80+
# IPython
81+
profile_default/
82+
ipython_config.py
83+
84+
# pyenv
85+
.python-version
86+
87+
# pipenv
88+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
90+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
91+
# install all needed dependencies.
92+
#Pipfile.lock
93+
94+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
95+
__pypackages__/
96+
97+
# Celery stuff
98+
celerybeat-schedule
99+
celerybeat.pid
100+
101+
# SageMath parsed files
102+
*.sage.py
103+
104+
# Environments
105+
.env
106+
.venv
107+
env/
108+
venv/
109+
ENV/
110+
env.bak/
111+
venv.bak/
112+
113+
# Spyder project settings
114+
.spyderproject
115+
.spyproject
116+
117+
# Rope project settings
118+
.ropeproject
119+
120+
# mkdocs documentation
121+
/site
122+
123+
# mypy
124+
.mypy_cache/
125+
.dmypy.json
126+
dmypy.json
127+
128+
# Pyre type checker
129+
.pyre/

README.md

Lines changed: 54 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
11
# Django Lightweight Queue
22

3-
DLQ is a lightweight & modular queue and cron system for Django.
3+
DLQ is a lightweight & modular queue and cron system for Django. It powers
4+
millions of production jobs every day at Thread.
5+
6+
## Installation
7+
8+
```shell
9+
pip install django-lightweight-queue[redis]
10+
```
11+
12+
Currently the only production-ready backends are redis-based, so the `redis`
13+
extra is essentially required. Additional non-redis backed production-ready
14+
backends are great candidates for community contributions.
415

516
## Basic Usage
617

7-
``` python
18+
```python
819
import time
920
from django_lightweight_queue import task
1021

@@ -25,42 +36,50 @@ for more details.
2536
All automatically picked up configuration options begin with `LIGHTWEIGHT_QUEUE_`
2637
and can be found in `app_settings.py`. They should be placed in the usual Django
2738
settings files, for example:
28-
``` python
39+
40+
```python
2941
LIGHTWEIGHT_QUEUE_BACKEND = 'django_lightweight_queue.backends.redis.RedisBackend'
3042
```
3143

32-
If desired, specific configuration overrides can be placed in a standalone python
33-
file which passed on the command line.
44+
#### Special Configuration
45+
46+
If desired, specific configuration overrides can be placed in a standalone
47+
python file which passed on the command line. This is useful for applying
48+
customisations for specific servers.
3449

3550
For example, given a `special.py` containing:
36-
``` python
51+
52+
```python
3753
LIGHTWEIGHT_QUEUE_REDIS_PORT = 12345
3854
```
55+
3956
and then running:
57+
4058
```
4159
$ python manage.py queue_runner --config=special.py
4260
```
61+
4362
will result in the runner to use the settings from the specified configuration
4463
file in preference to settings from the Django environment. Any settings not
4564
present in the specified file are inherited from the global configuration.
4665

47-
### Backends
66+
## Backends
4867

4968
There are four built-in backends:
50-
- Synchronous (the default): executes the task inline, without any actual queuing
51-
- Redis: executes tasks at-most-once using [Redis][redis] for storage of the
52-
enqueued tasks
53-
- Reliable Redis: executes tasks at-least-once using [Redis][redis] for storage
54-
of the enqueued tasks
55-
- Debug Web: a backend for use in debugging. Instead of running jobs it prints
56-
the url to a view that can be used to run a task in a transaction which will
57-
be rolled back. This is useful for debugging and optimising tasks.
69+
70+
| Backend | Type | Description |
71+
| -------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
72+
| Synchronous | Development | Executes the task inline, without any actual queuing. |
73+
| Redis | Production | Executes tasks at-most-once using [Redis][redis] for storage of the enqueued tasks. |
74+
| Reliable Redis | Production | Executes tasks at-least-once using [Redis][redis] for storage of the enqueued tasks (subject to Redis consistency). Does not guarantee the task _completes_. |
75+
| Debug Web | Debugging | Instead of running jobs it prints the url to a view that can be used to run a task in a transaction which will be rolled back. This is useful for debugging and optimising tasks. |
5876

5977
[redis]: https://redis.io/
6078

6179
## Running Workers
6280

6381
The queue runner is implemented as a Django management command:
82+
6483
```
6584
$ python manage.py queue_runner
6685
```
@@ -73,37 +92,47 @@ $ python manage.py queue_runner --machine 2 --of 4
7392
```
7493

7594
Alternatively a runner can be told explicitly which configuration to use:
95+
7696
```
7797
$ python manage.py queue_runner --exact-configuration --config=special.py
7898
```
99+
79100
When using `--exact-configuration` the number of workers is configured exactly,
80101
rather than being treated as the configuration for a pool. Additionally,
81102
exactly-configured runners will _not_ run any cron workers.
82103

83-
### Example
104+
#### Example
84105

85106
Given a Django configuration containing:
86-
``` python
107+
108+
```python
87109
LIGHTWEIGHT_QUEUE_WORKERS = {
88110
'queue1': 3,
89111
}
90112
```
113+
91114
and a `special.py` containing:
92-
``` python
115+
116+
```python
93117
LIGHTWEIGHT_QUEUE_WORKERS = {
94118
'queue1': 2,
95119
}
96120
```
121+
97122
Running any of:
123+
98124
```
99125
$ python manage.py queue_runner --machine 1 --of 3 # or,
100126
$ python manage.py queue_runner --machine 2 --of 3 # or,
101127
$ python manage.py queue_runner --machine 3 --of 3
102128
```
129+
103130
will result in one worker for `queue1` on the current machine, while:
131+
104132
```
105133
$ python manage.py queue_runner --exact-configuration --config=special.py
106134
```
135+
107136
will result in two workers on the current machine.
108137

109138
## Cron Tasks
@@ -115,7 +144,7 @@ To specify that a management command should be run at a given time, place a
115144
`cron.py` file in the root folder of the Django app which defines the command
116145
and which contains a `CONFIG` variable:
117146

118-
``` python
147+
```python
119148
CONFIG = (
120149
{
121150
'command': 'my_cron_command',
@@ -128,3 +157,9 @@ CONFIG = (
128157
},
129158
)
130159
```
160+
161+
## Maintainers
162+
163+
This repository was created by [Chris Lamb](https://github.com/lamby) at
164+
[Thread](https://www.thread.com/), and continues to be maintained by the [Thread
165+
engineering team](https://github.com/thread).

django_lightweight_queue/app_settings.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@
22

33
from . import constants
44

5+
56
def setting(suffix, default):
6-
attr_name = '%s%s' % (constants.SETTING_NAME_PREFIX, suffix)
7+
attr_name = '{}{}'.format(constants.SETTING_NAME_PREFIX, suffix)
78
return getattr(settings, attr_name, default)
89

10+
911
WORKERS = setting('WORKERS', {})
1012
BACKEND = setting('BACKEND', 'django_lightweight_queue.backends.synchronous.SynchronousBackend')
1113

14+
LOGGER_FACTORY = setting('LOGGER_FACTORY', 'logging.getLogger')
15+
1216
# Allow per-queue overrides of the backend.
1317
BACKEND_OVERRIDES = setting('BACKEND_OVERRIDES', {})
1418

@@ -33,8 +37,4 @@ def setting(suffix, default):
3337
# Workers will export metrics on this port, and ports following it
3438
PROMETHEUS_START_PORT = setting('PROMETHEUS_START_PORT', 9300)
3539

36-
ENABLE_FLUENT_LOGGING = setting('ENABLE_FLUENT_LOGGING', False)
37-
FLUENT_HOST = setting('FLUENT_HOST', '127.0.0.1')
38-
FLUENT_PORT = setting('FLUENT_PORT', 24224)
39-
4040
ATOMIC_JOBS = setting('ATOMIC_JOBS', True)

django_lightweight_queue/apps.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from .utils import load_all_tasks
44

5+
56
class DjangoLightweightQueueConfig(AppConfig):
67
name = 'django_lightweight_queue'
78

0 commit comments

Comments
 (0)