Skip to content

Commit fdcd88a

Browse files
authored
Merge pull request #35 from octue/feature/disable-enqueueing-task-using-setting
Disable enqueueing task using setting
2 parents 3b74a08 + 40afc31 commit fdcd88a

File tree

6 files changed

+75
-7
lines changed

6 files changed

+75
-7
lines changed

django_gcp/exceptions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,7 @@ class AttemptedOverwriteError(Exception):
3636

3737
class MissingBlobError(Exception):
3838
"""Raised when attempting to access or copy a blob that is not present in GCS"""
39+
40+
41+
class IncompatibleSettingsError(ValueError):
42+
"""Raised when settings values are mutually exclusive"""

django_gcp/tasks/manager.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ def delimiter(self):
4949
"""Return the GCP_TASKS_DELIMITER setting or a default"""
5050
return getattr(settings, "GCP_TASKS_DELIMITER", "--")
5151

52+
@property
53+
def disable_execute(self):
54+
"""Return the GCP_TASKS_DISABLE_EXECUTE setting or default False"""
55+
return getattr(settings, "GCP_TASKS_DISABLE_EXECUTE", False)
56+
5257
@property
5358
def domain(self):
5459
"""Return the GCP_TASKS_DOMAIN setting or a default"""

django_gcp/tasks/tasks.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from django.urls import reverse
1212
from django.utils.timezone import now
1313
from django_gcp.events.utils import decode_pubsub_message
14-
from django_gcp.exceptions import DuplicateTaskError, IncorrectTaskUsageError
14+
from django_gcp.exceptions import DuplicateTaskError, IncompatibleSettingsError, IncorrectTaskUsageError
1515
from gcp_pilot.pubsub import CloudPublisher, CloudSubscriber
1616
from google.api_core.exceptions import AlreadyExists
1717
from google.cloud import pubsub_v1
@@ -83,13 +83,19 @@ class Task(metaclass=TaskMeta):
8383
deduplicate = False
8484

8585
def enqueue(self, **kwargs):
86-
"""Invoke a task (place it onto a queue for processing)"""
86+
"""Invoke a task (place it onto a queue for processing)
87+
88+
Some settings affect the behaviour of this method, allowing bypass or immediate execution. See settings documentation for more.
89+
"""
8790
return self._send(
8891
task_kwargs=kwargs,
8992
)
9093

9194
def enqueue_later(self, when, **kwargs):
92-
"""Invoke a task (place it onto a queue for processing after some time delay)"""
95+
"""Invoke a task (place it onto a queue for processing after some time delay)
96+
97+
Some settings affect the behaviour of this method, allowing bypass or immediate execution. See settings documentation for more.
98+
"""
9399
if isinstance(when, int):
94100
delay_in_seconds = when
95101
elif isinstance(when, timedelta):
@@ -163,6 +169,12 @@ def _body_to_kwargs(self, request_body):
163169
# interacting with Cloud Tasks, like the following _send method
164170

165171
def _send(self, task_kwargs, api_kwargs=None):
172+
if self.manager.disable_execute and self.manager.eager_execute:
173+
raise IncompatibleSettingsError("disable_execute and eager_execute should be mutually exclusive")
174+
175+
if self.manager.disable_execute:
176+
return None
177+
166178
payload = serialize(task_kwargs)
167179
if self.manager.eager_execute:
168180
return self.run(**deserialize(payload))

docs/source/tasks_settings.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,18 @@ If set to true, tasks will synchronously execute when their ``enqueue()`` method
8787
8888
Whilst not generally useful in production, this can be quite helpful for straightforward
8989
debugging of tasks in local environments.
90+
91+
92+
``GCP_TASKS_DISABLE_EXECUTE``
93+
-----------------------------
94+
Type: ``boolean``
95+
96+
Default: ``False``
97+
98+
If set to true, tasks will not be enqueued for processing when their ``enqueue()`` or ``enqueue_later()``
99+
methods are called. Instead, the method will simply return None without enqueuing the task, allowing for the
100+
disabling of task execution. This can be useful in scenarios where tasks need to be temporarily disabled or
101+
when testing/debugging task code.
102+
103+
It is important to note that this setting only affect tasks when their ``enqueue()`` or ``enqueue_later()``
104+
methods are called and that tasks can still be executed manually even if this setting is set to True.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "django-gcp"
3-
version = "0.9.1"
3+
version = "0.9.2"
44
description = "Utilities to run Django on Google Cloud Platform"
55
authors = ["Tom Clark"]
66
license = "MIT"

tests/test_tasks_enqueuing.py

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,21 @@
88

99
import json
1010
from unittest.mock import patch
11-
from django.test import SimpleTestCase
11+
from django.test import SimpleTestCase, override_settings
1212
from django.urls import reverse
1313
from django_gcp.events.utils import make_pubsub_message
14-
from django_gcp.exceptions import DuplicateTaskError, IncorrectTaskUsageError
14+
from django_gcp.exceptions import DuplicateTaskError, IncompatibleSettingsError, IncorrectTaskUsageError
1515
from django_gcp.tasks import OnDemandTask
1616
from gcp_pilot.mocker import patch_auth
1717
from google.api_core.exceptions import AlreadyExists
1818

19-
from tests.server.example.tasks import DeduplicatedOnDemandTask, MyOnDemandTask
19+
from tests.server.example.tasks import (
20+
DeduplicatedOnDemandTask,
21+
FailingOnDemandTask,
22+
MyOnDemandTask,
23+
MyPeriodicTask,
24+
MySubscriberTask,
25+
)
2026
from .test_events_utils import DEFAULT_SUBSCRIPTION
2127

2228

@@ -79,3 +85,29 @@ def test_failing_on_demand_task_returns_error(self):
7985

8086
self.assertEqual(500, response.status_code)
8187
self.assertIn("error", response.json())
88+
89+
def test_disable_enqueueing_with_a_setting(self):
90+
"""Assert that no task is enqueued if the GCP_TASKS_DISABLE_EXECUTE is true"""
91+
with patch_auth():
92+
with patch("django_gcp.tasks.tasks.run_coroutine") as patched_send:
93+
MyOnDemandTask().enqueue(a="1")
94+
self.assertEqual(patched_send.call_count, 1)
95+
96+
with override_settings(GCP_TASKS_DISABLE_EXECUTE=True):
97+
MyOnDemandTask().enqueue(a="1")
98+
MyPeriodicTask().enqueue(a="1")
99+
MySubscriberTask().enqueue(a="1")
100+
FailingOnDemandTask().enqueue(a="1")
101+
102+
self.assertEqual(patched_send.call_count, 1)
103+
104+
MyOnDemandTask().enqueue_later(a="1", when=10)
105+
MyPeriodicTask().enqueue_later(a="1", when=10)
106+
MySubscriberTask().enqueue_later(a="1", when=10)
107+
FailingOnDemandTask().enqueue_later(a="1", when=10)
108+
109+
self.assertEqual(patched_send.call_count, 1)
110+
111+
with override_settings(GCP_TASKS_DISABLE_EXECUTE=True, GCP_TASKS_EAGER_EXECUTE=True):
112+
with self.assertRaises(IncompatibleSettingsError):
113+
MyOnDemandTask().enqueue(a="1")

0 commit comments

Comments
 (0)