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 CHANGED
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.0.13"
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
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
- qstash_client = QStash(QSTASH_TOKEN)
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
@@ -0,0 +1,9 @@
1
+ from __future__ import annotations
2
+
3
+ from django.urls import path
4
+
5
+ from django_qstash.views import qstash_webhook_view
6
+
7
+ urlpatterns = [
8
+ path("", qstash_webhook_view),
9
+ ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: django-qstash
3
- Version: 0.0.13
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 URL](#configure-webhook-url)
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
- - [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)
@@ -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 URL
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 django_qstash.views import qstash_webhook_view
135
+ from django.urls import include
131
136
 
132
137
  urlpatterns = [
133
138
  # ...
134
- path("qstash/webhook/", qstash_webhook_view),
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
- ## Public Domain In Development
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
- django-qstash _requires_ a publicly accessible domain to work (e.g. `https://djangoqstash.com`). There are many ways to do this, we recommend:
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=YxzkGaAxjJrK8LRaZOcuwlnwzmTIBbfSOmhFmFG4oKk,188
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=cgHf-g6lDAltY_Vt6GUVJNY2JSz1czBOHL-WVkkLs2M,149
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=YvpXMo1AdIWvbotISWJmhg0vrW3A3UQ4BieNzMfRC7Y,524
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.13.dist-info/METADATA,sha256=6Vu2KEGFnQqPikFsTWo1cUJBRTq9Qi6CAJQsBuCijBM,19422
49
- django_qstash-0.0.13.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
50
- django_qstash-0.0.13.dist-info/top_level.txt,sha256=AlV3WSK1A0ZvKuCLsINtIJhJW8zo7SEB-D3_RAjZ0hI,14
51
- django_qstash-0.0.13.dist-info/RECORD,,
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,,