django-qstash 0.0.14__tar.gz → 0.0.15__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.

Files changed (65) hide show
  1. {django_qstash-0.0.14 → django_qstash-0.0.15}/PKG-INFO +31 -6
  2. {django_qstash-0.0.14 → django_qstash-0.0.15}/README.md +30 -5
  3. {django_qstash-0.0.14 → django_qstash-0.0.15}/pyproject.toml +1 -1
  4. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/__init__.py +1 -1
  5. django_qstash-0.0.15/src/django_qstash/client.py +25 -0
  6. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/settings.py +1 -1
  7. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash.egg-info/PKG-INFO +31 -6
  8. django_qstash-0.0.14/src/django_qstash/client.py +0 -7
  9. {django_qstash-0.0.14 → django_qstash-0.0.15}/setup.cfg +0 -0
  10. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/app/__init__.py +0 -0
  11. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/app/base.py +0 -0
  12. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/app/decorators.py +0 -0
  13. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/callbacks.py +0 -0
  14. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/cron.py +0 -0
  15. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/db/__init__.py +0 -0
  16. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/db/models.py +0 -0
  17. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/discovery/__init__.py +0 -0
  18. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/discovery/fields.py +0 -0
  19. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/discovery/models.py +0 -0
  20. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/discovery/utils.py +0 -0
  21. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/discovery/validators.py +0 -0
  22. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/exceptions.py +0 -0
  23. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/handlers.py +0 -0
  24. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/management/__init__.py +0 -0
  25. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/management/commands/__init__.py +0 -0
  26. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/management/commands/available_tasks.py +0 -0
  27. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/management/commands/clear_stale_results.py +0 -0
  28. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/management/commands/task_schedules.py +0 -0
  29. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/results/__init__.py +0 -0
  30. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/results/admin.py +0 -0
  31. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/results/apps.py +0 -0
  32. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/results/migrations/0001_initial.py +0 -0
  33. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/results/migrations/0002_taskresult_function_path_alter_taskresult_status_and_more.py +0 -0
  34. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/results/migrations/__init__.py +0 -0
  35. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/results/models.py +0 -0
  36. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/results/services.py +0 -0
  37. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/results/tasks.py +0 -0
  38. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/schedules/__init__.py +0 -0
  39. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/schedules/admin.py +0 -0
  40. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/schedules/apps.py +0 -0
  41. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/schedules/exceptions.py +0 -0
  42. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/schedules/formatters.py +0 -0
  43. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/schedules/forms.py +0 -0
  44. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/schedules/migrations/0001_initial.py +0 -0
  45. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/schedules/migrations/0002_taskschedule_updated_at.py +0 -0
  46. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/schedules/migrations/0003_alter_taskschedule_cron.py +0 -0
  47. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/schedules/migrations/__init__.py +0 -0
  48. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/schedules/models.py +0 -0
  49. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/schedules/services.py +0 -0
  50. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/schedules/signals.py +0 -0
  51. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/schedules/validators.py +0 -0
  52. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/urls.py +0 -0
  53. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/utils.py +0 -0
  54. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash/views.py +0 -0
  55. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash.egg-info/SOURCES.txt +0 -0
  56. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash.egg-info/dependency_links.txt +0 -0
  57. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash.egg-info/requires.txt +0 -0
  58. {django_qstash-0.0.14 → django_qstash-0.0.15}/src/django_qstash.egg-info/top_level.txt +0 -0
  59. {django_qstash-0.0.14 → django_qstash-0.0.15}/tests/test_callbacks.py +0 -0
  60. {django_qstash-0.0.14 → django_qstash-0.0.15}/tests/test_exceptions.py +0 -0
  61. {django_qstash-0.0.14 → django_qstash-0.0.15}/tests/test_handlers.py +0 -0
  62. {django_qstash-0.0.14 → django_qstash-0.0.15}/tests/test_results_models.py +0 -0
  63. {django_qstash-0.0.14 → django_qstash-0.0.15}/tests/test_settings.py +0 -0
  64. {django_qstash-0.0.14 → django_qstash-0.0.15}/tests/test_utils.py +0 -0
  65. {django_qstash-0.0.14 → django_qstash-0.0.15}/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.14
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
@@ -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
- - [Public Domain In Development](#public-domain-in-development)
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
- ## Public Domain In Development
324
+ ## Development
323
325
 
324
- django-qstash _requires_ a publicly accessible domain to work (e.g. `https://djangoqstash.com`). There are many ways to do this, we recommend:
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_.
334
+
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.
@@ -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
- - [Public Domain In Development](#public-domain-in-development)
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
- ## Public Domain In Development
295
+ ## Development
294
296
 
295
- django-qstash _requires_ a publicly accessible domain to work (e.g. `https://djangoqstash.com`). There are many ways to do this, we recommend:
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_.
305
+
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.
@@ -6,7 +6,7 @@ requires = [
6
6
 
7
7
  [project]
8
8
  name = "django-qstash"
9
- version = "0.0.14"
9
+ version = "0.0.15"
10
10
  description = "A drop-in replacement for Celery's shared_task with Upstash QStash."
11
11
  readme = "README.md"
12
12
  license = { file = "LICENSE" }
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.0.14"
3
+ __version__ = "0.0.15"
4
4
 
5
5
  from django_qstash.app import shared_task
6
6
  from django_qstash.app import stashed_task
@@ -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.14
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
@@ -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
- - [Public Domain In Development](#public-domain-in-development)
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
- ## Public Domain In Development
324
+ ## Development
323
325
 
324
- django-qstash _requires_ a publicly accessible domain to work (e.g. `https://djangoqstash.com`). There are many ways to do this, we recommend:
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_.
334
+
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,7 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from qstash import QStash
4
-
5
- from django_qstash.settings import QSTASH_TOKEN
6
-
7
- qstash_client = QStash(QSTASH_TOKEN)
File without changes