Skip to content

Commit c82a8d9

Browse files
committed
add basic support for django_tasks
1 parent 2e4af47 commit c82a8d9

File tree

5 files changed

+127
-3
lines changed

5 files changed

+127
-3
lines changed

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ manage:
4444
bot:
4545
$(DEV_CMD) run_bot
4646

47+
worker:
48+
$(DEV_CMD) db_worker -v 2
49+
4750

4851
# Test, lint, etc
4952
# ================

intbot/.env.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
DISCORD_BOT_TOKEN='asdf'
2+
DISCORD_TEST_CHANNEL_ID="123123123123123123123123"
3+
DISCORD_TEST_CHANNEL_NAME="#test-channel"

intbot/core/tasks.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from django.conf import settings
2+
3+
from core.models import DiscordMessage, Webhook
4+
from django.utils import timezone
5+
from django_tasks import task
6+
7+
8+
@task
9+
def process_webhook(wh_uuid: str):
10+
wh = Webhook.objects.get(uuid=wh_uuid)
11+
12+
if wh.source == "internal":
13+
process_internal_webhook(wh)
14+
15+
else:
16+
raise ValueError(f"Unsupported source {wh.source}")
17+
18+
19+
def process_internal_webhook(wh: Webhook):
20+
if wh.source != "internal":
21+
raise ValueError("Incorrect wh.source = {wh.source}")
22+
23+
DiscordMessage.objects.create(
24+
channel_id=settings.DISCORD_TEST_CHANNEL_ID,
25+
channel_name=settings.DISCORD_TEST_CHANNEL_NAME,
26+
content=f"Webhook content: {wh.content}",
27+
# Mark as unsend - to be sent with the next batch
28+
sent_at=None,
29+
)
30+
wh.processed_at = timezone.now()
31+
wh.save()

intbot/intbot/settings.py

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
"django.contrib.staticfiles",
2929
# Third party apps
3030
"django_extensions",
31+
"django_tasks",
32+
"django_tasks.backends.database",
3133
# Project apps
3234
"core",
3335
]
@@ -127,6 +129,12 @@
127129
}
128130
}
129131

132+
TASKS = {
133+
"default": {
134+
"BACKEND": "django_tasks.backends.database.DatabaseBackend",
135+
}
136+
}
137+
130138
WEBHOOK_INTERNAL_TOKEN = "dev-token"
131139

132140
# This is only needed if you end up running the bot locally, hence it
@@ -135,9 +143,16 @@
135143
# one from the developer portal.
136144
# If you run it locally, you probably want to run it against your own test
137145
# bot and a test server.
138-
DISCORD_BOT_TOKEN = os.environ.get("DISCORD_BOT_TOKEN", "")
139-
if not DISCORD_BOT_TOKEN:
140-
warnings.warn("DISCORD_BOT_TOKEN not set")
146+
147+
def warn_if_missing(name, default=""):
148+
value = os.environ.get(name, default)
149+
if not value:
150+
warnings.warn(f"{name} not set")
151+
152+
DISCORD_TEST_CHANNEL_ID = warn_if_missing("DISCORD_TEST_CHANNEL_ID", "")
153+
DISCORD_TEST_CHANNEL_NAME = warn_if_missing("DISCORD_TEST_CHANNEL_NAME", "")
154+
DISCORD_BOT_TOKEN = warn_if_missing("DISCORD_BOT_TOKEN", "")
155+
141156

142157
elif DJANGO_ENV == "test":
143158
DEBUG = True
@@ -158,6 +173,22 @@
158173

159174
WEBHOOK_INTERNAL_TOKEN = "test-random-token"
160175

176+
TASKS = {
177+
"default": {
178+
"BACKEND": "django_tasks.backends.immediate.ImmediateBackend",
179+
# This setting doesn't really make sense in this context, but it
180+
# makes it work in the test environment...
181+
# TODO(artcz): Let's figure out later why.
182+
# NOTE: in django-tasks tests the test harness seem to be quite
183+
# different so maybe there's also something we can check in the
184+
# library itself.
185+
"ENQUEUE_ON_COMMIT": False,
186+
}
187+
}
188+
189+
DISCORD_TEST_CHANNEL_ID = "12345"
190+
DISCORD_TEST_CHANNEL_NAME = "#test-channel"
191+
161192

162193
elif DJANGO_ENV == "local_container":
163194
DEBUG = False
@@ -179,6 +210,12 @@
179210
}
180211
}
181212

213+
TASKS = {
214+
"default": {
215+
"BACKEND": "django_tasks.backends.database.DatabaseBackend",
216+
}
217+
}
218+
182219
# For 500 errors to appear on stderr
183220
LOGGING = {
184221
"version": 1,
@@ -220,6 +257,12 @@
220257
}
221258
}
222259

260+
TASKS = {
261+
"default": {
262+
"BACKEND": "django_tasks.backends.database.DatabaseBackend",
263+
}
264+
}
265+
223266
# For 500 errors to appear on stderr
224267
# For now it's good for docker, in the future sentry/or rollabar should be
225268
# here
@@ -242,6 +285,8 @@
242285
}
243286

244287
DISCORD_BOT_TOKEN = os.environ["DISCORD_BOT_TOKEN"]
288+
DISCORD_TEST_CHANNEL_ID = os.environ["DISCORD_TEST_CHANNEL_ID"]
289+
DISCORD_TEST_CHANNEL_NAME = os.environ["DISCORD_TEST_CHANNEL_NAME"]
245290

246291
CSRF_TRUSTED_ORIGINS = [
247292
"https://internal.europython.eu",

intbot/tests/test_tasks.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import pytest
2+
from core.models import DiscordMessage, Webhook
3+
from core.tasks import process_internal_webhook, process_webhook
4+
from django_tasks.task import ResultStatus
5+
6+
7+
@pytest.mark.django_db
8+
def test_process_internal_webhook_handles_internal_webhook_correctly():
9+
wh = Webhook.objects.create(
10+
source="internal",
11+
event="test1",
12+
content={
13+
"random": "content",
14+
},
15+
)
16+
17+
process_internal_webhook(wh)
18+
19+
dm = DiscordMessage.objects.get()
20+
assert dm.content == "Webhook content: {'random': 'content'}"
21+
assert dm.channel_id == "12345"
22+
assert dm.channel_name == "#test-channel"
23+
24+
25+
@pytest.mark.django_db
26+
def test_process_internal_webhook_fails_if_incorrect_source():
27+
wh = Webhook(source="asdf")
28+
29+
with pytest.raises(ValueError):
30+
process_internal_webhook(wh)
31+
32+
33+
@pytest.mark.django_db
34+
def test_process_webhook_fails_if_unsupported_source(caplog):
35+
wh = Webhook.objects.create(source="asdf", event="test1", content={})
36+
37+
# If the task is enqueued the errors are not emited.
38+
# Instead we have to check the result
39+
result = process_webhook.enqueue(str(wh.uuid))
40+
41+
assert result.status == ResultStatus.FAILED
42+
assert result._exception_class == ValueError
43+
assert result.traceback.endswith("ValueError: Unsupported source asdf\n")

0 commit comments

Comments
 (0)