aa-killtracker 0.17.0__py3-none-any.whl → 1.0.0__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.
- {aa_killtracker-0.17.0.dist-info → aa_killtracker-1.0.0.dist-info}/METADATA +7 -8
- {aa_killtracker-0.17.0.dist-info → aa_killtracker-1.0.0.dist-info}/RECORD +36 -29
- killtracker/__init__.py +1 -1
- killtracker/admin.py +13 -8
- killtracker/app_settings.py +20 -10
- killtracker/apps.py +2 -4
- killtracker/core/discord.py +162 -0
- killtracker/core/helpers.py +13 -0
- killtracker/core/{discord_messages.py → trackers.py} +74 -59
- killtracker/core/workers.py +46 -0
- killtracker/core/{killmails.py → zkb.py} +97 -72
- killtracker/forms.py +1 -1
- killtracker/managers.py +3 -3
- killtracker/models/trackers.py +7 -10
- killtracker/models/webhooks.py +60 -128
- killtracker/providers.py +1 -1
- killtracker/signals.py +31 -0
- killtracker/tasks.py +141 -92
- killtracker/tests/core/test_discord.py +184 -0
- killtracker/tests/core/test_helpers.py +23 -0
- killtracker/tests/core/{test_discord_messages_1.py → test_tracker_1.py} +28 -8
- killtracker/tests/core/{test_discord_messages_2.py → test_tracker_2.py} +11 -11
- killtracker/tests/core/test_workers.py +49 -0
- killtracker/tests/core/{test_killmails.py → test_zkb.py} +109 -52
- killtracker/tests/models/test_killmails.py +0 -2
- killtracker/tests/models/test_trackers_1.py +24 -24
- killtracker/tests/models/test_trackers_2.py +6 -5
- killtracker/tests/models/test_webhooks.py +63 -0
- killtracker/tests/test_integration.py +25 -12
- killtracker/tests/test_tasks.py +161 -92
- killtracker/tests/test_utils.py +39 -0
- killtracker/tests/testdata/factories.py +1 -1
- killtracker/tests/testdata/helpers.py +1 -1
- killtracker/tests/utils.py +44 -0
- killtracker/exceptions.py +0 -32
- killtracker/tests/models/test_webhook.py +0 -150
- killtracker/tests/test_exceptions.py +0 -12
- {aa_killtracker-0.17.0.dist-info → aa_killtracker-1.0.0.dist-info}/WHEEL +0 -0
- {aa_killtracker-0.17.0.dist-info → aa_killtracker-1.0.0.dist-info}/licenses/LICENSE +0 -0
killtracker/tests/test_tasks.py
CHANGED
@@ -1,26 +1,31 @@
|
|
1
|
+
import datetime as dt
|
1
2
|
from unittest.mock import patch
|
2
3
|
|
3
|
-
import
|
4
|
-
import dhooks_lite
|
4
|
+
from celery.exceptions import Retry
|
5
5
|
|
6
6
|
from django.core.cache import cache
|
7
7
|
from django.test import TestCase
|
8
|
-
from django.
|
8
|
+
from django.utils.timezone import now
|
9
9
|
|
10
|
-
from killtracker.
|
10
|
+
from killtracker.core.discord import (
|
11
|
+
DiscordMessage,
|
12
|
+
HTTPError,
|
13
|
+
WebhookRateLimitExhausted,
|
14
|
+
)
|
11
15
|
from killtracker.models import EveKillmail
|
12
16
|
from killtracker.tasks import (
|
17
|
+
ZKBTooManyRequestsError,
|
13
18
|
delete_stale_killmails,
|
14
19
|
generate_killmail_message,
|
15
20
|
run_killtracker,
|
16
21
|
run_tracker,
|
17
22
|
send_messages_to_webhook,
|
18
|
-
send_test_message_to_webhook,
|
19
23
|
store_killmail,
|
20
24
|
)
|
21
25
|
|
22
26
|
from .testdata.factories import TrackerFactory
|
23
27
|
from .testdata.helpers import LoadTestDataMixin, load_eve_killmails, load_killmail
|
28
|
+
from .utils import reset_celery_once_locks
|
24
29
|
|
25
30
|
MODULE_PATH = "killtracker.tasks"
|
26
31
|
|
@@ -48,16 +53,13 @@ class TestTrackerBase(LoadTestDataMixin, TestCase):
|
|
48
53
|
)
|
49
54
|
|
50
55
|
|
51
|
-
@
|
56
|
+
@patch(MODULE_PATH + ".workers.is_shutting_down", spec=True)
|
52
57
|
@patch(MODULE_PATH + ".is_esi_online", spec=True)
|
53
58
|
@patch(MODULE_PATH + ".delete_stale_killmails", spec=True)
|
54
59
|
@patch(MODULE_PATH + ".store_killmail", spec=True)
|
55
60
|
@patch(MODULE_PATH + ".Killmail.create_from_zkb_redisq")
|
56
61
|
@patch(MODULE_PATH + ".run_tracker", spec=True)
|
57
62
|
class TestRunKilltracker(TestTrackerBase):
|
58
|
-
def setUp(self) -> None:
|
59
|
-
cache.clear()
|
60
|
-
|
61
63
|
@staticmethod
|
62
64
|
def my_fetch_from_zkb():
|
63
65
|
for killmail_id in [10000001, 10000002, 10000003, None]:
|
@@ -66,6 +68,9 @@ class TestRunKilltracker(TestTrackerBase):
|
|
66
68
|
else:
|
67
69
|
yield None
|
68
70
|
|
71
|
+
def setUp(self):
|
72
|
+
reset_celery_once_locks()
|
73
|
+
|
69
74
|
@patch(MODULE_PATH + ".KILLTRACKER_STORING_KILLMAILS_ENABLED", False)
|
70
75
|
def test_should_run_normally(
|
71
76
|
self,
|
@@ -74,35 +79,41 @@ class TestRunKilltracker(TestTrackerBase):
|
|
74
79
|
mock_store_killmail,
|
75
80
|
mock_delete_stale_killmails,
|
76
81
|
mock_is_esi_online,
|
82
|
+
mock_is_shutting_down,
|
77
83
|
):
|
78
84
|
# given
|
85
|
+
mock_is_shutting_down.return_value = False
|
79
86
|
mock_create_from_zkb_redisq.side_effect = self.my_fetch_from_zkb()
|
80
87
|
mock_is_esi_online.return_value = True
|
81
|
-
self.webhook_1.
|
88
|
+
self.webhook_1._error_queue.enqueue(load_killmail(10000004).asjson())
|
82
89
|
# when
|
83
|
-
run_killtracker
|
90
|
+
got = run_killtracker()
|
84
91
|
# then
|
92
|
+
self.assertEqual(got, 3)
|
85
93
|
self.assertEqual(mock_run_tracker.delay.call_count, 6)
|
86
94
|
self.assertEqual(mock_store_killmail.si.call_count, 0)
|
87
95
|
self.assertFalse(mock_delete_stale_killmails.delay.called)
|
88
|
-
self.assertEqual(self.webhook_1.
|
89
|
-
self.assertEqual(self.webhook_1.
|
96
|
+
self.assertEqual(self.webhook_1._main_queue.size(), 1)
|
97
|
+
self.assertEqual(self.webhook_1._error_queue.size(), 0)
|
90
98
|
|
91
99
|
@patch(MODULE_PATH + ".KILLTRACKER_STORING_KILLMAILS_ENABLED", False)
|
92
|
-
def
|
100
|
+
def test_should_abort_when_esi_is_offline(
|
93
101
|
self,
|
94
102
|
mock_run_tracker,
|
95
103
|
mock_create_from_zkb_redisq,
|
96
104
|
mock_store_killmail,
|
97
105
|
mock_delete_stale_killmails,
|
98
106
|
mock_is_esi_online,
|
107
|
+
mock_is_shutting_down,
|
99
108
|
):
|
100
109
|
# given
|
110
|
+
mock_is_shutting_down.return_value = False
|
101
111
|
mock_create_from_zkb_redisq.side_effect = self.my_fetch_from_zkb()
|
102
112
|
mock_is_esi_online.return_value = False
|
103
113
|
# when
|
104
|
-
run_killtracker
|
114
|
+
got = run_killtracker()
|
105
115
|
# then
|
116
|
+
self.assertEqual(got, 0)
|
106
117
|
self.assertEqual(mock_run_tracker.delay.call_count, 0)
|
107
118
|
self.assertEqual(mock_store_killmail.si.call_count, 0)
|
108
119
|
self.assertFalse(mock_delete_stale_killmails.delay.called)
|
@@ -115,13 +126,16 @@ class TestRunKilltracker(TestTrackerBase):
|
|
115
126
|
mock_store_killmail,
|
116
127
|
mock_delete_stale_killmails,
|
117
128
|
mock_is_esi_online,
|
129
|
+
mock_is_shutting_down,
|
118
130
|
):
|
119
131
|
# given
|
132
|
+
mock_is_shutting_down.return_value = False
|
120
133
|
mock_create_from_zkb_redisq.side_effect = self.my_fetch_from_zkb()
|
121
134
|
mock_is_esi_online.return_value = True
|
122
135
|
# when
|
123
|
-
run_killtracker
|
136
|
+
got = run_killtracker()
|
124
137
|
# then
|
138
|
+
self.assertEqual(got, 2)
|
125
139
|
self.assertEqual(mock_run_tracker.delay.call_count, 4)
|
126
140
|
|
127
141
|
@patch(MODULE_PATH + ".KILLTRACKER_PURGE_KILLMAILS_AFTER_DAYS", 30)
|
@@ -133,17 +147,63 @@ class TestRunKilltracker(TestTrackerBase):
|
|
133
147
|
mock_store_killmail,
|
134
148
|
mock_delete_stale_killmails,
|
135
149
|
mock_is_esi_online,
|
150
|
+
mock_is_shutting_down,
|
136
151
|
):
|
137
152
|
# given
|
153
|
+
mock_is_shutting_down.return_value = False
|
138
154
|
mock_create_from_zkb_redisq.side_effect = self.my_fetch_from_zkb()
|
139
155
|
mock_is_esi_online.return_value = True
|
140
156
|
# when
|
141
|
-
run_killtracker
|
157
|
+
run_killtracker()
|
142
158
|
# then
|
143
159
|
self.assertEqual(mock_run_tracker.delay.call_count, 6)
|
144
160
|
self.assertEqual(mock_store_killmail.si.call_count, 3)
|
145
161
|
self.assertTrue(mock_delete_stale_killmails.delay.called)
|
146
162
|
|
163
|
+
@patch(MODULE_PATH + ".KILLTRACKER_MAX_KILLMAILS_PER_RUN", 2)
|
164
|
+
def test_should_retry_when_too_many_errors_received(
|
165
|
+
self,
|
166
|
+
mock_run_tracker,
|
167
|
+
mock_create_from_zkb_redisq,
|
168
|
+
mock_store_killmail,
|
169
|
+
mock_delete_stale_killmails,
|
170
|
+
mock_is_esi_online,
|
171
|
+
mock_is_shutting_down,
|
172
|
+
):
|
173
|
+
# given
|
174
|
+
mock_is_shutting_down.return_value = False
|
175
|
+
mock_create_from_zkb_redisq.side_effect = ZKBTooManyRequestsError(
|
176
|
+
now() + dt.timedelta(minutes=1)
|
177
|
+
)
|
178
|
+
mock_is_esi_online.return_value = True
|
179
|
+
# when/then
|
180
|
+
with self.assertRaises(Retry):
|
181
|
+
run_killtracker()
|
182
|
+
# then
|
183
|
+
self.assertEqual(mock_run_tracker.delay.call_count, 0)
|
184
|
+
|
185
|
+
@patch(MODULE_PATH + ".KILLTRACKER_STORING_KILLMAILS_ENABLED", False)
|
186
|
+
def test_should_abort_when_worker_is_offline(
|
187
|
+
self,
|
188
|
+
mock_run_tracker,
|
189
|
+
mock_create_from_zkb_redisq,
|
190
|
+
mock_store_killmail,
|
191
|
+
mock_delete_stale_killmails,
|
192
|
+
mock_is_esi_online,
|
193
|
+
mock_is_shutting_down,
|
194
|
+
):
|
195
|
+
# given
|
196
|
+
mock_is_shutting_down.return_value = True
|
197
|
+
mock_create_from_zkb_redisq.side_effect = self.my_fetch_from_zkb()
|
198
|
+
mock_is_esi_online.return_value = True
|
199
|
+
# when
|
200
|
+
got = run_killtracker()
|
201
|
+
# then
|
202
|
+
self.assertEqual(got, 0)
|
203
|
+
self.assertEqual(mock_run_tracker.delay.call_count, 0)
|
204
|
+
self.assertEqual(mock_store_killmail.si.call_count, 0)
|
205
|
+
self.assertFalse(mock_delete_stale_killmails.delay.called)
|
206
|
+
|
147
207
|
|
148
208
|
@patch(MODULE_PATH + ".retry_task_if_esi_is_down", lambda x: None)
|
149
209
|
@patch(MODULE_PATH + ".send_messages_to_webhook", spec=True)
|
@@ -189,7 +249,7 @@ class TestRunTracker(TestTrackerBase):
|
|
189
249
|
# given
|
190
250
|
killmail = load_killmail(10000003)
|
191
251
|
killmail.save()
|
192
|
-
self.webhook_1.enqueue_message(content="test")
|
252
|
+
self.webhook_1.enqueue_message(DiscordMessage(content="test"))
|
193
253
|
# when
|
194
254
|
run_tracker(self.tracker_1.pk, killmail.id)
|
195
255
|
# then
|
@@ -222,7 +282,7 @@ class TestGenerateKillmailMessage(TestTrackerBase):
|
|
222
282
|
generate_killmail_message(self.tracker_1.pk, self.killmail_id)
|
223
283
|
# then
|
224
284
|
self.assertTrue(mock_send_messages_to_webhook.delay.called)
|
225
|
-
self.assertEqual(self.webhook_1.
|
285
|
+
self.assertEqual(self.webhook_1._main_queue.size(), 1)
|
226
286
|
self.assertFalse(mock_retry.called)
|
227
287
|
|
228
288
|
@patch(MODULE_PATH + ".KILLTRACKER_GENERATE_MESSAGE_MAX_RETRIES", 3)
|
@@ -238,87 +298,114 @@ class TestGenerateKillmailMessage(TestTrackerBase):
|
|
238
298
|
with self.assertRaises(RuntimeError):
|
239
299
|
generate_killmail_message(self.tracker_1.pk, self.killmail_id)
|
240
300
|
self.assertFalse(mock_send_messages_to_webhook.delay.called)
|
241
|
-
self.assertEqual(self.webhook_1.
|
301
|
+
self.assertEqual(self.webhook_1._main_queue.size(), 0)
|
242
302
|
self.assertEqual(mock_retry.call_count, 4)
|
243
303
|
|
244
304
|
|
245
|
-
@patch("celery.app.task.Context.called_directly", False) # make retry work with eager
|
246
|
-
@override_settings(CELERY_ALWAYS_EAGER=True)
|
247
|
-
|
305
|
+
# @patch("celery.app.task.Context.called_directly", False) # make retry work with eager
|
306
|
+
# @override_settings(CELERY_ALWAYS_EAGER=True)
|
307
|
+
|
308
|
+
|
309
|
+
@patch(MODULE_PATH + ".workers.is_shutting_down", spec=True)
|
310
|
+
@patch(MODULE_PATH + ".Webhook.send_message", spec=True)
|
248
311
|
class TestSendMessagesToWebhook(TestTrackerBase):
|
249
312
|
def setUp(self) -> None:
|
250
313
|
cache.clear()
|
251
314
|
|
252
|
-
def
|
253
|
-
"""when one message in queue, then send it and retry with delay"""
|
315
|
+
def test_should_send_one_message(self, mock_send_message, mock_is_shutting_down):
|
254
316
|
# given
|
255
|
-
|
256
|
-
|
257
|
-
)
|
258
|
-
self.webhook_1.enqueue_message(content="Test message")
|
317
|
+
mock_is_shutting_down.return_value = False
|
318
|
+
mock_send_message.return_value = 42
|
319
|
+
self.webhook_1.enqueue_message(DiscordMessage(content="Test message"))
|
259
320
|
# when
|
260
|
-
send_messages_to_webhook
|
321
|
+
send_messages_to_webhook(self.webhook_1.pk)
|
261
322
|
# then
|
262
|
-
self.assertEqual(
|
263
|
-
self.assertEqual(self.webhook_1.
|
264
|
-
self.assertEqual(self.webhook_1.
|
323
|
+
self.assertEqual(mock_send_message.call_count, 1)
|
324
|
+
self.assertEqual(self.webhook_1._main_queue.size(), 0)
|
325
|
+
self.assertEqual(self.webhook_1._error_queue.size(), 0)
|
265
326
|
|
266
|
-
def
|
267
|
-
"""when three messages in queue, then sends them and returns 3"""
|
327
|
+
def test_should_send_three_messages(self, mock_send_message, mock_is_shutting_down):
|
268
328
|
# given
|
269
|
-
|
270
|
-
|
271
|
-
)
|
272
|
-
self.webhook_1.enqueue_message(content="Test message")
|
273
|
-
self.webhook_1.enqueue_message(content="Test message")
|
274
|
-
self.webhook_1.enqueue_message(content="Test message")
|
329
|
+
mock_is_shutting_down.return_value = False
|
330
|
+
mock_send_message.return_value = [1, 2, 3]
|
331
|
+
self.webhook_1.enqueue_message(DiscordMessage(content="Test message"))
|
332
|
+
self.webhook_1.enqueue_message(DiscordMessage(content="Test message"))
|
333
|
+
self.webhook_1.enqueue_message(DiscordMessage(content="Test message"))
|
275
334
|
# when
|
276
|
-
send_messages_to_webhook
|
335
|
+
send_messages_to_webhook(self.webhook_1.pk)
|
277
336
|
# then
|
278
|
-
self.assertEqual(
|
279
|
-
self.assertEqual(self.webhook_1.
|
280
|
-
self.assertEqual(self.webhook_1.
|
337
|
+
self.assertEqual(mock_send_message.call_count, 3)
|
338
|
+
self.assertEqual(self.webhook_1._main_queue.size(), 0)
|
339
|
+
self.assertEqual(self.webhook_1._error_queue.size(), 0)
|
281
340
|
|
282
|
-
def
|
283
|
-
|
341
|
+
def test_should_do_nothing_when_queue_is_empty(
|
342
|
+
self, mock_send_message, mock_is_shutting_down
|
343
|
+
):
|
284
344
|
# given
|
285
|
-
|
286
|
-
{}, status_code=200
|
287
|
-
)
|
345
|
+
mock_is_shutting_down.return_value = False
|
288
346
|
# when
|
289
|
-
send_messages_to_webhook
|
347
|
+
send_messages_to_webhook(self.webhook_1.pk)
|
290
348
|
# then
|
291
|
-
self.assertEqual(
|
292
|
-
self.assertEqual(self.webhook_1.
|
293
|
-
self.assertEqual(self.webhook_1.
|
349
|
+
self.assertEqual(mock_send_message.call_count, 0)
|
350
|
+
self.assertEqual(self.webhook_1._main_queue.size(), 0)
|
351
|
+
self.assertEqual(self.webhook_1._error_queue.size(), 0)
|
294
352
|
|
295
|
-
def
|
296
|
-
|
353
|
+
def test_should_put_failed_message_in_error_queue(
|
354
|
+
self, mock_send_message, mock_is_shutting_down
|
355
|
+
):
|
297
356
|
# given
|
298
|
-
|
299
|
-
|
300
|
-
)
|
301
|
-
self.webhook_1.enqueue_message(content="Test message")
|
357
|
+
mock_is_shutting_down.return_value = False
|
358
|
+
mock_send_message.side_effect = HTTPError(404)
|
359
|
+
self.webhook_1.enqueue_message(DiscordMessage(content="Test message"))
|
302
360
|
# when
|
303
|
-
send_messages_to_webhook
|
361
|
+
send_messages_to_webhook(self.webhook_1.pk)
|
304
362
|
# then
|
305
|
-
self.assertEqual(
|
306
|
-
self.assertEqual(self.webhook_1.
|
307
|
-
self.assertEqual(self.webhook_1.
|
363
|
+
self.assertEqual(mock_send_message.call_count, 1)
|
364
|
+
self.assertEqual(self.webhook_1._main_queue.size(), 0)
|
365
|
+
self.assertEqual(self.webhook_1._error_queue.size(), 1)
|
308
366
|
|
309
|
-
def
|
310
|
-
|
311
|
-
|
312
|
-
then message is re-queued and retry once
|
313
|
-
"""
|
367
|
+
def test_should_retry_on_too_many_requests_error(
|
368
|
+
self, mock_send_message, mock_is_shutting_down
|
369
|
+
):
|
314
370
|
# given
|
315
|
-
|
316
|
-
|
371
|
+
mock_is_shutting_down.return_value = False
|
372
|
+
mock_send_message.side_effect = WebhookRateLimitExhausted(10)
|
373
|
+
self.webhook_1.enqueue_message(DiscordMessage(content="Test message"))
|
317
374
|
# when
|
318
|
-
|
375
|
+
with self.assertRaises(Retry):
|
376
|
+
send_messages_to_webhook(self.webhook_1.pk)
|
319
377
|
# then
|
320
|
-
self.assertEqual(
|
321
|
-
self.assertEqual(self.webhook_1.
|
378
|
+
self.assertEqual(mock_send_message.call_count, 1)
|
379
|
+
self.assertEqual(self.webhook_1._main_queue.size(), 1)
|
380
|
+
|
381
|
+
def test_should_abort_when_worker_is_shutting_down(
|
382
|
+
self, mock_send_message, mock_is_shutting_down
|
383
|
+
):
|
384
|
+
# given
|
385
|
+
mock_is_shutting_down.return_value = True
|
386
|
+
mock_send_message.return_value = 42
|
387
|
+
self.webhook_1.enqueue_message(DiscordMessage(content="Test message"))
|
388
|
+
# when
|
389
|
+
send_messages_to_webhook(self.webhook_1.pk)
|
390
|
+
# then
|
391
|
+
self.assertEqual(mock_send_message.call_count, 0)
|
392
|
+
self.assertEqual(self.webhook_1._main_queue.size(), 1)
|
393
|
+
|
394
|
+
@patch(MODULE_PATH + ".KILLTRACKER_MAX_MESSAGES_SENT_PER_RUN", 1)
|
395
|
+
def test_retry_when_limit_is_reached(
|
396
|
+
self, mock_send_message, mock_is_shutting_down
|
397
|
+
):
|
398
|
+
# given
|
399
|
+
mock_is_shutting_down.return_value = False
|
400
|
+
mock_send_message.return_value = [1, 2]
|
401
|
+
self.webhook_1.enqueue_message(DiscordMessage(content="Test message"))
|
402
|
+
self.webhook_1.enqueue_message(DiscordMessage(content="Test message"))
|
403
|
+
# when
|
404
|
+
with self.assertRaises(Retry):
|
405
|
+
send_messages_to_webhook(self.webhook_1.pk)
|
406
|
+
# then
|
407
|
+
self.assertEqual(mock_send_message.call_count, 1)
|
408
|
+
self.assertEqual(self.webhook_1._main_queue.size(), 1)
|
322
409
|
|
323
410
|
|
324
411
|
@patch(MODULE_PATH + ".logger", spec=True)
|
@@ -347,24 +434,6 @@ class TestStoreKillmail(TestTrackerBase):
|
|
347
434
|
self.assertTrue(mock_logger.warning.called)
|
348
435
|
|
349
436
|
|
350
|
-
@override_settings(CELERY_ALWAYS_EAGER=True, CELERY_EAGER_PROPAGATES_EXCEPTIONS=True)
|
351
|
-
@patch("killtracker.models.webhooks.dhooks_lite.Webhook.execute", spec=True)
|
352
|
-
@patch(MODULE_PATH + ".logger", spec=True)
|
353
|
-
class TestSendTestKillmailsToWebhook(TestTrackerBase):
|
354
|
-
def setUp(self) -> None:
|
355
|
-
self.webhook_1.main_queue.clear()
|
356
|
-
|
357
|
-
def test_run_normal(self, mock_logger, mock_execute):
|
358
|
-
# given
|
359
|
-
mock_execute.return_value = dhooks_lite.WebhookResponse({}, status_code=200)
|
360
|
-
# when
|
361
|
-
with self.assertRaises(celery.exceptions.Retry):
|
362
|
-
send_test_message_to_webhook.delay(self.webhook_1.pk)
|
363
|
-
# then
|
364
|
-
self.assertTrue(mock_execute.called)
|
365
|
-
self.assertFalse(mock_logger.error.called)
|
366
|
-
|
367
|
-
|
368
437
|
@patch(MODULE_PATH + ".EveKillmail.objects.delete_stale")
|
369
438
|
class TestDeleteStaleKillmails(TestTrackerBase):
|
370
439
|
def test_normal(self, mock_delete_stale):
|
@@ -0,0 +1,39 @@
|
|
1
|
+
from unittest import TestCase
|
2
|
+
|
3
|
+
from .utils import CacheFake
|
4
|
+
|
5
|
+
|
6
|
+
class TestCacheFake(TestCase):
|
7
|
+
def test_get_should_return_value_when_found(self):
|
8
|
+
cache = CacheFake()
|
9
|
+
cache.set("alpha", 5)
|
10
|
+
got = cache.get("alpha")
|
11
|
+
self.assertEqual(got, 5)
|
12
|
+
|
13
|
+
def test_get_should_return_default_when_not_found(self):
|
14
|
+
cache = CacheFake()
|
15
|
+
cache.set("alpha", 5)
|
16
|
+
got = cache.get("bravo", 99)
|
17
|
+
self.assertEqual(got, 99)
|
18
|
+
|
19
|
+
def test_delete_should_remove_key(self):
|
20
|
+
cache = CacheFake()
|
21
|
+
cache.set("alpha", 5)
|
22
|
+
cache.delete("alpha")
|
23
|
+
self.assertIsNone(cache.get("alpha"))
|
24
|
+
|
25
|
+
def test_delete_should_ignore_when_key_does_not_exist(self):
|
26
|
+
cache = CacheFake()
|
27
|
+
cache.delete("alpha")
|
28
|
+
|
29
|
+
def test_clear_should_remove_all_keys(self):
|
30
|
+
cache = CacheFake()
|
31
|
+
cache.set("alpha", 5)
|
32
|
+
cache.clear()
|
33
|
+
self.assertIsNone(cache.get("alpha"))
|
34
|
+
|
35
|
+
def test_set_with_timeout(self):
|
36
|
+
cache = CacheFake()
|
37
|
+
cache.set("alpha", "django", timeout=5)
|
38
|
+
got = cache.get("alpha")
|
39
|
+
self.assertEqual(got, "django")
|
@@ -14,7 +14,7 @@ from allianceauth.eveonline.models import EveFactionInfo
|
|
14
14
|
|
15
15
|
from killtracker.app_settings import KILLTRACKER_KILLMAIL_MAX_AGE_FOR_TRACKER
|
16
16
|
from killtracker.constants import EveCategoryId
|
17
|
-
from killtracker.core.
|
17
|
+
from killtracker.core.zkb import (
|
18
18
|
Killmail,
|
19
19
|
KillmailAttacker,
|
20
20
|
KillmailPosition,
|
@@ -8,7 +8,7 @@ from eveuniverse.models import EveEntity, EveType, EveUniverseEntityModel
|
|
8
8
|
from allianceauth.eveonline.models import EveAllianceInfo, EveCorporationInfo
|
9
9
|
from allianceauth.tests.auth_utils import AuthUtils
|
10
10
|
|
11
|
-
from killtracker.core.
|
11
|
+
from killtracker.core.zkb import Killmail
|
12
12
|
from killtracker.models import EveKillmail, Webhook
|
13
13
|
|
14
14
|
from . import _current_dir
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import logging
|
2
|
+
from typing import Any, Dict
|
3
|
+
|
4
|
+
from app_utils.allianceauth import get_redis_client
|
5
|
+
|
6
|
+
logger = logging.getLogger(__name__)
|
7
|
+
|
8
|
+
|
9
|
+
def reset_celery_once_locks():
|
10
|
+
"""Reset celery once locks for given tasks."""
|
11
|
+
r = get_redis_client()
|
12
|
+
app_label = "killtracker"
|
13
|
+
if keys := r.keys(f":?:qo_{app_label}.*"):
|
14
|
+
deleted_count = r.delete(*keys)
|
15
|
+
logger.info("Removed %d stuck celery once keys", deleted_count)
|
16
|
+
else:
|
17
|
+
deleted_count = 0
|
18
|
+
|
19
|
+
|
20
|
+
class CacheFake:
|
21
|
+
"""A fake for replacing Django's cache in tests."""
|
22
|
+
|
23
|
+
def __init__(self):
|
24
|
+
self._cache: Dict[str, Any] = {}
|
25
|
+
|
26
|
+
def clear(self) -> None:
|
27
|
+
self._cache.clear()
|
28
|
+
|
29
|
+
def delete(self, key: str, version: int = None) -> None:
|
30
|
+
try:
|
31
|
+
del self._cache[key]
|
32
|
+
except KeyError:
|
33
|
+
pass
|
34
|
+
|
35
|
+
def get(self, key: str, default: Any = None, version: int = None) -> Any:
|
36
|
+
try:
|
37
|
+
return self._cache[key]
|
38
|
+
except KeyError:
|
39
|
+
return default
|
40
|
+
|
41
|
+
def set(
|
42
|
+
self, key: str, value: Any, timeout: int = None, version: int = None
|
43
|
+
) -> None:
|
44
|
+
self._cache[key] = value
|
killtracker/exceptions.py
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
"""Custom exceptions for killtracker."""
|
2
|
-
|
3
|
-
from typing import Optional
|
4
|
-
|
5
|
-
|
6
|
-
class KilltrackerException(Exception):
|
7
|
-
"""Exception from Killtracker"""
|
8
|
-
|
9
|
-
|
10
|
-
class WebhookTooManyRequests(KilltrackerException):
|
11
|
-
"""Webhook is temporarily blocked."""
|
12
|
-
|
13
|
-
DEFAULT_RESET_AFTER = 600
|
14
|
-
|
15
|
-
def __init__(self, retry_after: Optional[int] = None) -> None:
|
16
|
-
"""
|
17
|
-
Parameters:
|
18
|
-
- retry_after: time in seconds until this blockage will be reset
|
19
|
-
"""
|
20
|
-
super().__init__()
|
21
|
-
if retry_after is None:
|
22
|
-
retry_after = self.DEFAULT_RESET_AFTER
|
23
|
-
self._reset_after = int(retry_after)
|
24
|
-
|
25
|
-
@property
|
26
|
-
def retry_after(self) -> int:
|
27
|
-
"""Return in how many seconds to retry."""
|
28
|
-
return self._reset_after
|
29
|
-
|
30
|
-
|
31
|
-
class KillmailDoesNotExist(KilltrackerException):
|
32
|
-
"""Killmail does not exist in storage."""
|