django-qstash 0.0.9__py3-none-any.whl → 0.0.11__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 +3 -2
- django_qstash/app/__init__.py +2 -1
- django_qstash/app/decorators.py +22 -3
- django_qstash/discovery/fields.py +6 -6
- django_qstash/discovery/utils.py +10 -2
- django_qstash/discovery/validators.py +2 -2
- django_qstash/management/commands/available_tasks.py +37 -0
- django_qstash/results/tasks.py +2 -2
- {django_qstash-0.0.9.dist-info → django_qstash-0.0.11.dist-info}/METADATA +129 -24
- {django_qstash-0.0.9.dist-info → django_qstash-0.0.11.dist-info}/RECORD +12 -11
- {django_qstash-0.0.9.dist-info → django_qstash-0.0.11.dist-info}/WHEEL +0 -0
- {django_qstash-0.0.9.dist-info → django_qstash-0.0.11.dist-info}/top_level.txt +0 -0
django_qstash/__init__.py
CHANGED
django_qstash/app/__init__.py
CHANGED
|
@@ -3,5 +3,6 @@ from __future__ import annotations
|
|
|
3
3
|
from .base import AsyncResult
|
|
4
4
|
from .base import QStashTask
|
|
5
5
|
from .decorators import shared_task
|
|
6
|
+
from .decorators import stashed_task
|
|
6
7
|
|
|
7
|
-
__all__ = ["AsyncResult", "QStashTask", "shared_task"]
|
|
8
|
+
__all__ = ["AsyncResult", "QStashTask", "stashed_task", "shared_task"]
|
django_qstash/app/decorators.py
CHANGED
|
@@ -6,24 +6,43 @@ from typing import Callable
|
|
|
6
6
|
from django_qstash.app.base import QStashTask
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
def
|
|
9
|
+
def stashed_task(
|
|
10
10
|
func: Callable | None = None,
|
|
11
11
|
name: str | None = None,
|
|
12
12
|
deduplicated: bool = False,
|
|
13
13
|
**options: dict[str, Any],
|
|
14
14
|
) -> QStashTask:
|
|
15
15
|
"""
|
|
16
|
-
Decorator that mimics Celery's shared_task
|
|
16
|
+
Decorator that mimics Celery's shared_task that maintains
|
|
17
|
+
Celery compatibility.
|
|
17
18
|
|
|
18
19
|
Can be used as:
|
|
20
|
+
|
|
21
|
+
from django_qstash import shared_task
|
|
22
|
+
|
|
19
23
|
@shared_task
|
|
20
24
|
def my_task():
|
|
21
25
|
pass
|
|
22
26
|
|
|
23
|
-
@
|
|
27
|
+
@stashed_task(name="custom_name", deduplicated=True)
|
|
24
28
|
def my_task():
|
|
25
29
|
pass
|
|
26
30
|
"""
|
|
27
31
|
if func is not None:
|
|
28
32
|
return QStashTask(func, name=name, deduplicated=deduplicated, **options)
|
|
29
33
|
return lambda f: QStashTask(f, name=name, deduplicated=deduplicated, **options)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def shared_task(func: Callable | None = None, **options: dict[str, Any]) -> QStashTask:
|
|
37
|
+
"""
|
|
38
|
+
Decorator that is a drop-in replacement for Celery's shared_task.
|
|
39
|
+
|
|
40
|
+
Can be used as:
|
|
41
|
+
|
|
42
|
+
from django_qstash import shared_task
|
|
43
|
+
|
|
44
|
+
@shared_task
|
|
45
|
+
def my_task():
|
|
46
|
+
pass
|
|
47
|
+
"""
|
|
48
|
+
return stashed_task(func, **options)
|
|
@@ -16,10 +16,10 @@ class TaskChoiceField(forms.ChoiceField):
|
|
|
16
16
|
kwargs.pop("max_length", None)
|
|
17
17
|
|
|
18
18
|
# Get tasks before calling parent to set choices
|
|
19
|
-
tasks = discover_tasks()
|
|
19
|
+
tasks = discover_tasks(locations_only=False)
|
|
20
20
|
|
|
21
21
|
# Convert tasks to choices using (task_name, task_name) format
|
|
22
|
-
task_choices = [(
|
|
22
|
+
task_choices = [(task["location"], task["field_label"]) for task in tasks]
|
|
23
23
|
|
|
24
24
|
kwargs["choices"] = task_choices
|
|
25
25
|
kwargs["validators"] = [task_exists_validator] + kwargs.get("validators", [])
|
|
@@ -30,9 +30,9 @@ class TaskChoiceField(forms.ChoiceField):
|
|
|
30
30
|
Returns the actual task dot notation path for the selected value
|
|
31
31
|
"""
|
|
32
32
|
if self.data:
|
|
33
|
-
tasks = discover_tasks()
|
|
33
|
+
tasks = discover_tasks(locations_only=False)
|
|
34
34
|
|
|
35
|
-
for
|
|
36
|
-
if
|
|
37
|
-
return
|
|
35
|
+
for task in tasks:
|
|
36
|
+
if task["field_label"] == self.data:
|
|
37
|
+
return task["location"]
|
|
38
38
|
return None
|
django_qstash/discovery/utils.py
CHANGED
|
@@ -19,7 +19,7 @@ DJANGO_QSTASH_DISCOVER_INCLUDE_SETTINGS_DIR = getattr(
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
@lru_cache(maxsize=None)
|
|
22
|
-
def discover_tasks() -> list[
|
|
22
|
+
def discover_tasks(locations_only: bool = False) -> list[str] | list[dict]:
|
|
23
23
|
"""
|
|
24
24
|
Automatically discover tasks in Django apps and return them as a list of tuples.
|
|
25
25
|
Each tuple contains (dot_notation_path, task_name).
|
|
@@ -72,13 +72,21 @@ def discover_tasks() -> list[tuple[str, str]]:
|
|
|
72
72
|
label = value
|
|
73
73
|
else:
|
|
74
74
|
label = f"{attr.name} ({package}.tasks)"
|
|
75
|
-
discovered_tasks.append(
|
|
75
|
+
discovered_tasks.append(
|
|
76
|
+
{
|
|
77
|
+
"name": attr.name,
|
|
78
|
+
"field_label": label,
|
|
79
|
+
"location": f"{package}.tasks.{attr_name}",
|
|
80
|
+
}
|
|
81
|
+
)
|
|
76
82
|
except Exception as e:
|
|
77
83
|
warnings.warn(
|
|
78
84
|
f"Failed to import tasks from {package}: {str(e)}",
|
|
79
85
|
RuntimeWarning,
|
|
80
86
|
stacklevel=2,
|
|
81
87
|
)
|
|
88
|
+
if locations_only:
|
|
89
|
+
return [x["location"] for x in discovered_tasks]
|
|
82
90
|
return discovered_tasks
|
|
83
91
|
|
|
84
92
|
|
|
@@ -15,8 +15,8 @@ def task_exists_validator(task_name):
|
|
|
15
15
|
Raises:
|
|
16
16
|
ValidationError: If the task cannot be found
|
|
17
17
|
"""
|
|
18
|
-
|
|
19
|
-
available_tasks =
|
|
18
|
+
discover_tasks.cache_clear()
|
|
19
|
+
available_tasks = discover_tasks(locations_only=True)
|
|
20
20
|
|
|
21
21
|
if task_name not in available_tasks:
|
|
22
22
|
raise ValidationError(
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from django.core.management.base import BaseCommand
|
|
4
|
+
|
|
5
|
+
from django_qstash.discovery.utils import discover_tasks
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Command(BaseCommand):
|
|
9
|
+
help = "View all available tasks"
|
|
10
|
+
|
|
11
|
+
def add_arguments(self, parser):
|
|
12
|
+
parser.add_argument(
|
|
13
|
+
"--locations",
|
|
14
|
+
action="store_true",
|
|
15
|
+
help="Only show task paths",
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
def handle(self, *args, **options):
|
|
19
|
+
locations_only = options["locations"] or False
|
|
20
|
+
self.stdout.write("Available tasks:")
|
|
21
|
+
discover_tasks.cache_clear()
|
|
22
|
+
if locations_only:
|
|
23
|
+
tasks = discover_tasks(locations_only=locations_only)
|
|
24
|
+
for task in tasks:
|
|
25
|
+
self.stdout.write(f"\t- {self.style.SQL_FIELD(task)}")
|
|
26
|
+
else:
|
|
27
|
+
tasks = discover_tasks(locations_only=False)
|
|
28
|
+
for task in tasks:
|
|
29
|
+
name = task["name"]
|
|
30
|
+
field_label = task["field_label"]
|
|
31
|
+
location = task["location"]
|
|
32
|
+
self.stdout.write(
|
|
33
|
+
f" Name: {self.style.SQL_FIELD(name)}\n"
|
|
34
|
+
f" Location: {self.style.SQL_FIELD(location)}\n"
|
|
35
|
+
f" Field Label: {self.style.SQL_FIELD(field_label)}"
|
|
36
|
+
)
|
|
37
|
+
self.stdout.write("")
|
django_qstash/results/tasks.py
CHANGED
|
@@ -7,14 +7,14 @@ from django.apps import apps
|
|
|
7
7
|
from django.conf import settings
|
|
8
8
|
from django.utils import timezone
|
|
9
9
|
|
|
10
|
-
from django_qstash import
|
|
10
|
+
from django_qstash import stashed_task
|
|
11
11
|
|
|
12
12
|
DJANGO_QSTASH_RESULT_TTL = getattr(settings, "DJANGO_QSTASH_RESULT_TTL", 604800)
|
|
13
13
|
|
|
14
14
|
logger = logging.getLogger(__name__)
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
@
|
|
17
|
+
@stashed_task(name="Cleanup Task Results")
|
|
18
18
|
def clear_stale_results_task(
|
|
19
19
|
since=None, stdout=None, user_confirm=False, *args, **options
|
|
20
20
|
):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: django-qstash
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.11
|
|
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
|
|
@@ -33,16 +33,32 @@ Requires-Dist: requests>=2.30
|
|
|
33
33
|
|
|
34
34
|
_django-qstash_ is a drop-in replacement for Celery's `shared_task`.
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
|
|
37
|
+
## How it works
|
|
38
|
+
|
|
39
|
+
In `tasks.py` in your apps:
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from django_qstash import shared_task
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@shared_task
|
|
46
|
+
def my_task():
|
|
47
|
+
pass
|
|
48
|
+
```
|
|
49
|
+
> To use Celery too, you can use `@stashed_task` instead of `@shared_task` more below.
|
|
50
|
+
|
|
51
|
+
To do this we need:
|
|
37
52
|
|
|
38
53
|
- [Upstash QStash](https://upstash.com/docs/qstash/overall/getstarted)
|
|
39
|
-
- A single public _webhook_ to call `@
|
|
54
|
+
- A single public _webhook_ to call `@stashed_task` functions automatically
|
|
40
55
|
|
|
41
56
|
This allows us to:
|
|
42
57
|
|
|
58
|
+
- Nearly identical usage to Celery's `@shared_task` with far less configuration and overhead
|
|
43
59
|
- Focus just on Django
|
|
44
|
-
- Drop Celery
|
|
45
|
-
-
|
|
60
|
+
- Drop Celery completely, scale it down, or use it as normal. django-qstash can work hand-in-hand with Celery
|
|
61
|
+
- Unlock true serverless and scale-to-zero for Django
|
|
46
62
|
- Run background tasks through webhooks
|
|
47
63
|
- Cut costs
|
|
48
64
|
- Trigger GitHub Actions Workflows or GitLab CI/CD pipelines for handling other kinds of background tasks based on our project's code.
|
|
@@ -51,6 +67,7 @@ This allows us to:
|
|
|
51
67
|
## Table of Contents
|
|
52
68
|
|
|
53
69
|
- [django-qstash](#django-qstash)
|
|
70
|
+
- [How it works](#how-it-works)
|
|
54
71
|
- [Table of Contents](#table-of-contents)
|
|
55
72
|
- [Installation](#installation)
|
|
56
73
|
- [Using Pip](#using-pip)
|
|
@@ -68,8 +85,13 @@ This allows us to:
|
|
|
68
85
|
- [`.apply_async()` With Time Delay](#apply_async-with-time-delay)
|
|
69
86
|
- [JSON-ready Arguments](#json-ready-arguments)
|
|
70
87
|
- [Example Task](#example-task)
|
|
71
|
-
- [
|
|
72
|
-
- [
|
|
88
|
+
- [Management Commands](#management-commands)
|
|
89
|
+
- [Development Usage](#development-usage)
|
|
90
|
+
- [Django Settings Configuration](#django-settings-configuration)
|
|
91
|
+
- [Schedule Tasks (Optional)](#schedule-tasks-optional)
|
|
92
|
+
- [Installation](#installation-1)
|
|
93
|
+
- [Schedule a Task](#schedule-a-task)
|
|
94
|
+
- [Store Task Results (Optional)](#store-task-results-optional)
|
|
73
95
|
- [Clear Stale Results](#clear-stale-results)
|
|
74
96
|
- [Definitions](#definitions)
|
|
75
97
|
- [Motivation](#motivation)
|
|
@@ -89,12 +111,13 @@ INSTALLED_APPS = [
|
|
|
89
111
|
##...
|
|
90
112
|
"django_qstash",
|
|
91
113
|
"django_qstash.results",
|
|
114
|
+
"django_qstash.schedules",
|
|
92
115
|
##...
|
|
93
116
|
]
|
|
94
117
|
```
|
|
95
|
-
- `django_qstash` Includes the `@shared_task`
|
|
118
|
+
- `django_qstash` Includes the `@shared_task` and `@stashed_task` decorators and webhook view
|
|
96
119
|
- `django_qstash.results` (Optional): Store task results in Django DB
|
|
97
|
-
|
|
120
|
+
- `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.
|
|
98
121
|
|
|
99
122
|
### Configure Webhook URL
|
|
100
123
|
|
|
@@ -138,7 +161,7 @@ There is a sample project in [sample_project/](sample_project/) that shows how a
|
|
|
138
161
|
|
|
139
162
|
## Usage
|
|
140
163
|
|
|
141
|
-
Django-QStash revolves around the `
|
|
164
|
+
Django-QStash revolves around the `stashed_task` decorator. The goal is to be a drop-in replacement for Celery's `stashed_task` decorator.
|
|
142
165
|
|
|
143
166
|
Here's how it works:
|
|
144
167
|
- Define a Task
|
|
@@ -146,10 +169,10 @@ Here's how it works:
|
|
|
146
169
|
|
|
147
170
|
### Define a Task
|
|
148
171
|
```python
|
|
149
|
-
from django_qstash import
|
|
172
|
+
from django_qstash import stashed_task
|
|
150
173
|
|
|
151
174
|
|
|
152
|
-
@
|
|
175
|
+
@stashed_task
|
|
153
176
|
def hello_world(name: str, age: int = None, activity: str = None):
|
|
154
177
|
if age is None:
|
|
155
178
|
print(f"Hello {name}! I see you're {activity}.")
|
|
@@ -157,7 +180,6 @@ def hello_world(name: str, age: int = None, activity: str = None):
|
|
|
157
180
|
print(f"Hello {name}! I see you're {activity} at {age} years old.")
|
|
158
181
|
```
|
|
159
182
|
|
|
160
|
-
|
|
161
183
|
### Regular Task Call
|
|
162
184
|
Nothing special here. Just call the function like any other to verify it works.
|
|
163
185
|
|
|
@@ -220,10 +242,13 @@ print(json.dumps(data))
|
|
|
220
242
|
|
|
221
243
|
```python
|
|
222
244
|
# from celery import shared_task
|
|
223
|
-
|
|
245
|
+
# becomes
|
|
246
|
+
# from django_qstash import shared_task
|
|
247
|
+
# or
|
|
248
|
+
from django_qstash import stashed_task
|
|
224
249
|
|
|
225
250
|
|
|
226
|
-
@
|
|
251
|
+
@stashed_task
|
|
227
252
|
def math_add_task(a, b, save_to_file=False, *args, **kwargs):
|
|
228
253
|
logger.info(f"Adding {a} and {b}")
|
|
229
254
|
if save_to_file:
|
|
@@ -254,22 +279,101 @@ math_add_task.apply_async(
|
|
|
254
279
|
The `.delay()` method does not support a countdown parameter because it simply passes the arguments (*args, **kwargs) to the `apply_async()` method.
|
|
255
280
|
|
|
256
281
|
|
|
257
|
-
##
|
|
282
|
+
## Management Commands
|
|
283
|
+
|
|
284
|
+
- `python manage.py available_tasks` to view all available tasks
|
|
285
|
+
|
|
286
|
+
_Requires `django_qstash.schedules` installed._
|
|
287
|
+
- `python manage.py task_schedules --list` see all schedules relate to the `DJANGO_QSTASH_DOMAIN`
|
|
288
|
+
- `python manage.py task_schedules --sync` sync schedules based on the `DJANGO_QSTASH_DOMAIN` to store in the Django Admin.
|
|
289
|
+
|
|
290
|
+
## Development Usage
|
|
291
|
+
|
|
292
|
+
django-qstash requires a public domain to work (e.g. `https://djangoqstash.com`). There are many ways to do this, we recommend:
|
|
293
|
+
|
|
294
|
+
- [Cloudflare Tunnels](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) with a domain name you control.
|
|
295
|
+
- [ngrok](https://ngrok.com/)
|
|
296
|
+
|
|
297
|
+
Once you have a domain name, you can configure the `DJANGO_QSTASH_DOMAIN` setting in your Django settings.
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
## Django Settings Configuration
|
|
258
301
|
|
|
259
302
|
In Django settings, you can configure the following:
|
|
260
303
|
|
|
261
|
-
`DJANGO_QSTASH_DOMAIN`: Must be a valid and publicly accessible domain. For example `https://djangoqstash.com
|
|
304
|
+
- `DJANGO_QSTASH_DOMAIN`: Must be a valid and publicly accessible domain. For example `https://djangoqstash.com`. Review [Development usage](#development-usage) for setting up a domain name during development.
|
|
305
|
+
|
|
306
|
+
- `DJANGO_QSTASH_WEBHOOK_PATH` (default:`/qstash/webhook/`): The path where QStash will send webhooks to your Django application.
|
|
307
|
+
|
|
308
|
+
- `DJANGO_QSTASH_FORCE_HTTPS` (default:`True`): Whether to force HTTPS for the webhook.
|
|
262
309
|
|
|
263
|
-
|
|
310
|
+
- `DJANGO_QSTASH_RESULT_TTL` (default:`604800`): A number of seconds after which task result data can be safely deleted. Defaults to 604800 seconds (7 days or 7 * 24 * 60 * 60).
|
|
264
311
|
|
|
265
|
-
`DJANGO_QSTASH_WEBHOOK_PATH` (default:`/qstash/webhook/`): The path where QStash will send webhooks to your Django application.
|
|
266
312
|
|
|
267
|
-
|
|
313
|
+
## Schedule Tasks (Optional)
|
|
268
314
|
|
|
269
|
-
`
|
|
315
|
+
The `django_qstash.schedules` app schedules tasks using Upstash [QStash Schedules](https://upstash.com/docs/qstash/features/schedules) and the django-qstash `@stashed_task` decorator.
|
|
270
316
|
|
|
317
|
+
### Installation
|
|
271
318
|
|
|
272
|
-
|
|
319
|
+
Update your `INSTALLED_APPS` setting to include `django_qstash.schedules`.
|
|
320
|
+
|
|
321
|
+
```python
|
|
322
|
+
INSTALLED_APPS = [
|
|
323
|
+
# ...
|
|
324
|
+
"django_qstash", # required
|
|
325
|
+
"django_qstash.schedules",
|
|
326
|
+
# ...
|
|
327
|
+
]
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
Run migrations:
|
|
331
|
+
```bash
|
|
332
|
+
python manage.py migrate django_qstash_schedules
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
## Schedule a Task
|
|
337
|
+
|
|
338
|
+
Tasks must exist before you can schedule them. Review [Define a Task](#define-a-task) for more information.
|
|
339
|
+
|
|
340
|
+
Here's how you can schedule a task:
|
|
341
|
+
- Django Admin (`/admin/django_qstash_schedules/taskschedule/add/`)
|
|
342
|
+
- Django shell (`python manage.py shell`)
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
```python
|
|
348
|
+
from django_qstash.schedules.models import TaskSchedule
|
|
349
|
+
from django_qstash.discovery.utils import discover_tasks
|
|
350
|
+
|
|
351
|
+
all_available_tasks = discover_tasks(paths_only=True)
|
|
352
|
+
|
|
353
|
+
desired_task = "django_qstash.results.clear_stale_results_task"
|
|
354
|
+
# or desired_task = "example_app.tasks.my_task"
|
|
355
|
+
|
|
356
|
+
task_to_use = desired_task
|
|
357
|
+
if desired_task not in available_task_locations:
|
|
358
|
+
task_to_use = available_task_locations[0]
|
|
359
|
+
|
|
360
|
+
print(f"Using task: {task_to_use}")
|
|
361
|
+
|
|
362
|
+
TaskSchedule.objects.create(
|
|
363
|
+
name="My Schedule",
|
|
364
|
+
cron="0 0 * * *",
|
|
365
|
+
task_name=task_to_use,
|
|
366
|
+
args=["arg1", "arg2"],
|
|
367
|
+
kwargs={"kwarg1": "value1", "kwarg2": "value2"},
|
|
368
|
+
)
|
|
369
|
+
```
|
|
370
|
+
- `django_qstash.results.clear_stale_results_task` is a built-in task that `django_qstash.results` provides
|
|
371
|
+
- `args` and `kwargs` are the arguments to pass to the task
|
|
372
|
+
- `cron` is the cron schedule to run the task. Use [contrab.guru](https://crontab.guru/) for writing the cron format.
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
## Store Task Results (Optional)
|
|
273
377
|
|
|
274
378
|
In `django_qstash.results.models` we have the `TaskResult` model class that can be used to track async task results. These entries are created via webhooks.
|
|
275
379
|
|
|
@@ -278,6 +382,7 @@ To install it, just add `django_qstash.results` to your `INSTALLED_APPS` setting
|
|
|
278
382
|
```python
|
|
279
383
|
INSTALLED_APPS = [
|
|
280
384
|
# ...
|
|
385
|
+
"django_qstash",
|
|
281
386
|
"django_qstash.results",
|
|
282
387
|
# ...
|
|
283
388
|
]
|
|
@@ -285,14 +390,14 @@ INSTALLED_APPS = [
|
|
|
285
390
|
|
|
286
391
|
Run migrations:
|
|
287
392
|
```bash
|
|
288
|
-
python manage.py migrate
|
|
393
|
+
python manage.py migrate django_qstash_results
|
|
289
394
|
```
|
|
290
395
|
|
|
291
396
|
### Clear Stale Results
|
|
292
397
|
|
|
293
398
|
We recommend purging the `TaskResult` model after a certain amount of time.
|
|
294
399
|
```bash
|
|
295
|
-
python manage.py clear_stale_results
|
|
400
|
+
python manage.py clear_stale_results --since 604800
|
|
296
401
|
```
|
|
297
402
|
Args:
|
|
298
403
|
- `--since` is the number of seconds ago to clear results for. Defaults to 604800 seconds (7 days or the `DJANGO_QSTASH_RESULT_TTL` setting).
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
django_qstash/__init__.py,sha256=
|
|
1
|
+
django_qstash/__init__.py,sha256=IpryDJmo4VtbkyGvYNbMeNbhF7Cg0fvpj5d3SLT7wac,188
|
|
2
2
|
django_qstash/callbacks.py,sha256=VG5tGdNzAmUEh7NlpghrxhWvnpRNXZucWmWwxaemw0M,530
|
|
3
3
|
django_qstash/client.py,sha256=cgHf-g6lDAltY_Vt6GUVJNY2JSz1czBOHL-WVkkLs2M,149
|
|
4
4
|
django_qstash/exceptions.py,sha256=pH6kKRJFIVFkDHUJQ9yRWmtGdBBSXpNAwMSFuNzMgPw,392
|
|
@@ -6,16 +6,17 @@ django_qstash/handlers.py,sha256=mmm8TJOqV3j1rQXooNOa128gtmALXFNCAaDZ5xwIcuw,495
|
|
|
6
6
|
django_qstash/settings.py,sha256=YvpXMo1AdIWvbotISWJmhg0vrW3A3UQ4BieNzMfRC7Y,524
|
|
7
7
|
django_qstash/utils.py,sha256=wrTU30cobO2di18BNEFtKD4ih2euf7eQNpg6p6TkQ1Y,1185
|
|
8
8
|
django_qstash/views.py,sha256=H32f_jGnlwOTO0YG9znNo2b-GRYZ8TM-Wt0T62SGdXM,639
|
|
9
|
-
django_qstash/app/__init__.py,sha256=
|
|
9
|
+
django_qstash/app/__init__.py,sha256=kmoCVoESInzCZ_oGUiPVY4GsFQwBC07cqFJCyn9Loyk,240
|
|
10
10
|
django_qstash/app/base.py,sha256=gM7GIJh_omZcxbmsrwAEadA-N6EuUJbPzh0CflOIVRg,3864
|
|
11
|
-
django_qstash/app/decorators.py,sha256=
|
|
11
|
+
django_qstash/app/decorators.py,sha256=Zkr0dLhW5-7yGmj7JunLGcgzOwsONRyz3YkrD957DqY,1170
|
|
12
12
|
django_qstash/discovery/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
-
django_qstash/discovery/fields.py,sha256=
|
|
13
|
+
django_qstash/discovery/fields.py,sha256=h-31sysbIU05KGKGBAu7uQo9bZnZg3kgjN_ZhPPMTGU,1260
|
|
14
14
|
django_qstash/discovery/models.py,sha256=9ml9lTKEqEKx2uqYvejZw_BjdnowgFOPE7rYNt_8E9A,685
|
|
15
|
-
django_qstash/discovery/utils.py,sha256=
|
|
16
|
-
django_qstash/discovery/validators.py,sha256=
|
|
15
|
+
django_qstash/discovery/utils.py,sha256=OW-sbHWSnA1Hop5X0ys1hlxoYi5fNTXfAg0rKku5sx0,3561
|
|
16
|
+
django_qstash/discovery/validators.py,sha256=50-GxdSNj00eY-EGxDR8u1kUQDj0g8PoeWHAGG1cvzk,657
|
|
17
17
|
django_qstash/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
18
|
django_qstash/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
|
+
django_qstash/management/commands/available_tasks.py,sha256=l-do7Mry83NxbCdyMLcLZKtwE_T428i8wA42FIn5fq0,1295
|
|
19
20
|
django_qstash/management/commands/clear_stale_results.py,sha256=mxXXqIy6pnvsN8JVE0xe3mypqtkaZbpqdBjpox-MDik,1402
|
|
20
21
|
django_qstash/management/commands/task_schedules.py,sha256=b9lJ1vjQKHyGzWAo9csGwE_oaKfgcSC8bPFLt9Ry6WE,4278
|
|
21
22
|
django_qstash/results/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -23,7 +24,7 @@ django_qstash/results/admin.py,sha256=q9fn3lfn0gviMfiimYij0wBCYww7FxyrOfGPr1Nvnt
|
|
|
23
24
|
django_qstash/results/apps.py,sha256=4me4cg5yeoeSJTphkHYzGMJUfGucT47FNIUMYu5gmIo,275
|
|
24
25
|
django_qstash/results/models.py,sha256=aEiAhGJOuLRtjibUw6xdQqUt3eYKLqY2as4I4QSrF5U,1047
|
|
25
26
|
django_qstash/results/services.py,sha256=HvNp5D1tQ__nz4LVUTAGxuyLl_dnlBps4pJ6E9HD2kA,991
|
|
26
|
-
django_qstash/results/tasks.py,sha256=
|
|
27
|
+
django_qstash/results/tasks.py,sha256=5o0Lb2XjWDVQOHPnZnW97stzdydCeq_UZzdE2j2jvEs,2168
|
|
27
28
|
django_qstash/results/migrations/0001_initial.py,sha256=A90SKgWmBf4SIJYG1Jh6-b_81Ia1zIzGj3Bfl1O4-kg,1902
|
|
28
29
|
django_qstash/results/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
30
|
django_qstash/schedules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -39,7 +40,7 @@ django_qstash/schedules/validators.py,sha256=i8IEjnRVk-iysmqvT_kbPYpxTKCQWoX9P1J
|
|
|
39
40
|
django_qstash/schedules/migrations/0001_initial.py,sha256=66cA8xnJV3h7QgzCaOiv-Nu3Xl9IdZQPgQKhxyW3bs4,4516
|
|
40
41
|
django_qstash/schedules/migrations/0002_taskschedule_updated_at.py,sha256=6hZO0a9P2ZpOROkk7O5UXBhahghU0QfxZl4E-c3HKGw,459
|
|
41
42
|
django_qstash/schedules/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
42
|
-
django_qstash-0.0.
|
|
43
|
-
django_qstash-0.0.
|
|
44
|
-
django_qstash-0.0.
|
|
45
|
-
django_qstash-0.0.
|
|
43
|
+
django_qstash-0.0.11.dist-info/METADATA,sha256=FoYduoYeCoobQqnx2__vsz-yXnYsysOcGRLnIfVAjxE,15971
|
|
44
|
+
django_qstash-0.0.11.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
45
|
+
django_qstash-0.0.11.dist-info/top_level.txt,sha256=AlV3WSK1A0ZvKuCLsINtIJhJW8zo7SEB-D3_RAjZ0hI,14
|
|
46
|
+
django_qstash-0.0.11.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|