django-qstash 0.0.14__tar.gz → 0.1.0__tar.gz
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-0.0.14 → django_qstash-0.1.0}/PKG-INFO +35 -10
- {django_qstash-0.0.14 → django_qstash-0.1.0}/README.md +34 -9
- {django_qstash-0.0.14 → django_qstash-0.1.0}/pyproject.toml +1 -1
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/__init__.py +1 -1
- django_qstash-0.1.0/src/django_qstash/client.py +25 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/settings.py +1 -1
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash.egg-info/PKG-INFO +35 -10
- django_qstash-0.0.14/src/django_qstash/client.py +0 -7
- {django_qstash-0.0.14 → django_qstash-0.1.0}/setup.cfg +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/app/__init__.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/app/base.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/app/decorators.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/callbacks.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/cron.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/db/__init__.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/db/models.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/discovery/__init__.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/discovery/fields.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/discovery/models.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/discovery/utils.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/discovery/validators.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/exceptions.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/handlers.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/management/__init__.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/management/commands/__init__.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/management/commands/available_tasks.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/management/commands/clear_stale_results.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/management/commands/task_schedules.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/results/__init__.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/results/admin.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/results/apps.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/results/migrations/0001_initial.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/results/migrations/0002_taskresult_function_path_alter_taskresult_status_and_more.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/results/migrations/__init__.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/results/models.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/results/services.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/results/tasks.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/schedules/__init__.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/schedules/admin.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/schedules/apps.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/schedules/exceptions.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/schedules/formatters.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/schedules/forms.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/schedules/migrations/0001_initial.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/schedules/migrations/0002_taskschedule_updated_at.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/schedules/migrations/0003_alter_taskschedule_cron.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/schedules/migrations/__init__.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/schedules/models.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/schedules/services.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/schedules/signals.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/schedules/validators.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/urls.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/utils.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/views.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash.egg-info/SOURCES.txt +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash.egg-info/dependency_links.txt +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash.egg-info/requires.txt +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash.egg-info/top_level.txt +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/tests/test_callbacks.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/tests/test_exceptions.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/tests/test_handlers.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/tests/test_results_models.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/tests/test_settings.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/tests/test_utils.py +0 -0
- {django_qstash-0.0.14 → django_qstash-0.1.0}/tests/test_views.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: django-qstash
|
|
3
|
-
Version: 0.0
|
|
3
|
+
Version: 0.1.0
|
|
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
|
|
@@ -27,11 +27,11 @@ Requires-Dist: django>=4.2
|
|
|
27
27
|
Requires-Dist: qstash>=2
|
|
28
28
|
Requires-Dist: requests>=2.30
|
|
29
29
|
|
|
30
|
-
> :warning: **BETA Software**: Working on being production-ready soon.
|
|
31
|
-
|
|
32
30
|
# django-qstash
|
|
33
31
|
|
|
34
|
-
|
|
32
|
+
Run background tasks with Django through webhooks and Upstash QStash.
|
|
33
|
+
|
|
34
|
+
_django-qstash_ is designed to be a drop-in replacement for Celery's `shared_task` or run alongside Celery.
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
## How it works
|
|
@@ -46,7 +46,7 @@ from django_qstash import shared_task
|
|
|
46
46
|
def my_task():
|
|
47
47
|
pass
|
|
48
48
|
```
|
|
49
|
-
> To use Celery
|
|
49
|
+
> To use django-qstash with Celery, you can use `@stashed_task` instead of `@shared_task` (more below).
|
|
50
50
|
|
|
51
51
|
To do this we need:
|
|
52
52
|
|
|
@@ -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)
|
|
@@ -319,15 +321,33 @@ _Requires `django_qstash.schedules` installed._
|
|
|
319
321
|
- `python manage.py task_schedules --list` see all schedules relate to the `DJANGO_QSTASH_DOMAIN`
|
|
320
322
|
- `python manage.py task_schedules --sync` sync schedules based on the `DJANGO_QSTASH_DOMAIN` to store in the Django Admin.
|
|
321
323
|
|
|
322
|
-
##
|
|
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)
|
|
330
|
+
|
|
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_.
|
|
323
334
|
|
|
324
|
-
|
|
335
|
+
To get a public domain during development, we recommend any of the following:
|
|
325
336
|
|
|
326
337
|
- [Cloudflare Tunnels](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) with a domain name you control.
|
|
327
338
|
- [ngrok](https://ngrok.com/)
|
|
328
339
|
|
|
329
340
|
Once you have a domain name, you can configure the `DJANGO_QSTASH_DOMAIN` setting in your Django settings.
|
|
330
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
|
+
|
|
331
351
|
## Django Settings Configuration
|
|
332
352
|
|
|
333
353
|
Various options are available to configure django-qstash.
|
|
@@ -371,10 +391,13 @@ CSRF_TRUSTED_ORIGINS = [os.environ.get("CSRF_TRUSTED_ORIGIN")]
|
|
|
371
391
|
###########################
|
|
372
392
|
# qstash-py settings
|
|
373
393
|
###########################
|
|
394
|
+
USE_LOCAL_QSTASH = str(os.environ.get("USE_LOCAL_QSTASH")) == "1"
|
|
374
395
|
QSTASH_TOKEN = os.environ.get("QSTASH_TOKEN")
|
|
375
396
|
QSTASH_CURRENT_SIGNING_KEY = os.environ.get("QSTASH_CURRENT_SIGNING_KEY")
|
|
376
397
|
QSTASH_NEXT_SIGNING_KEY = os.environ.get("QSTASH_NEXT_SIGNING_KEY")
|
|
377
|
-
|
|
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"
|
|
378
401
|
###########################
|
|
379
402
|
# django_qstash settings
|
|
380
403
|
###########################
|
|
@@ -511,7 +534,7 @@ I think serverless is the answer. Pay for what you use and scale to zero when yo
|
|
|
511
534
|
|
|
512
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.
|
|
513
536
|
|
|
514
|
-
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.
|
|
515
538
|
|
|
516
539
|
To make Django truly scale-to-zero and serverless, we need to drop Celery.
|
|
517
540
|
|
|
@@ -525,4 +548,6 @@ It works by leveraging Upstash QStash to deliver messages about your tasks (e.g.
|
|
|
525
548
|
>
|
|
526
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.
|
|
527
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
|
+
|
|
528
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,8 +1,8 @@
|
|
|
1
|
-
> :warning: **BETA Software**: Working on being production-ready soon.
|
|
2
|
-
|
|
3
1
|
# django-qstash
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
Run background tasks with Django through webhooks and Upstash QStash.
|
|
4
|
+
|
|
5
|
+
_django-qstash_ is designed to be a drop-in replacement for Celery's `shared_task` or run alongside Celery.
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
## How it works
|
|
@@ -17,7 +17,7 @@ from django_qstash import shared_task
|
|
|
17
17
|
def my_task():
|
|
18
18
|
pass
|
|
19
19
|
```
|
|
20
|
-
> To use Celery
|
|
20
|
+
> To use django-qstash with Celery, you can use `@stashed_task` instead of `@shared_task` (more below).
|
|
21
21
|
|
|
22
22
|
To do this we need:
|
|
23
23
|
|
|
@@ -57,7 +57,9 @@ This allows us to:
|
|
|
57
57
|
- [Arguments Must be JSON-ready](#arguments-must-be-json-ready)
|
|
58
58
|
- [Example Task](#example-task)
|
|
59
59
|
- [Management Commands](#management-commands)
|
|
60
|
-
- [
|
|
60
|
+
- [Development](#development)
|
|
61
|
+
- [Development with a Public Domain](#development-with-a-public-domain)
|
|
62
|
+
- [Development with Docker Compose](#development-with-docker-compose)
|
|
61
63
|
- [Django Settings Configuration](#django-settings-configuration)
|
|
62
64
|
- [`DJANGO_QSTASH_DOMAIN`](#django_qstash_domain)
|
|
63
65
|
- [`DJANGO_QSTASH_WEBHOOK_PATH`](#django_qstash_webhook_path)
|
|
@@ -290,15 +292,33 @@ _Requires `django_qstash.schedules` installed._
|
|
|
290
292
|
- `python manage.py task_schedules --list` see all schedules relate to the `DJANGO_QSTASH_DOMAIN`
|
|
291
293
|
- `python manage.py task_schedules --sync` sync schedules based on the `DJANGO_QSTASH_DOMAIN` to store in the Django Admin.
|
|
292
294
|
|
|
293
|
-
##
|
|
295
|
+
## Development
|
|
296
|
+
|
|
297
|
+
During development, you have two options:
|
|
298
|
+
|
|
299
|
+
- Use Upstash.com with a publicly accessible domain (preferred)
|
|
300
|
+
- Use Docker Compose with [compose.dev.yaml](./compose.dev.yaml)
|
|
301
|
+
|
|
302
|
+
### Development with a Public Domain
|
|
303
|
+
|
|
304
|
+
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_.
|
|
294
305
|
|
|
295
|
-
|
|
306
|
+
To get a public domain during development, we recommend any of the following:
|
|
296
307
|
|
|
297
308
|
- [Cloudflare Tunnels](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) with a domain name you control.
|
|
298
309
|
- [ngrok](https://ngrok.com/)
|
|
299
310
|
|
|
300
311
|
Once you have a domain name, you can configure the `DJANGO_QSTASH_DOMAIN` setting in your Django settings.
|
|
301
312
|
|
|
313
|
+
### Development with Docker Compose
|
|
314
|
+
Upstash covers how to run QStash during development on [this guide](https://upstash.com/docs/qstash/howto/local-development)
|
|
315
|
+
|
|
316
|
+
In our case we need to the following things:
|
|
317
|
+
|
|
318
|
+
- `docker compose -f compose.dev.yaml up`
|
|
319
|
+
- Add `QSTASH_URL=http://127.0.0.1:8585` to your `.env` file.
|
|
320
|
+
- 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).
|
|
321
|
+
|
|
302
322
|
## Django Settings Configuration
|
|
303
323
|
|
|
304
324
|
Various options are available to configure django-qstash.
|
|
@@ -342,10 +362,13 @@ CSRF_TRUSTED_ORIGINS = [os.environ.get("CSRF_TRUSTED_ORIGIN")]
|
|
|
342
362
|
###########################
|
|
343
363
|
# qstash-py settings
|
|
344
364
|
###########################
|
|
365
|
+
USE_LOCAL_QSTASH = str(os.environ.get("USE_LOCAL_QSTASH")) == "1"
|
|
345
366
|
QSTASH_TOKEN = os.environ.get("QSTASH_TOKEN")
|
|
346
367
|
QSTASH_CURRENT_SIGNING_KEY = os.environ.get("QSTASH_CURRENT_SIGNING_KEY")
|
|
347
368
|
QSTASH_NEXT_SIGNING_KEY = os.environ.get("QSTASH_NEXT_SIGNING_KEY")
|
|
348
|
-
|
|
369
|
+
if DJANGO_DEBUG and USE_LOCAL_QSTASH:
|
|
370
|
+
# connect to the docker compose qstash instance
|
|
371
|
+
os.environ["QSTASH_URL"] = "http://127.0.0.1:8585"
|
|
349
372
|
###########################
|
|
350
373
|
# django_qstash settings
|
|
351
374
|
###########################
|
|
@@ -482,7 +505,7 @@ I think serverless is the answer. Pay for what you use and scale to zero when yo
|
|
|
482
505
|
|
|
483
506
|
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.
|
|
484
507
|
|
|
485
|
-
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.
|
|
508
|
+
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.
|
|
486
509
|
|
|
487
510
|
To make Django truly scale-to-zero and serverless, we need to drop Celery.
|
|
488
511
|
|
|
@@ -496,4 +519,6 @@ It works by leveraging Upstash QStash to deliver messages about your tasks (e.g.
|
|
|
496
519
|
>
|
|
497
520
|
> 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.
|
|
498
521
|
|
|
522
|
+
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.
|
|
523
|
+
|
|
499
524
|
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.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import warnings
|
|
5
|
+
|
|
6
|
+
from qstash import QStash
|
|
7
|
+
|
|
8
|
+
from django_qstash.settings import QSTASH_TOKEN
|
|
9
|
+
|
|
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()
|
|
@@ -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
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: django-qstash
|
|
3
|
-
Version: 0.0
|
|
3
|
+
Version: 0.1.0
|
|
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
|
|
@@ -27,11 +27,11 @@ Requires-Dist: django>=4.2
|
|
|
27
27
|
Requires-Dist: qstash>=2
|
|
28
28
|
Requires-Dist: requests>=2.30
|
|
29
29
|
|
|
30
|
-
> :warning: **BETA Software**: Working on being production-ready soon.
|
|
31
|
-
|
|
32
30
|
# django-qstash
|
|
33
31
|
|
|
34
|
-
|
|
32
|
+
Run background tasks with Django through webhooks and Upstash QStash.
|
|
33
|
+
|
|
34
|
+
_django-qstash_ is designed to be a drop-in replacement for Celery's `shared_task` or run alongside Celery.
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
## How it works
|
|
@@ -46,7 +46,7 @@ from django_qstash import shared_task
|
|
|
46
46
|
def my_task():
|
|
47
47
|
pass
|
|
48
48
|
```
|
|
49
|
-
> To use Celery
|
|
49
|
+
> To use django-qstash with Celery, you can use `@stashed_task` instead of `@shared_task` (more below).
|
|
50
50
|
|
|
51
51
|
To do this we need:
|
|
52
52
|
|
|
@@ -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)
|
|
@@ -319,15 +321,33 @@ _Requires `django_qstash.schedules` installed._
|
|
|
319
321
|
- `python manage.py task_schedules --list` see all schedules relate to the `DJANGO_QSTASH_DOMAIN`
|
|
320
322
|
- `python manage.py task_schedules --sync` sync schedules based on the `DJANGO_QSTASH_DOMAIN` to store in the Django Admin.
|
|
321
323
|
|
|
322
|
-
##
|
|
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)
|
|
330
|
+
|
|
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_.
|
|
323
334
|
|
|
324
|
-
|
|
335
|
+
To get a public domain during development, we recommend any of the following:
|
|
325
336
|
|
|
326
337
|
- [Cloudflare Tunnels](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) with a domain name you control.
|
|
327
338
|
- [ngrok](https://ngrok.com/)
|
|
328
339
|
|
|
329
340
|
Once you have a domain name, you can configure the `DJANGO_QSTASH_DOMAIN` setting in your Django settings.
|
|
330
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
|
+
|
|
331
351
|
## Django Settings Configuration
|
|
332
352
|
|
|
333
353
|
Various options are available to configure django-qstash.
|
|
@@ -371,10 +391,13 @@ CSRF_TRUSTED_ORIGINS = [os.environ.get("CSRF_TRUSTED_ORIGIN")]
|
|
|
371
391
|
###########################
|
|
372
392
|
# qstash-py settings
|
|
373
393
|
###########################
|
|
394
|
+
USE_LOCAL_QSTASH = str(os.environ.get("USE_LOCAL_QSTASH")) == "1"
|
|
374
395
|
QSTASH_TOKEN = os.environ.get("QSTASH_TOKEN")
|
|
375
396
|
QSTASH_CURRENT_SIGNING_KEY = os.environ.get("QSTASH_CURRENT_SIGNING_KEY")
|
|
376
397
|
QSTASH_NEXT_SIGNING_KEY = os.environ.get("QSTASH_NEXT_SIGNING_KEY")
|
|
377
|
-
|
|
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"
|
|
378
401
|
###########################
|
|
379
402
|
# django_qstash settings
|
|
380
403
|
###########################
|
|
@@ -511,7 +534,7 @@ I think serverless is the answer. Pay for what you use and scale to zero when yo
|
|
|
511
534
|
|
|
512
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.
|
|
513
536
|
|
|
514
|
-
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.
|
|
515
538
|
|
|
516
539
|
To make Django truly scale-to-zero and serverless, we need to drop Celery.
|
|
517
540
|
|
|
@@ -525,4 +548,6 @@ It works by leveraging Upstash QStash to deliver messages about your tasks (e.g.
|
|
|
525
548
|
>
|
|
526
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.
|
|
527
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
|
+
|
|
528
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.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/management/commands/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/management/commands/task_schedules.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/results/migrations/0001_initial.py
RENAMED
|
File without changes
|
|
File without changes
|
{django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/results/migrations/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/schedules/migrations/0001_initial.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash/schedules/migrations/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_qstash-0.0.14 → django_qstash-0.1.0}/src/django_qstash.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|