djanquiltdb-plugin-celery 1.0.0__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.
- djanquiltdb_plugin_celery-1.0.0/CHANGELOG.rst +4 -0
- djanquiltdb_plugin_celery-1.0.0/LICENSE +23 -0
- djanquiltdb_plugin_celery-1.0.0/MANIFEST.in +19 -0
- djanquiltdb_plugin_celery-1.0.0/PKG-INFO +137 -0
- djanquiltdb_plugin_celery-1.0.0/README.rst +91 -0
- djanquiltdb_plugin_celery-1.0.0/pyproject.toml +99 -0
- djanquiltdb_plugin_celery-1.0.0/setup.cfg +4 -0
- djanquiltdb_plugin_celery-1.0.0/src/djanquiltdb_plugin_celery/__init__.py +52 -0
- djanquiltdb_plugin_celery-1.0.0/src/djanquiltdb_plugin_celery/checks.py +79 -0
- djanquiltdb_plugin_celery-1.0.0/src/djanquiltdb_plugin_celery/decorators.py +289 -0
- djanquiltdb_plugin_celery-1.0.0/src/djanquiltdb_plugin_celery/settings.py +75 -0
- djanquiltdb_plugin_celery-1.0.0/src/djanquiltdb_plugin_celery/targets.py +241 -0
- djanquiltdb_plugin_celery-1.0.0/src/djanquiltdb_plugin_celery/tasks.py +416 -0
- djanquiltdb_plugin_celery-1.0.0/src/djanquiltdb_plugin_celery/utils.py +178 -0
- djanquiltdb_plugin_celery-1.0.0/src/djanquiltdb_plugin_celery.egg-info/PKG-INFO +137 -0
- djanquiltdb_plugin_celery-1.0.0/src/djanquiltdb_plugin_celery.egg-info/SOURCES.txt +41 -0
- djanquiltdb_plugin_celery-1.0.0/src/djanquiltdb_plugin_celery.egg-info/dependency_links.txt +1 -0
- djanquiltdb_plugin_celery-1.0.0/src/djanquiltdb_plugin_celery.egg-info/entry_points.txt +2 -0
- djanquiltdb_plugin_celery-1.0.0/src/djanquiltdb_plugin_celery.egg-info/requires.txt +21 -0
- djanquiltdb_plugin_celery-1.0.0/src/djanquiltdb_plugin_celery.egg-info/top_level.txt +1 -0
- djanquiltdb_plugin_celery-1.0.0/tests/config/__init__.py +5 -0
- djanquiltdb_plugin_celery-1.0.0/tests/config/celery.py +5 -0
- djanquiltdb_plugin_celery-1.0.0/tests/config/settings.py +66 -0
- djanquiltdb_plugin_celery-1.0.0/tests/config/worker_check_settings.py +7 -0
- djanquiltdb_plugin_celery-1.0.0/tests/example/__init__.py +0 -0
- djanquiltdb_plugin_celery-1.0.0/tests/example/migrations/0001_initial.py +37 -0
- djanquiltdb_plugin_celery-1.0.0/tests/example/migrations/__init__.py +0 -0
- djanquiltdb_plugin_celery-1.0.0/tests/example/models.py +32 -0
- djanquiltdb_plugin_celery-1.0.0/tests/example/tasks.py +148 -0
- djanquiltdb_plugin_celery-1.0.0/tests/manage.py +10 -0
- djanquiltdb_plugin_celery-1.0.0/tests/plugin_tests/__init__.py +0 -0
- djanquiltdb_plugin_celery-1.0.0/tests/plugin_tests/base.py +50 -0
- djanquiltdb_plugin_celery-1.0.0/tests/plugin_tests/checks.py +138 -0
- djanquiltdb_plugin_celery-1.0.0/tests/plugin_tests/fan_out.py +505 -0
- djanquiltdb_plugin_celery-1.0.0/tests/plugin_tests/inheritance.py +324 -0
- djanquiltdb_plugin_celery-1.0.0/tests/plugin_tests/installation.py +79 -0
- djanquiltdb_plugin_celery-1.0.0/tests/plugin_tests/settings.py +35 -0
- djanquiltdb_plugin_celery-1.0.0/tests/plugin_tests/targets.py +457 -0
- djanquiltdb_plugin_celery-1.0.0/tests/plugin_tests/tasks.py +816 -0
- djanquiltdb_plugin_celery-1.0.0/tests/plugin_tests/worker.py +149 -0
- djanquiltdb_plugin_celery-1.0.0/tests/plugin_tests/worker_start.py +46 -0
- djanquiltdb_plugin_celery-1.0.0/tests/raising_check/__init__.py +5 -0
- djanquiltdb_plugin_celery-1.0.0/tests/raising_check/apps.py +21 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Copyright (c) 2026, DjanQuiltDB Project
|
|
2
|
+
|
|
3
|
+
Redistribution and use in source and binary forms, with or without
|
|
4
|
+
modification, are permitted provided that the following conditions are met:
|
|
5
|
+
* Redistributions of source code must retain the above copyright notice, this
|
|
6
|
+
list of conditions and the following disclaimer.
|
|
7
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
|
8
|
+
this list of conditions and the following disclaimer in the documentation
|
|
9
|
+
and/or other materials provided with the distribution.
|
|
10
|
+
* Neither the name of the copyright holder nor the names of its
|
|
11
|
+
contributors may be used to endorse or promote products derived from
|
|
12
|
+
this software without specific prior written permission.
|
|
13
|
+
|
|
14
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
15
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
16
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
17
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
18
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
19
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
20
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
21
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
22
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
23
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# The sdist is what downstream packagers build and test from, so it includes the whole test project, not just the
|
|
2
|
+
# importable package. Without the graft below, setuptools' defaults ship none of the fixture apps or settings that the
|
|
3
|
+
# suite imports, and the suite in the sdist cannot run.
|
|
4
|
+
#
|
|
5
|
+
# The documentation is not here: docs/ is at the repository root and covers the core library and the in-tree plugins
|
|
6
|
+
# together, so docs/ cannot be grafted into one package. The Documentation URL in pyproject.toml points to the
|
|
7
|
+
# documentation.
|
|
8
|
+
|
|
9
|
+
include CHANGELOG.rst
|
|
10
|
+
include LICENSE
|
|
11
|
+
include README.rst
|
|
12
|
+
|
|
13
|
+
graft tests
|
|
14
|
+
|
|
15
|
+
global-exclude *.py[cod]
|
|
16
|
+
global-exclude __pycache__
|
|
17
|
+
# A local test run leaves its coverage data in the test project; it is not part of the release.
|
|
18
|
+
global-exclude .coverage
|
|
19
|
+
global-exclude .coverage.*
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: djanquiltdb-plugin-celery
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Celery tasks that run in a shard, or once in every shard, of a DjanQuiltDB project
|
|
5
|
+
Author-email: DjanQuiltDB Project <djanquiltdb@portal42.net>
|
|
6
|
+
License-Expression: BSD-3-Clause
|
|
7
|
+
Project-URL: Homepage, https://github.com/DjanQuiltDB/djanquiltdb
|
|
8
|
+
Project-URL: Documentation, https://djanquiltdb.readthedocs.io/en/latest/plugins/celery/index.html
|
|
9
|
+
Project-URL: Source, https://github.com/DjanQuiltDB/djanquiltdb/tree/master/packages/djanquiltdb-plugin-celery
|
|
10
|
+
Project-URL: Issues, https://github.com/DjanQuiltDB/djanquiltdb/issues
|
|
11
|
+
Project-URL: Changelog, https://github.com/DjanQuiltDB/djanquiltdb/blob/master/packages/djanquiltdb-plugin-celery/CHANGELOG.rst
|
|
12
|
+
Keywords: django,database,sharding,postgresql,celery,tasks
|
|
13
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
14
|
+
Classifier: Environment :: Web Environment
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Framework :: Celery
|
|
21
|
+
Classifier: Framework :: Django
|
|
22
|
+
Classifier: Framework :: Django :: 6.0
|
|
23
|
+
Classifier: Framework :: Django :: 6.1
|
|
24
|
+
Classifier: Topic :: Database
|
|
25
|
+
Requires-Python: >=3.14
|
|
26
|
+
Description-Content-Type: text/x-rst
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: django<7.0,>=6.0
|
|
29
|
+
Requires-Dist: djanquiltdb<5.0,>=4.4
|
|
30
|
+
Requires-Dist: celery<6.0,>=5.6
|
|
31
|
+
Provides-Extra: lint
|
|
32
|
+
Requires-Dist: ruff==0.15.21; extra == "lint"
|
|
33
|
+
Provides-Extra: test
|
|
34
|
+
Requires-Dist: coverage; extra == "test"
|
|
35
|
+
Requires-Dist: psycopg[binary]>=3.0.0; extra == "test"
|
|
36
|
+
Requires-Dist: dj-database-url; extra == "test"
|
|
37
|
+
Provides-Extra: docs
|
|
38
|
+
Requires-Dist: sphinx<10,>=8; extra == "docs"
|
|
39
|
+
Provides-Extra: dev
|
|
40
|
+
Requires-Dist: djanquiltdb-plugin-celery[docs,lint,test]; extra == "dev"
|
|
41
|
+
Requires-Dist: pre-commit; extra == "dev"
|
|
42
|
+
Requires-Dist: tox>=4.21; extra == "dev"
|
|
43
|
+
Requires-Dist: build; extra == "dev"
|
|
44
|
+
Requires-Dist: twine; extra == "dev"
|
|
45
|
+
Dynamic: license-file
|
|
46
|
+
|
|
47
|
+
.. The logo needs an absolute URL: this README is the PyPI long description, where an image with a relative path does
|
|
48
|
+
not render.
|
|
49
|
+
|
|
50
|
+
.. image:: https://raw.githubusercontent.com/DjanQuiltDB/djanquiltdb/master/assets/icon-128.png
|
|
51
|
+
:alt: DjanQuiltDB
|
|
52
|
+
:width: 128
|
|
53
|
+
|
|
54
|
+
=========================
|
|
55
|
+
djanquiltdb-plugin-celery
|
|
56
|
+
=========================
|
|
57
|
+
|
|
58
|
+
.. image:: https://img.shields.io/pypi/v/djanquiltdb-plugin-celery.svg
|
|
59
|
+
:target: https://pypi.org/project/djanquiltdb-plugin-celery/
|
|
60
|
+
:alt: PyPI
|
|
61
|
+
|
|
62
|
+
.. image:: https://img.shields.io/pypi/pyversions/djanquiltdb-plugin-celery.svg
|
|
63
|
+
:target: https://pypi.org/project/djanquiltdb-plugin-celery/
|
|
64
|
+
:alt: Supported Python versions
|
|
65
|
+
|
|
66
|
+
.. image:: https://img.shields.io/pypi/frameworkversions/django/djanquiltdb-plugin-celery.svg
|
|
67
|
+
:target: https://pypi.org/project/djanquiltdb-plugin-celery/
|
|
68
|
+
:alt: Supported Django versions
|
|
69
|
+
|
|
70
|
+
.. image:: https://img.shields.io/badge/postgres-17%20%7C%2018-4169e1?logo=postgresql&logoColor=white
|
|
71
|
+
:target: https://www.postgresql.org/
|
|
72
|
+
:alt: Supported PostgreSQL versions
|
|
73
|
+
|
|
74
|
+
.. image:: https://github.com/DjanQuiltDB/djanquiltdb/actions/workflows/ci.yml/badge.svg
|
|
75
|
+
:target: https://github.com/DjanQuiltDB/djanquiltdb/actions/workflows/ci.yml
|
|
76
|
+
:alt: CI
|
|
77
|
+
|
|
78
|
+
.. image:: https://readthedocs.org/projects/djanquiltdb/badge/?version=latest
|
|
79
|
+
:target: https://djanquiltdb.readthedocs.io/en/latest/plugins/celery/index.html
|
|
80
|
+
:alt: Documentation
|
|
81
|
+
|
|
82
|
+
.. image:: https://img.shields.io/pypi/l/djanquiltdb-plugin-celery.svg
|
|
83
|
+
:target: https://github.com/DjanQuiltDB/djanquiltdb/blob/master/LICENSE
|
|
84
|
+
:alt: BSD-3-Clause licence
|
|
85
|
+
|
|
86
|
+
`DjanQuiltDB <https://github.com/djanquiltdb/djanquiltdb>`_ shards a database across schemas and nodes. This library
|
|
87
|
+
provides `Celery <https://docs.celeryq.dev/>`_ tasks that run in the shard that they are sent to, and that are retried
|
|
88
|
+
while that shard is in maintenance::
|
|
89
|
+
|
|
90
|
+
from djanquiltdb.decorators.celery import task_for_shard
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@task_for_shard
|
|
94
|
+
def send_invoice(invoice_id):
|
|
95
|
+
Invoice.objects.get(pk=invoice_id).send()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
send_invoice.for_shard(shard).delay(invoice_id=12)
|
|
99
|
+
send_invoice.delay(invoice_id=12, tenant_id=3)
|
|
100
|
+
|
|
101
|
+
A task that is decorated with ``task_for_node`` runs in the public schema of the node that its ``node_name`` identifies.
|
|
102
|
+
A task that is decorated with ``task_for_active_shard`` runs in the shard that is active where the task is sent. A task
|
|
103
|
+
that is decorated with ``task_for_every_shard`` runs once in every active shard when it is sent without a shard::
|
|
104
|
+
|
|
105
|
+
from djanquiltdb.decorators.celery import task_for_every_shard
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@task_for_every_shard(queue='fanout', spread=(0, 300))
|
|
109
|
+
def clean_up_drafts():
|
|
110
|
+
Draft.objects.filter(updated_at__lt=a_month_ago()).delete()
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
clean_up_drafts.delay()
|
|
114
|
+
|
|
115
|
+
Install the plugin through the ``celery`` extra of DjanQuiltDB::
|
|
116
|
+
|
|
117
|
+
pip install djanquiltdb[celery]
|
|
118
|
+
|
|
119
|
+
Full documentation is at https://djanquiltdb.readthedocs.io/en/latest/plugins/celery/index.html.
|
|
120
|
+
|
|
121
|
+
Development
|
|
122
|
+
===========
|
|
123
|
+
|
|
124
|
+
This package is developed in the `DjanQuiltDB repository <https://github.com/DjanQuiltDB/djanquiltdb>`_ beside
|
|
125
|
+
``djanquiltdb`` itself. Tests run through tox against the Postgres containers in the repository's
|
|
126
|
+
``docker-compose.yml``; see ``DOCKER.md`` at the repository root::
|
|
127
|
+
|
|
128
|
+
docker compose run --rm test tox
|
|
129
|
+
|
|
130
|
+
Requirements
|
|
131
|
+
------------
|
|
132
|
+
|
|
133
|
+
* Python 3.14
|
|
134
|
+
* Django 6.0 or 6.1
|
|
135
|
+
* PostgreSQL 17 or 18
|
|
136
|
+
* djanquiltdb 4.4.0 or newer 4.x
|
|
137
|
+
* Celery 5.6 or newer 5.x
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
.. The logo needs an absolute URL: this README is the PyPI long description, where an image with a relative path does
|
|
2
|
+
not render.
|
|
3
|
+
|
|
4
|
+
.. image:: https://raw.githubusercontent.com/DjanQuiltDB/djanquiltdb/master/assets/icon-128.png
|
|
5
|
+
:alt: DjanQuiltDB
|
|
6
|
+
:width: 128
|
|
7
|
+
|
|
8
|
+
=========================
|
|
9
|
+
djanquiltdb-plugin-celery
|
|
10
|
+
=========================
|
|
11
|
+
|
|
12
|
+
.. image:: https://img.shields.io/pypi/v/djanquiltdb-plugin-celery.svg
|
|
13
|
+
:target: https://pypi.org/project/djanquiltdb-plugin-celery/
|
|
14
|
+
:alt: PyPI
|
|
15
|
+
|
|
16
|
+
.. image:: https://img.shields.io/pypi/pyversions/djanquiltdb-plugin-celery.svg
|
|
17
|
+
:target: https://pypi.org/project/djanquiltdb-plugin-celery/
|
|
18
|
+
:alt: Supported Python versions
|
|
19
|
+
|
|
20
|
+
.. image:: https://img.shields.io/pypi/frameworkversions/django/djanquiltdb-plugin-celery.svg
|
|
21
|
+
:target: https://pypi.org/project/djanquiltdb-plugin-celery/
|
|
22
|
+
:alt: Supported Django versions
|
|
23
|
+
|
|
24
|
+
.. image:: https://img.shields.io/badge/postgres-17%20%7C%2018-4169e1?logo=postgresql&logoColor=white
|
|
25
|
+
:target: https://www.postgresql.org/
|
|
26
|
+
:alt: Supported PostgreSQL versions
|
|
27
|
+
|
|
28
|
+
.. image:: https://github.com/DjanQuiltDB/djanquiltdb/actions/workflows/ci.yml/badge.svg
|
|
29
|
+
:target: https://github.com/DjanQuiltDB/djanquiltdb/actions/workflows/ci.yml
|
|
30
|
+
:alt: CI
|
|
31
|
+
|
|
32
|
+
.. image:: https://readthedocs.org/projects/djanquiltdb/badge/?version=latest
|
|
33
|
+
:target: https://djanquiltdb.readthedocs.io/en/latest/plugins/celery/index.html
|
|
34
|
+
:alt: Documentation
|
|
35
|
+
|
|
36
|
+
.. image:: https://img.shields.io/pypi/l/djanquiltdb-plugin-celery.svg
|
|
37
|
+
:target: https://github.com/DjanQuiltDB/djanquiltdb/blob/master/LICENSE
|
|
38
|
+
:alt: BSD-3-Clause licence
|
|
39
|
+
|
|
40
|
+
`DjanQuiltDB <https://github.com/djanquiltdb/djanquiltdb>`_ shards a database across schemas and nodes. This library
|
|
41
|
+
provides `Celery <https://docs.celeryq.dev/>`_ tasks that run in the shard that they are sent to, and that are retried
|
|
42
|
+
while that shard is in maintenance::
|
|
43
|
+
|
|
44
|
+
from djanquiltdb.decorators.celery import task_for_shard
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@task_for_shard
|
|
48
|
+
def send_invoice(invoice_id):
|
|
49
|
+
Invoice.objects.get(pk=invoice_id).send()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
send_invoice.for_shard(shard).delay(invoice_id=12)
|
|
53
|
+
send_invoice.delay(invoice_id=12, tenant_id=3)
|
|
54
|
+
|
|
55
|
+
A task that is decorated with ``task_for_node`` runs in the public schema of the node that its ``node_name`` identifies.
|
|
56
|
+
A task that is decorated with ``task_for_active_shard`` runs in the shard that is active where the task is sent. A task
|
|
57
|
+
that is decorated with ``task_for_every_shard`` runs once in every active shard when it is sent without a shard::
|
|
58
|
+
|
|
59
|
+
from djanquiltdb.decorators.celery import task_for_every_shard
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@task_for_every_shard(queue='fanout', spread=(0, 300))
|
|
63
|
+
def clean_up_drafts():
|
|
64
|
+
Draft.objects.filter(updated_at__lt=a_month_ago()).delete()
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
clean_up_drafts.delay()
|
|
68
|
+
|
|
69
|
+
Install the plugin through the ``celery`` extra of DjanQuiltDB::
|
|
70
|
+
|
|
71
|
+
pip install djanquiltdb[celery]
|
|
72
|
+
|
|
73
|
+
Full documentation is at https://djanquiltdb.readthedocs.io/en/latest/plugins/celery/index.html.
|
|
74
|
+
|
|
75
|
+
Development
|
|
76
|
+
===========
|
|
77
|
+
|
|
78
|
+
This package is developed in the `DjanQuiltDB repository <https://github.com/DjanQuiltDB/djanquiltdb>`_ beside
|
|
79
|
+
``djanquiltdb`` itself. Tests run through tox against the Postgres containers in the repository's
|
|
80
|
+
``docker-compose.yml``; see ``DOCKER.md`` at the repository root::
|
|
81
|
+
|
|
82
|
+
docker compose run --rm test tox
|
|
83
|
+
|
|
84
|
+
Requirements
|
|
85
|
+
------------
|
|
86
|
+
|
|
87
|
+
* Python 3.14
|
|
88
|
+
* Django 6.0 or 6.1
|
|
89
|
+
* PostgreSQL 17 or 18
|
|
90
|
+
* djanquiltdb 4.4.0 or newer 4.x
|
|
91
|
+
* Celery 5.6 or newer 5.x
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
# The PEP 639 license expression below needs setuptools 77, which is also new enough that `wheel` does not have to be
|
|
3
|
+
# declared here.
|
|
4
|
+
requires = ["setuptools>=77"]
|
|
5
|
+
build-backend = "setuptools.build_meta"
|
|
6
|
+
|
|
7
|
+
[project]
|
|
8
|
+
name = "djanquiltdb-plugin-celery"
|
|
9
|
+
dynamic = ["version"]
|
|
10
|
+
description = "Celery tasks that run in a shard, or once in every shard, of a DjanQuiltDB project"
|
|
11
|
+
readme = "README.rst"
|
|
12
|
+
requires-python = ">=3.14"
|
|
13
|
+
license = "BSD-3-Clause"
|
|
14
|
+
license-files = ["LICENSE"]
|
|
15
|
+
authors = [
|
|
16
|
+
{ name = "DjanQuiltDB Project", email = "djanquiltdb@portal42.net" },
|
|
17
|
+
]
|
|
18
|
+
keywords = [
|
|
19
|
+
"django",
|
|
20
|
+
"database",
|
|
21
|
+
"sharding",
|
|
22
|
+
"postgresql",
|
|
23
|
+
"celery",
|
|
24
|
+
"tasks",
|
|
25
|
+
]
|
|
26
|
+
classifiers = [
|
|
27
|
+
"Development Status :: 5 - Production/Stable",
|
|
28
|
+
"Environment :: Web Environment",
|
|
29
|
+
"Intended Audience :: Developers",
|
|
30
|
+
"Operating System :: OS Independent",
|
|
31
|
+
"Programming Language :: Python",
|
|
32
|
+
"Programming Language :: Python :: 3",
|
|
33
|
+
"Programming Language :: Python :: 3.14",
|
|
34
|
+
"Framework :: Celery",
|
|
35
|
+
"Framework :: Django",
|
|
36
|
+
"Framework :: Django :: 6.0",
|
|
37
|
+
"Framework :: Django :: 6.1",
|
|
38
|
+
"Topic :: Database",
|
|
39
|
+
]
|
|
40
|
+
dependencies = [
|
|
41
|
+
"django>=6.0,<7.0",
|
|
42
|
+
# 4.4 enters a shard id or a mapping value of 0, and reads the shard again once use_shard holds its lock, so that a
|
|
43
|
+
# task that is retried during a move does not enter the shard where it was before the move.
|
|
44
|
+
"djanquiltdb>=4.4,<5.0",
|
|
45
|
+
# 5.6 is the first release that supports Python 3.14. QuiltTask, the task class of the plugin, subclasses
|
|
46
|
+
# celery.contrib.django.task.DjangoTask and relies on Celery passing custom message headers on to
|
|
47
|
+
# task.request.headers, so a new major version has to be checked before the upper bound is raised.
|
|
48
|
+
"celery>=5.6,<6.0",
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
[project.entry-points."djanquiltdb.plugins"]
|
|
52
|
+
celery = "djanquiltdb_plugin_celery:plugin"
|
|
53
|
+
|
|
54
|
+
[project.urls]
|
|
55
|
+
Homepage = "https://github.com/DjanQuiltDB/djanquiltdb"
|
|
56
|
+
Documentation = "https://djanquiltdb.readthedocs.io/en/latest/plugins/celery/index.html"
|
|
57
|
+
Source = "https://github.com/DjanQuiltDB/djanquiltdb/tree/master/packages/djanquiltdb-plugin-celery"
|
|
58
|
+
Issues = "https://github.com/DjanQuiltDB/djanquiltdb/issues"
|
|
59
|
+
Changelog = "https://github.com/DjanQuiltDB/djanquiltdb/blob/master/packages/djanquiltdb-plugin-celery/CHANGELOG.rst"
|
|
60
|
+
|
|
61
|
+
[project.optional-dependencies]
|
|
62
|
+
lint = [
|
|
63
|
+
"ruff==0.15.21",
|
|
64
|
+
]
|
|
65
|
+
test = [
|
|
66
|
+
"coverage",
|
|
67
|
+
"psycopg[binary]>=3.0.0",
|
|
68
|
+
"dj-database-url",
|
|
69
|
+
]
|
|
70
|
+
docs = [
|
|
71
|
+
"sphinx>=8,<10",
|
|
72
|
+
]
|
|
73
|
+
dev = [
|
|
74
|
+
"djanquiltdb-plugin-celery[test,lint,docs]",
|
|
75
|
+
"pre-commit",
|
|
76
|
+
# 4.21 is the first release with native TOML configuration, so that tox.ini is not needed.
|
|
77
|
+
"tox>=4.21",
|
|
78
|
+
"build",
|
|
79
|
+
"twine",
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
[tool.setuptools.dynamic]
|
|
83
|
+
version = { attr = "djanquiltdb_plugin_celery.__version__" }
|
|
84
|
+
|
|
85
|
+
[tool.setuptools.packages.find]
|
|
86
|
+
where = ["src"]
|
|
87
|
+
|
|
88
|
+
[tool.coverage.run]
|
|
89
|
+
source = ["djanquiltdb_plugin_celery"]
|
|
90
|
+
branch = true
|
|
91
|
+
|
|
92
|
+
[tool.coverage.report]
|
|
93
|
+
show_missing = true
|
|
94
|
+
fail_under = 100
|
|
95
|
+
|
|
96
|
+
# The shared settings are in ruff.toml at the repository root, and only the src roots are set per package.
|
|
97
|
+
[tool.ruff]
|
|
98
|
+
extend = "../../ruff.toml"
|
|
99
|
+
src = ["src", "tests"]
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This package defines the plugin object, which DjanQuiltDB finds through the ``djanquiltdb.plugins`` entry-point group,
|
|
3
|
+
and exports the public API of the plugin. DjanQuiltDB serves the decorators as ``djanquiltdb.decorators.celery``, and
|
|
4
|
+
the helpers as ``djanquiltdb.utils.celery``.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from types import SimpleNamespace
|
|
8
|
+
|
|
9
|
+
from djanquiltdb_plugin_celery import decorators, utils
|
|
10
|
+
from djanquiltdb_plugin_celery.decorators import (
|
|
11
|
+
task_for_active_shard,
|
|
12
|
+
task_for_every_node,
|
|
13
|
+
task_for_every_shard,
|
|
14
|
+
task_for_node,
|
|
15
|
+
task_for_shard,
|
|
16
|
+
)
|
|
17
|
+
from djanquiltdb_plugin_celery.utils import (
|
|
18
|
+
aggregate_per_shard,
|
|
19
|
+
fan_out,
|
|
20
|
+
fan_out_to_nodes,
|
|
21
|
+
fanout_shards,
|
|
22
|
+
per_node_signatures,
|
|
23
|
+
per_shard_signatures,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
__version__ = '1.0.0'
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def install():
|
|
30
|
+
"""
|
|
31
|
+
Registers the plugin's system checks. DjanQuiltDB calls install() once the app registry is ready.
|
|
32
|
+
"""
|
|
33
|
+
from djanquiltdb_plugin_celery import checks # noqa: F401
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
plugin = SimpleNamespace(decorators=decorators, utils=utils, install=install)
|
|
37
|
+
|
|
38
|
+
__all__ = [
|
|
39
|
+
'aggregate_per_shard',
|
|
40
|
+
'fan_out',
|
|
41
|
+
'fan_out_to_nodes',
|
|
42
|
+
'fanout_shards',
|
|
43
|
+
'install',
|
|
44
|
+
'per_node_signatures',
|
|
45
|
+
'per_shard_signatures',
|
|
46
|
+
'plugin',
|
|
47
|
+
'task_for_active_shard',
|
|
48
|
+
'task_for_every_node',
|
|
49
|
+
'task_for_every_shard',
|
|
50
|
+
'task_for_node',
|
|
51
|
+
'task_for_shard',
|
|
52
|
+
]
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from django.conf import settings
|
|
2
|
+
from django.core import checks
|
|
3
|
+
from djanquiltdb.utils import get_mapping_class
|
|
4
|
+
|
|
5
|
+
from djanquiltdb_plugin_celery.settings import (
|
|
6
|
+
QUEUE_DESCRIPTION,
|
|
7
|
+
QUILT_CELERY_DEFAULTS,
|
|
8
|
+
SPREAD_DESCRIPTION,
|
|
9
|
+
is_spread,
|
|
10
|
+
)
|
|
11
|
+
from djanquiltdb_plugin_celery.targets import NODE_NAME_KWARG, SHARD_ID_KWARG
|
|
12
|
+
|
|
13
|
+
#: For each key of QUILT_CELERY: a function that returns whether a value of the key is valid, and how a message
|
|
14
|
+
#: describes the valid values. A boolean is an instance of int, so the keys that accept an integer and not a boolean
|
|
15
|
+
#: exclude it.
|
|
16
|
+
QUILT_CELERY_VALIDATORS = {
|
|
17
|
+
'MAPPING_KWARG': (lambda value: isinstance(value, (str, type(None))), 'a string or None'),
|
|
18
|
+
'MAX_RETRIES': (
|
|
19
|
+
lambda value: value is None or (isinstance(value, int) and not isinstance(value, bool)),
|
|
20
|
+
'an integer or None',
|
|
21
|
+
),
|
|
22
|
+
'RETRY_BACKOFF': (lambda value: isinstance(value, (bool, int)), 'a boolean or an integer'),
|
|
23
|
+
'RETRY_BACKOFF_MAX': (lambda value: isinstance(value, int) and not isinstance(value, bool), 'an integer'),
|
|
24
|
+
'RETRY_JITTER': (lambda value: isinstance(value, bool), 'a boolean'),
|
|
25
|
+
'FANOUT_QUEUE': (lambda value: isinstance(value, (str, type(None))), QUEUE_DESCRIPTION),
|
|
26
|
+
'FANOUT_SPREAD': (is_spread, SPREAD_DESCRIPTION),
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@checks.register(checks.Tags.compatibility)
|
|
31
|
+
def check_quilt_celery_setting(app_configs, **kwargs):
|
|
32
|
+
"""
|
|
33
|
+
Reports a QUILT_CELERY setting, key or value that the celery plugin cannot use.
|
|
34
|
+
"""
|
|
35
|
+
quilt_celery = getattr(settings, 'QUILT_CELERY', {})
|
|
36
|
+
|
|
37
|
+
if not isinstance(quilt_celery, dict):
|
|
38
|
+
return [checks.Error('QUILT_CELERY is not a dict.', id='djanquiltdb_plugin_celery.E002')]
|
|
39
|
+
|
|
40
|
+
messages = [
|
|
41
|
+
checks.Error(
|
|
42
|
+
'QUILT_CELERY has the key {!r}, which the celery plugin does not read.'.format(name),
|
|
43
|
+
hint='The plugin reads the keys {}.'.format(', '.join(QUILT_CELERY_DEFAULTS)),
|
|
44
|
+
id='djanquiltdb_plugin_celery.E001',
|
|
45
|
+
)
|
|
46
|
+
for name in quilt_celery
|
|
47
|
+
if name not in QUILT_CELERY_DEFAULTS
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
for name, (is_valid, description) in QUILT_CELERY_VALIDATORS.items():
|
|
51
|
+
if name in quilt_celery and not is_valid(quilt_celery[name]):
|
|
52
|
+
messages.append(
|
|
53
|
+
checks.Error(
|
|
54
|
+
"QUILT_CELERY['{}'] is {!r}, and it accepts {}.".format(name, quilt_celery[name], description),
|
|
55
|
+
id='djanquiltdb_plugin_celery.E002',
|
|
56
|
+
)
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
if quilt_celery.get('MAPPING_KWARG') in (SHARD_ID_KWARG, NODE_NAME_KWARG):
|
|
60
|
+
messages.append(
|
|
61
|
+
checks.Error(
|
|
62
|
+
"QUILT_CELERY['MAPPING_KWARG'] is {!r}, which already identifies a target in another way.".format(
|
|
63
|
+
quilt_celery['MAPPING_KWARG']
|
|
64
|
+
),
|
|
65
|
+
hint='Set it to the keyword argument that has the mapping value, such as tenant_id.',
|
|
66
|
+
id='djanquiltdb_plugin_celery.E002',
|
|
67
|
+
)
|
|
68
|
+
)
|
|
69
|
+
elif quilt_celery.get('MAPPING_KWARG') and get_mapping_class() is None:
|
|
70
|
+
messages.append(
|
|
71
|
+
checks.Error(
|
|
72
|
+
"QUILT_CELERY['MAPPING_KWARG'] is {!r}, but QUILT_DB has no MAPPING_MODEL in which a task can look up "
|
|
73
|
+
'the shard of a mapping value.'.format(quilt_celery['MAPPING_KWARG']),
|
|
74
|
+
hint="Set QUILT_DB['MAPPING_MODEL'], or remove QUILT_CELERY['MAPPING_KWARG'].",
|
|
75
|
+
id='djanquiltdb_plugin_celery.E002',
|
|
76
|
+
)
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
return messages
|