django-qstash 0.0.7__py3-none-any.whl → 0.0.8__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 +2 -2
- django_qstash/app/__init__.py +7 -0
- django_qstash/{tasks.py → app/base.py} +0 -23
- django_qstash/app/decorators.py +29 -0
- django_qstash/discovery/utils.py +2 -2
- django_qstash/management/commands/clear_stale_results.py +14 -33
- django_qstash/results/tasks.py +67 -0
- {django_qstash-0.0.7.dist-info → django_qstash-0.0.8.dist-info}/METADATA +1 -1
- {django_qstash-0.0.7.dist-info → django_qstash-0.0.8.dist-info}/RECORD +11 -8
- {django_qstash-0.0.7.dist-info → django_qstash-0.0.8.dist-info}/WHEEL +0 -0
- {django_qstash-0.0.7.dist-info → django_qstash-0.0.8.dist-info}/top_level.txt +0 -0
django_qstash/__init__.py
CHANGED
|
@@ -118,26 +118,3 @@ class AsyncResult:
|
|
|
118
118
|
@property
|
|
119
119
|
def id(self) -> str:
|
|
120
120
|
return self.task_id
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
def shared_task(
|
|
124
|
-
func: Callable | None = None,
|
|
125
|
-
name: str | None = None,
|
|
126
|
-
deduplicated: bool = False,
|
|
127
|
-
**options: dict[str, Any],
|
|
128
|
-
) -> QStashTask:
|
|
129
|
-
"""
|
|
130
|
-
Decorator that mimics Celery's shared_task
|
|
131
|
-
|
|
132
|
-
Can be used as:
|
|
133
|
-
@shared_task
|
|
134
|
-
def my_task():
|
|
135
|
-
pass
|
|
136
|
-
|
|
137
|
-
@shared_task(name="custom_name", deduplicated=True)
|
|
138
|
-
def my_task():
|
|
139
|
-
pass
|
|
140
|
-
"""
|
|
141
|
-
if func is not None:
|
|
142
|
-
return QStashTask(func, name=name, deduplicated=deduplicated, **options)
|
|
143
|
-
return lambda f: QStashTask(f, name=name, deduplicated=deduplicated, **options)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
from typing import Callable
|
|
5
|
+
|
|
6
|
+
from django_qstash.app.base import QStashTask
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def shared_task(
|
|
10
|
+
func: Callable | None = None,
|
|
11
|
+
name: str | None = None,
|
|
12
|
+
deduplicated: bool = False,
|
|
13
|
+
**options: dict[str, Any],
|
|
14
|
+
) -> QStashTask:
|
|
15
|
+
"""
|
|
16
|
+
Decorator that mimics Celery's shared_task
|
|
17
|
+
|
|
18
|
+
Can be used as:
|
|
19
|
+
@shared_task
|
|
20
|
+
def my_task():
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
@shared_task(name="custom_name", deduplicated=True)
|
|
24
|
+
def my_task():
|
|
25
|
+
pass
|
|
26
|
+
"""
|
|
27
|
+
if func is not None:
|
|
28
|
+
return QStashTask(func, name=name, deduplicated=deduplicated, **options)
|
|
29
|
+
return lambda f: QStashTask(f, name=name, deduplicated=deduplicated, **options)
|
django_qstash/discovery/utils.py
CHANGED
|
@@ -32,7 +32,7 @@ def discover_tasks() -> list[tuple[str, str]]:
|
|
|
32
32
|
('other_app.tasks.custom_task', 'special_name')
|
|
33
33
|
]
|
|
34
34
|
"""
|
|
35
|
-
from django_qstash.
|
|
35
|
+
from django_qstash.app import QStashTask
|
|
36
36
|
|
|
37
37
|
discovered_tasks = []
|
|
38
38
|
packages = []
|
|
@@ -71,7 +71,7 @@ def discover_tasks() -> list[tuple[str, str]]:
|
|
|
71
71
|
if attr.name == attr_name:
|
|
72
72
|
label = value
|
|
73
73
|
else:
|
|
74
|
-
label = f"{attr.name} ({
|
|
74
|
+
label = f"{attr.name} ({package}.tasks)"
|
|
75
75
|
discovered_tasks.append((value, label))
|
|
76
76
|
except Exception as e:
|
|
77
77
|
warnings.warn(
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from datetime import timedelta
|
|
4
|
-
|
|
5
|
-
from django.apps import apps
|
|
6
3
|
from django.conf import settings
|
|
7
4
|
from django.core.management.base import BaseCommand
|
|
8
|
-
|
|
5
|
+
|
|
6
|
+
from django_qstash.results.tasks import clear_stale_results_task
|
|
9
7
|
|
|
10
8
|
DJANGO_QSTASH_RESULT_TTL = getattr(settings, "DJANGO_QSTASH_RESULT_TTL", 604800)
|
|
11
9
|
|
|
@@ -25,37 +23,20 @@ class Command(BaseCommand):
|
|
|
25
23
|
type=int,
|
|
26
24
|
help="The number of seconds ago to clear results for",
|
|
27
25
|
)
|
|
26
|
+
parser.add_argument(
|
|
27
|
+
"--delay", action="store_true", help="Offload request using django_qstash"
|
|
28
|
+
)
|
|
28
29
|
|
|
29
30
|
def handle(self, *args, **options):
|
|
31
|
+
delay = options["delay"]
|
|
30
32
|
no_input = options["no_input"]
|
|
31
33
|
since = options.get("since") or DJANGO_QSTASH_RESULT_TTL
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
user_confirm = not no_input
|
|
35
|
+
if not delay:
|
|
36
|
+
clear_stale_results_task(
|
|
37
|
+
since=since, user_confirm=user_confirm, stdout=self.stdout
|
|
38
|
+
)
|
|
39
|
+
else:
|
|
40
|
+
clear_stale_results_task.delay(
|
|
41
|
+
since=since, user_confirm=user_confirm, stdout=self.stdout
|
|
40
42
|
)
|
|
41
|
-
return
|
|
42
|
-
to_delete = TaskResult.objects.filter(date_done__lt=cutoff_date)
|
|
43
|
-
|
|
44
|
-
if not to_delete.exists():
|
|
45
|
-
self.stdout.write("No stale Django QStash task results found")
|
|
46
|
-
return
|
|
47
|
-
|
|
48
|
-
# use input to confirm deletion
|
|
49
|
-
self.stdout.write(
|
|
50
|
-
f"Deleting {to_delete.count()} task results older than {cutoff_date} ({DJANGO_QSTASH_RESULT_TTL} seconds)"
|
|
51
|
-
)
|
|
52
|
-
if not no_input:
|
|
53
|
-
if input("Are you sure? (y/n): ") != "y":
|
|
54
|
-
self.stdout.write("Skipping deletion")
|
|
55
|
-
return
|
|
56
|
-
|
|
57
|
-
deleted_count, _ = to_delete.delete()
|
|
58
|
-
|
|
59
|
-
self.stdout.write(
|
|
60
|
-
self.style.SUCCESS(f"Successfully deleted {deleted_count} stale results.")
|
|
61
|
-
)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from datetime import timedelta
|
|
5
|
+
|
|
6
|
+
from django.apps import apps
|
|
7
|
+
from django.conf import settings
|
|
8
|
+
from django.utils import timezone
|
|
9
|
+
|
|
10
|
+
from django_qstash import shared_task
|
|
11
|
+
|
|
12
|
+
DJANGO_QSTASH_RESULT_TTL = getattr(settings, "DJANGO_QSTASH_RESULT_TTL", 604800)
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@shared_task(name="Cleanup Task Results")
|
|
18
|
+
def clear_stale_results_task(
|
|
19
|
+
since=None, stdout=None, user_confirm=False, *args, **options
|
|
20
|
+
):
|
|
21
|
+
delta_seconds = since or DJANGO_QSTASH_RESULT_TTL
|
|
22
|
+
cutoff_date = timezone.now() - timedelta(seconds=delta_seconds)
|
|
23
|
+
TaskResult = None
|
|
24
|
+
try:
|
|
25
|
+
TaskResult = apps.get_model("django_qstash_results", "TaskResult")
|
|
26
|
+
except LookupError as e:
|
|
27
|
+
msg = "Django QStash Results not installed.\nAdd `django_qstash.results` to INSTALLED_APPS and run migrations."
|
|
28
|
+
if stdout is not None:
|
|
29
|
+
stdout.write(msg)
|
|
30
|
+
logger.exception(msg)
|
|
31
|
+
raise e
|
|
32
|
+
qs_to_delete = TaskResult.objects.filter(date_done__lt=cutoff_date)
|
|
33
|
+
|
|
34
|
+
if user_confirm:
|
|
35
|
+
user_input = input("Are you sure? (Y/n): ")
|
|
36
|
+
if f"{user_input}".lower() != "y":
|
|
37
|
+
msg = "Skipping deletion"
|
|
38
|
+
if stdout is not None:
|
|
39
|
+
stdout.write(msg)
|
|
40
|
+
logger.info(msg)
|
|
41
|
+
return
|
|
42
|
+
|
|
43
|
+
if not qs_to_delete.exists():
|
|
44
|
+
msg = "No stale Django QStash task results found"
|
|
45
|
+
if stdout is not None:
|
|
46
|
+
stdout.write(msg)
|
|
47
|
+
else:
|
|
48
|
+
logger.info(msg)
|
|
49
|
+
return
|
|
50
|
+
delete_msg = f"Deleting {qs_to_delete.count()} task results older than {cutoff_date} ({DJANGO_QSTASH_RESULT_TTL} seconds)"
|
|
51
|
+
if stdout is not None:
|
|
52
|
+
stdout.write(delete_msg)
|
|
53
|
+
else:
|
|
54
|
+
logger.info(delete_msg)
|
|
55
|
+
try:
|
|
56
|
+
deleted_count, _ = qs_to_delete.delete()
|
|
57
|
+
msg = f"Successfully deleted {deleted_count} stale results."
|
|
58
|
+
if stdout is not None:
|
|
59
|
+
stdout.write(msg)
|
|
60
|
+
else:
|
|
61
|
+
logger.info(msg)
|
|
62
|
+
except Exception as e:
|
|
63
|
+
msg = f"Error deleting stale results: {e}"
|
|
64
|
+
if stdout is not None:
|
|
65
|
+
stdout.write(msg)
|
|
66
|
+
logger.exception(msg)
|
|
67
|
+
raise e
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: django-qstash
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.8
|
|
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
|
|
@@ -1,26 +1,29 @@
|
|
|
1
|
-
django_qstash/__init__.py,sha256=
|
|
1
|
+
django_qstash/__init__.py,sha256=NkydB5VW3zGO7c9-nveE0LELDPNix3lLQIZxWDeFBtI,128
|
|
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
|
|
5
5
|
django_qstash/handlers.py,sha256=mmm8TJOqV3j1rQXooNOa128gtmALXFNCAaDZ5xwIcuw,4950
|
|
6
6
|
django_qstash/settings.py,sha256=YvpXMo1AdIWvbotISWJmhg0vrW3A3UQ4BieNzMfRC7Y,524
|
|
7
|
-
django_qstash/tasks.py,sha256=VYv7m0Uz1v8kPBegGHam5AH0Hcc-n53BZz3IdQcAqsk,4462
|
|
8
7
|
django_qstash/utils.py,sha256=wrTU30cobO2di18BNEFtKD4ih2euf7eQNpg6p6TkQ1Y,1185
|
|
9
8
|
django_qstash/views.py,sha256=H32f_jGnlwOTO0YG9znNo2b-GRYZ8TM-Wt0T62SGdXM,639
|
|
9
|
+
django_qstash/app/__init__.py,sha256=353w1JyvIinkr3aHjyT7I01utFM56lrgIjSSfqtJkA4,187
|
|
10
|
+
django_qstash/app/base.py,sha256=gM7GIJh_omZcxbmsrwAEadA-N6EuUJbPzh0CflOIVRg,3864
|
|
11
|
+
django_qstash/app/decorators.py,sha256=Gn0TAxUHfS4fKUdKdArvHeWlxrRvj9_NOVnC1a6pGTQ,732
|
|
10
12
|
django_qstash/discovery/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
13
|
django_qstash/discovery/fields.py,sha256=qZDKMpl6VMRJL0FkGwXkeN_rcCT32cupDaXJOz-bFzs,1226
|
|
12
14
|
django_qstash/discovery/models.py,sha256=9ml9lTKEqEKx2uqYvejZw_BjdnowgFOPE7rYNt_8E9A,685
|
|
13
|
-
django_qstash/discovery/utils.py,sha256=
|
|
15
|
+
django_qstash/discovery/utils.py,sha256=NxX6Y-Hd_AALgeESUW8AbIHReYPpbntvZjhlbrXTYnw,3224
|
|
14
16
|
django_qstash/discovery/validators.py,sha256=NNCf7ltW--sTw0w8FWwTp-4PtiS35U6DITEApx-D7X4,645
|
|
15
17
|
django_qstash/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
18
|
django_qstash/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
-
django_qstash/management/commands/clear_stale_results.py,sha256=
|
|
19
|
+
django_qstash/management/commands/clear_stale_results.py,sha256=mxXXqIy6pnvsN8JVE0xe3mypqtkaZbpqdBjpox-MDik,1402
|
|
18
20
|
django_qstash/management/commands/task_schedules.py,sha256=b9lJ1vjQKHyGzWAo9csGwE_oaKfgcSC8bPFLt9Ry6WE,4278
|
|
19
21
|
django_qstash/results/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
22
|
django_qstash/results/admin.py,sha256=q9fn3lfn0gviMfiimYij0wBCYww7FxyrOfGPr1NvntA,434
|
|
21
23
|
django_qstash/results/apps.py,sha256=4me4cg5yeoeSJTphkHYzGMJUfGucT47FNIUMYu5gmIo,275
|
|
22
24
|
django_qstash/results/models.py,sha256=aEiAhGJOuLRtjibUw6xdQqUt3eYKLqY2as4I4QSrF5U,1047
|
|
23
25
|
django_qstash/results/services.py,sha256=HvNp5D1tQ__nz4LVUTAGxuyLl_dnlBps4pJ6E9HD2kA,991
|
|
26
|
+
django_qstash/results/tasks.py,sha256=NETuiREwCKfajWKCnnB5iAsHoSsvBIThf805_wpzjbw,2166
|
|
24
27
|
django_qstash/results/migrations/0001_initial.py,sha256=A90SKgWmBf4SIJYG1Jh6-b_81Ia1zIzGj3Bfl1O4-kg,1902
|
|
25
28
|
django_qstash/results/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
29
|
django_qstash/schedules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -36,7 +39,7 @@ django_qstash/schedules/validators.py,sha256=i8IEjnRVk-iysmqvT_kbPYpxTKCQWoX9P1J
|
|
|
36
39
|
django_qstash/schedules/migrations/0001_initial.py,sha256=66cA8xnJV3h7QgzCaOiv-Nu3Xl9IdZQPgQKhxyW3bs4,4516
|
|
37
40
|
django_qstash/schedules/migrations/0002_taskschedule_updated_at.py,sha256=6hZO0a9P2ZpOROkk7O5UXBhahghU0QfxZl4E-c3HKGw,459
|
|
38
41
|
django_qstash/schedules/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
|
-
django_qstash-0.0.
|
|
40
|
-
django_qstash-0.0.
|
|
41
|
-
django_qstash-0.0.
|
|
42
|
-
django_qstash-0.0.
|
|
42
|
+
django_qstash-0.0.8.dist-info/METADATA,sha256=bK9_Xyk6YmMJZO1FF3L3mZTuOlXkUIU7azMroDV6IQY,12307
|
|
43
|
+
django_qstash-0.0.8.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
44
|
+
django_qstash-0.0.8.dist-info/top_level.txt,sha256=AlV3WSK1A0ZvKuCLsINtIJhJW8zo7SEB-D3_RAjZ0hI,14
|
|
45
|
+
django_qstash-0.0.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|