Skip to content

Commit 1e3f238

Browse files
Don't enforce UUIDs for task ids (#120)
Still used for DB backend, since it has some DB engine optimisations. The rest can be simple opaque strings
1 parent 80f22bc commit 1e3f238

File tree

5 files changed

+30
-6
lines changed

5 files changed

+30
-6
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ result_id = result.id
172172
calculate_meaning_of_life.get_result(result_id)
173173
```
174174

175+
A result `id` should be considered an opaque string, whose length could be up to 64 characters. ID generation is backend-specific.
176+
175177
Only tasks of the same type can be retrieved this way. To retrieve the result of any task, you can call `get_result` on the backend:
176178

177179
```python

django_tasks/backends/dummy.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from copy import deepcopy
22
from functools import partial
33
from typing import List, TypeVar
4-
from uuid import uuid4
54

65
from django.db import transaction
76
from django.utils import timezone
@@ -10,7 +9,7 @@
109
from django_tasks.exceptions import ResultDoesNotExist
1110
from django_tasks.signals import task_enqueued
1211
from django_tasks.task import ResultStatus, Task, TaskResult
13-
from django_tasks.utils import json_normalize
12+
from django_tasks.utils import get_random_id, json_normalize
1413

1514
from .base import BaseTaskBackend
1615

@@ -40,7 +39,7 @@ def enqueue(
4039

4140
result = TaskResult[T](
4241
task=task,
43-
id=str(uuid4()),
42+
id=get_random_id(),
4443
status=ResultStatus.NEW,
4544
enqueued_at=None,
4645
started_at=None,

django_tasks/backends/immediate.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
from functools import partial
33
from inspect import iscoroutinefunction
44
from typing import TypeVar
5-
from uuid import uuid4
65

76
from asgiref.sync import async_to_sync
87
from django.db import transaction
@@ -11,7 +10,7 @@
1110

1211
from django_tasks.signals import task_enqueued, task_finished
1312
from django_tasks.task import ResultStatus, Task, TaskResult
14-
from django_tasks.utils import exception_to_dict, json_normalize
13+
from django_tasks.utils import exception_to_dict, get_random_id, json_normalize
1514

1615
from .base import BaseTaskBackend
1716

@@ -74,7 +73,7 @@ def enqueue(
7473

7574
task_result = TaskResult[T](
7675
task=task,
77-
id=str(uuid4()),
76+
id=get_random_id(),
7877
status=ResultStatus.NEW,
7978
enqueued_at=None,
8079
started_at=None,

django_tasks/utils.py

+14
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import inspect
22
import json
3+
import random
34
import time
45
from functools import wraps
56
from traceback import format_exception
67
from typing import Any, Callable, List, TypedDict, TypeVar
78

9+
from django.utils.crypto import RANDOM_STRING_CHARS
810
from django.utils.module_loading import import_string
911
from typing_extensions import ParamSpec
1012

@@ -87,3 +89,15 @@ def exception_from_dict(exc_data: SerializedExceptionDict) -> BaseException:
8789
raise TypeError(f"{type(exc_class)} is not an exception")
8890

8991
return exc_class(*exc_data["exc_args"])
92+
93+
94+
def get_random_id() -> str:
95+
"""
96+
Return a random string for use as a task id.
97+
98+
Whilst 64 characters is the max, just use 32 as a sensible middle-ground.
99+
100+
This should be much faster than Django's `get_random_string`, since
101+
it's not cryptographically secure.
102+
"""
103+
return "".join(random.choices(RANDOM_STRING_CHARS, k=32))

tests/tests/test_utils.py

+10
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,13 @@ def test_cannot_deserialize_non_exception(self) -> None:
163163
with self.subTest(data):
164164
with self.assertRaises((TypeError, ImportError)):
165165
utils.exception_from_dict(data)
166+
167+
168+
class RandomIdTestCase(SimpleTestCase):
169+
def test_correct_length(self) -> None:
170+
self.assertEqual(len(utils.get_random_id()), 32)
171+
172+
def test_random_ish(self) -> None:
173+
random_ids = [utils.get_random_id() for _ in range(1000)]
174+
175+
self.assertEqual(len(random_ids), len(set(random_ids)))

0 commit comments

Comments
 (0)