django-qstash 0.0.13__py3-none-any.whl → 0.0.15__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of django-qstash might be problematic. Click here for more details.
- django_qstash/__init__.py +1 -1
- django_qstash/client.py +19 -1
- django_qstash/settings.py +1 -1
- django_qstash/urls.py +9 -0
- {django_qstash-0.0.13.dist-info → django_qstash-0.0.15.dist-info}/METADATA +43 -11
- {django_qstash-0.0.13.dist-info → django_qstash-0.0.15.dist-info}/RECORD +8 -7
- {django_qstash-0.0.13.dist-info → django_qstash-0.0.15.dist-info}/WHEEL +0 -0
- {django_qstash-0.0.13.dist-info → django_qstash-0.0.15.dist-info}/top_level.txt +0 -0
django_qstash/__init__.py
CHANGED
django_qstash/client.py
CHANGED
|
@@ -1,7 +1,25 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import os
|
|
4
|
+
import warnings
|
|
5
|
+
|
|
3
6
|
from qstash import QStash
|
|
4
7
|
|
|
5
8
|
from django_qstash.settings import QSTASH_TOKEN
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
QSTASH_URL = os.environ.get("QSTASH_URL", None)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def init_qstash():
|
|
14
|
+
kwargs = {
|
|
15
|
+
"token": QSTASH_TOKEN,
|
|
16
|
+
}
|
|
17
|
+
if QSTASH_URL is not None:
|
|
18
|
+
warning_msg = f"\n\n\033[93mUsing {QSTASH_URL} as your QStash URL. \
|
|
19
|
+
\nThis configuration should only be used in development.\n\033[0m"
|
|
20
|
+
warnings.warn(warning_msg, RuntimeWarning, stacklevel=2)
|
|
21
|
+
kwargs["base_url"] = QSTASH_URL
|
|
22
|
+
return QStash(**kwargs)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
qstash_client = init_qstash()
|
django_qstash/settings.py
CHANGED
|
@@ -11,7 +11,7 @@ DJANGO_QSTASH_WEBHOOK_PATH = getattr(
|
|
|
11
11
|
)
|
|
12
12
|
if not QSTASH_TOKEN or not DJANGO_QSTASH_DOMAIN:
|
|
13
13
|
warnings.warn(
|
|
14
|
-
"QSTASH_TOKEN and DJANGO_QSTASH_DOMAIN should be set for QStash functionality",
|
|
14
|
+
"DJANGO_SETTINGS_MODULE (settings.py required) requires QSTASH_TOKEN and DJANGO_QSTASH_DOMAIN should be set for QStash functionality",
|
|
15
15
|
RuntimeWarning,
|
|
16
16
|
stacklevel=2,
|
|
17
17
|
)
|
django_qstash/urls.py
ADDED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: django-qstash
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.15
|
|
4
4
|
Summary: A drop-in replacement for Celery's shared_task with Upstash QStash.
|
|
5
5
|
Author-email: Justin Mitchel <justin@codingforentrepreneurs.com>
|
|
6
6
|
Project-URL: Changelog, https://github.com/jmitchel3/django-qstash
|
|
@@ -72,7 +72,7 @@ This allows us to:
|
|
|
72
72
|
- [Installation](#installation)
|
|
73
73
|
- [Using Pip](#using-pip)
|
|
74
74
|
- [Update Settings (`settings.py`)](#update-settings-settingspy)
|
|
75
|
-
- [Configure Webhook
|
|
75
|
+
- [Configure QStash Webhook Handler](#configure-qstash-webhook-handler)
|
|
76
76
|
- [Required Environment Variables](#required-environment-variables)
|
|
77
77
|
- [Sample Project](#sample-project)
|
|
78
78
|
- [Dependencies](#dependencies)
|
|
@@ -86,7 +86,9 @@ This allows us to:
|
|
|
86
86
|
- [Arguments Must be JSON-ready](#arguments-must-be-json-ready)
|
|
87
87
|
- [Example Task](#example-task)
|
|
88
88
|
- [Management Commands](#management-commands)
|
|
89
|
-
- [
|
|
89
|
+
- [Development](#development)
|
|
90
|
+
- [Development with a Public Domain](#development-with-a-public-domain)
|
|
91
|
+
- [Development with Docker Compose](#development-with-docker-compose)
|
|
90
92
|
- [Django Settings Configuration](#django-settings-configuration)
|
|
91
93
|
- [`DJANGO_QSTASH_DOMAIN`](#django_qstash_domain)
|
|
92
94
|
- [`DJANGO_QSTASH_WEBHOOK_PATH`](#django_qstash_webhook_path)
|
|
@@ -123,20 +125,27 @@ INSTALLED_APPS = [
|
|
|
123
125
|
- `django_qstash.results` (Optional): Store task results in Django DB
|
|
124
126
|
- `django_qstash.schedules` (Optional): Use QStash Schedules to run your `django_qstash` tasks. Out of the box support for _django_qstash_ `@stashed_task`. Schedule tasks using _cron_ (e.g. `0 0 * * *`) format which is required based on [QStash Schedules](https://upstash.com/docs/qstash/features/schedules). use [contrab.guru](https://crontab.guru/) for writing the cron format.
|
|
125
127
|
|
|
126
|
-
### Configure Webhook
|
|
128
|
+
### Configure QStash Webhook Handler
|
|
129
|
+
|
|
130
|
+
Set it and forget it. `django_qstash` will handle the webhook from qstash automatically for you.
|
|
127
131
|
|
|
128
132
|
In your `ROOT_URLCONF` (e.g. `urls.py`), add the following:
|
|
133
|
+
|
|
129
134
|
```python
|
|
130
|
-
from
|
|
135
|
+
from django.urls import include
|
|
131
136
|
|
|
132
137
|
urlpatterns = [
|
|
133
138
|
# ...
|
|
134
|
-
path("qstash/webhook/",
|
|
139
|
+
path("qstash/webhook/", include("django_qstash.urls")),
|
|
135
140
|
# ...
|
|
136
141
|
]
|
|
137
142
|
```
|
|
138
143
|
Be sure to use this path in your `DJANGO_QSTASH_WEBHOOK_PATH` environment variable.
|
|
139
144
|
|
|
145
|
+
|
|
146
|
+
The `django_qstash` webhook handler runs your `@shared_task` or `@stashed_task` functions via the `importlib` module. In other words, you should not need to modify the webhook handler.
|
|
147
|
+
|
|
148
|
+
|
|
140
149
|
### Required Environment Variables
|
|
141
150
|
|
|
142
151
|
Get your QStash token and signing keys from [Upstash](https://upstash.com/).
|
|
@@ -312,15 +321,33 @@ _Requires `django_qstash.schedules` installed._
|
|
|
312
321
|
- `python manage.py task_schedules --list` see all schedules relate to the `DJANGO_QSTASH_DOMAIN`
|
|
313
322
|
- `python manage.py task_schedules --sync` sync schedules based on the `DJANGO_QSTASH_DOMAIN` to store in the Django Admin.
|
|
314
323
|
|
|
315
|
-
##
|
|
324
|
+
## Development
|
|
325
|
+
|
|
326
|
+
During development, you have two options:
|
|
327
|
+
|
|
328
|
+
- Use Upstash.com with a publicly accessible domain (preferred)
|
|
329
|
+
- Use Docker Compose with [compose.dev.yaml](./compose.dev.yaml)
|
|
316
330
|
|
|
317
|
-
|
|
331
|
+
### Development with a Public Domain
|
|
332
|
+
|
|
333
|
+
The closer your development environment is to production the better. For that reason, using a publicly accessible domain is the preferred with to develop with _django-qstash_.
|
|
334
|
+
|
|
335
|
+
To get a public domain during development, we recommend any of the following:
|
|
318
336
|
|
|
319
337
|
- [Cloudflare Tunnels](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) with a domain name you control.
|
|
320
338
|
- [ngrok](https://ngrok.com/)
|
|
321
339
|
|
|
322
340
|
Once you have a domain name, you can configure the `DJANGO_QSTASH_DOMAIN` setting in your Django settings.
|
|
323
341
|
|
|
342
|
+
### Development with Docker Compose
|
|
343
|
+
Upstash covers how to run QStash during development on [this guide](https://upstash.com/docs/qstash/howto/local-development)
|
|
344
|
+
|
|
345
|
+
In our case we need to the following things:
|
|
346
|
+
|
|
347
|
+
- `docker compose -f compose.dev.yaml up`
|
|
348
|
+
- Add `QSTASH_URL=http://127.0.0.1:8585` to your `.env` file.
|
|
349
|
+
- Use the `QSTASH_TOKEN`, `QSTASH_CURRENT_SIGNING_KEY`, and `QSTASH_NEXT_SIGNING_KEY` the terminal output of Docker compose _or_ the values listed in [compose.dev.yaml](./compose.dev.yaml).
|
|
350
|
+
|
|
324
351
|
## Django Settings Configuration
|
|
325
352
|
|
|
326
353
|
Various options are available to configure django-qstash.
|
|
@@ -348,7 +375,7 @@ Various options are available to configure django-qstash.
|
|
|
348
375
|
|
|
349
376
|
### Example Django Settings
|
|
350
377
|
|
|
351
|
-
For a complete example, review [sample_project/settings.py](sample_project/settings.py) where [python-decouple](https://github.com/henriquebastos/python-decouple) is used to set the environment variables via the `.env` file or system environment variables (for production use).
|
|
378
|
+
For a complete example, review [sample_project/cfehome/settings.py](sample_project/cfehome/settings.py) where [python-decouple](https://github.com/henriquebastos/python-decouple) is used to set the environment variables via the `.env` file or system environment variables (for production use).
|
|
352
379
|
|
|
353
380
|
Using `os.environ`:
|
|
354
381
|
```python
|
|
@@ -364,10 +391,13 @@ CSRF_TRUSTED_ORIGINS = [os.environ.get("CSRF_TRUSTED_ORIGIN")]
|
|
|
364
391
|
###########################
|
|
365
392
|
# qstash-py settings
|
|
366
393
|
###########################
|
|
394
|
+
USE_LOCAL_QSTASH = str(os.environ.get("USE_LOCAL_QSTASH")) == "1"
|
|
367
395
|
QSTASH_TOKEN = os.environ.get("QSTASH_TOKEN")
|
|
368
396
|
QSTASH_CURRENT_SIGNING_KEY = os.environ.get("QSTASH_CURRENT_SIGNING_KEY")
|
|
369
397
|
QSTASH_NEXT_SIGNING_KEY = os.environ.get("QSTASH_NEXT_SIGNING_KEY")
|
|
370
|
-
|
|
398
|
+
if DJANGO_DEBUG and USE_LOCAL_QSTASH:
|
|
399
|
+
# connect to the docker compose qstash instance
|
|
400
|
+
os.environ["QSTASH_URL"] = "http://127.0.0.1:8585"
|
|
371
401
|
###########################
|
|
372
402
|
# django_qstash settings
|
|
373
403
|
###########################
|
|
@@ -504,7 +534,7 @@ I think serverless is the answer. Pay for what you use and scale to zero when yo
|
|
|
504
534
|
|
|
505
535
|
Django can be serverless and is pretty easy to do thanks to Docker and the countless hosting options and services out there. Celery cannot be serverless, at least yet.
|
|
506
536
|
|
|
507
|
-
Let's face it. Celery is a powerful tool to run async background tasks but it comes at a cost. It needs at least one server running 24/7. For best performance it needs 2 (one worker, one beat). It also needs Redis or RabbitMQ. Most background processes that are tied to web apps are not serverless; they have to "listen" for their next task.
|
|
537
|
+
Let's face it. Celery is a powerful tool to run async background tasks but it comes at a cost. It needs at least one server running 24/7. For best performance, it needs 2 (one worker, one beat). It also needs Redis or RabbitMQ. In a traditional Django setup with Celery and Redis, you need to run 3 to 4 different processes. Most background processes that are tied to web apps are not serverless; they have to "listen" for their next task.
|
|
508
538
|
|
|
509
539
|
To make Django truly scale-to-zero and serverless, we need to drop Celery.
|
|
510
540
|
|
|
@@ -518,4 +548,6 @@ It works by leveraging Upstash QStash to deliver messages about your tasks (e.g.
|
|
|
518
548
|
>
|
|
519
549
|
> Instead of calling an endpoint directly, QStash acts as a middleman between you and an API to guarantee delivery, perform automatic retries on failure, and more.
|
|
520
550
|
|
|
551
|
+
Compared to a traditional setup with Django, Celery, and Redis, which requires 3 to 4 processes, you only need to run a single process and can delegate the rest to Upstash QStash, significantly simplifying your infrastructure.
|
|
552
|
+
|
|
521
553
|
django-qstash has a webhook handler that converts a QStash message to run a specific `@shared_task` function (the one that called `.delay()` or `.apply_async()`). It's easy, it's cheap, it's effective, and best of all, it unlocks the scale-to-zero potential of Django as a serverless app.
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
django_qstash/__init__.py,sha256=
|
|
1
|
+
django_qstash/__init__.py,sha256=flZbUo7KZBqp_bfv_j-M02CRYxQovuoQF4OCVi9SF3o,188
|
|
2
2
|
django_qstash/callbacks.py,sha256=IQ-D8sPlSRuREZ1zwkRyd2GtxfmrJJh2x4jLd39rZCE,813
|
|
3
|
-
django_qstash/client.py,sha256=
|
|
3
|
+
django_qstash/client.py,sha256=9xO4iwR62PkEQhzC92yKRlzqEIF5Yi0HpYc88v_drsI,612
|
|
4
4
|
django_qstash/cron.py,sha256=13OzTMGXFgjNEXjs2Et20WGZYtW9lKlu79BjbRySnVc,716
|
|
5
5
|
django_qstash/exceptions.py,sha256=pH6kKRJFIVFkDHUJQ9yRWmtGdBBSXpNAwMSFuNzMgPw,392
|
|
6
6
|
django_qstash/handlers.py,sha256=TtYZ-Sr858ajISBpDuHIT7-qaVsoVfTE6vVFJ9-kpPE,5820
|
|
7
|
-
django_qstash/settings.py,sha256=
|
|
7
|
+
django_qstash/settings.py,sha256=s5xn4Rim8ip98q5Jiy1O6VVva2mUuAwUjbjo18fjqKA,579
|
|
8
|
+
django_qstash/urls.py,sha256=1dNblYOCIBdqSXbA1jSL9H0aiXN5gIDVwhfZeC4-DQw,172
|
|
8
9
|
django_qstash/utils.py,sha256=wrTU30cobO2di18BNEFtKD4ih2euf7eQNpg6p6TkQ1Y,1185
|
|
9
10
|
django_qstash/views.py,sha256=H32f_jGnlwOTO0YG9znNo2b-GRYZ8TM-Wt0T62SGdXM,639
|
|
10
11
|
django_qstash/app/__init__.py,sha256=kmoCVoESInzCZ_oGUiPVY4GsFQwBC07cqFJCyn9Loyk,240
|
|
@@ -45,7 +46,7 @@ django_qstash/schedules/migrations/0001_initial.py,sha256=66cA8xnJV3h7QgzCaOiv-N
|
|
|
45
46
|
django_qstash/schedules/migrations/0002_taskschedule_updated_at.py,sha256=6hZO0a9P2ZpOROkk7O5UXBhahghU0QfxZl4E-c3HKGw,459
|
|
46
47
|
django_qstash/schedules/migrations/0003_alter_taskschedule_cron.py,sha256=oBW_FcvosKsa0l_l3eVDRIZli5K1wQaN_DJjamVe23s,826
|
|
47
48
|
django_qstash/schedules/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
48
|
-
django_qstash-0.0.
|
|
49
|
-
django_qstash-0.0.
|
|
50
|
-
django_qstash-0.0.
|
|
51
|
-
django_qstash-0.0.
|
|
49
|
+
django_qstash-0.0.15.dist-info/METADATA,sha256=J8-nvVXGScbpWZfZdcQO-1n4O5pL6EiRdzJOUkczT8s,21209
|
|
50
|
+
django_qstash-0.0.15.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
51
|
+
django_qstash-0.0.15.dist-info/top_level.txt,sha256=AlV3WSK1A0ZvKuCLsINtIJhJW8zo7SEB-D3_RAjZ0hI,14
|
|
52
|
+
django_qstash-0.0.15.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|