aa-killtracker 0.17.0__py3-none-any.whl → 1.0.0a1__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.
Files changed (39) hide show
  1. {aa_killtracker-0.17.0.dist-info → aa_killtracker-1.0.0a1.dist-info}/METADATA +7 -7
  2. {aa_killtracker-0.17.0.dist-info → aa_killtracker-1.0.0a1.dist-info}/RECORD +36 -29
  3. killtracker/__init__.py +1 -1
  4. killtracker/admin.py +13 -8
  5. killtracker/app_settings.py +20 -10
  6. killtracker/apps.py +2 -4
  7. killtracker/core/discord.py +162 -0
  8. killtracker/core/helpers.py +13 -0
  9. killtracker/core/{discord_messages.py → trackers.py} +74 -59
  10. killtracker/core/workers.py +46 -0
  11. killtracker/core/{killmails.py → zkb.py} +97 -72
  12. killtracker/forms.py +1 -1
  13. killtracker/managers.py +3 -3
  14. killtracker/models/trackers.py +7 -10
  15. killtracker/models/webhooks.py +60 -128
  16. killtracker/providers.py +1 -1
  17. killtracker/signals.py +31 -0
  18. killtracker/tasks.py +141 -92
  19. killtracker/tests/core/test_discord.py +184 -0
  20. killtracker/tests/core/test_helpers.py +23 -0
  21. killtracker/tests/core/{test_discord_messages_1.py → test_tracker_1.py} +28 -8
  22. killtracker/tests/core/{test_discord_messages_2.py → test_tracker_2.py} +11 -11
  23. killtracker/tests/core/test_workers.py +49 -0
  24. killtracker/tests/core/{test_killmails.py → test_zkb.py} +109 -52
  25. killtracker/tests/models/test_killmails.py +0 -2
  26. killtracker/tests/models/test_trackers_1.py +24 -24
  27. killtracker/tests/models/test_trackers_2.py +6 -5
  28. killtracker/tests/models/test_webhooks.py +63 -0
  29. killtracker/tests/test_integration.py +25 -12
  30. killtracker/tests/test_tasks.py +161 -92
  31. killtracker/tests/test_utils.py +39 -0
  32. killtracker/tests/testdata/factories.py +1 -1
  33. killtracker/tests/testdata/helpers.py +1 -1
  34. killtracker/tests/utils.py +44 -0
  35. killtracker/exceptions.py +0 -32
  36. killtracker/tests/models/test_webhook.py +0 -150
  37. killtracker/tests/test_exceptions.py +0 -12
  38. {aa_killtracker-0.17.0.dist-info → aa_killtracker-1.0.0a1.dist-info}/WHEEL +0 -0
  39. {aa_killtracker-0.17.0.dist-info → aa_killtracker-1.0.0a1.dist-info}/licenses/LICENSE +0 -0
@@ -1,26 +1,31 @@
1
+ import datetime as dt
1
2
  from unittest.mock import patch
2
3
 
3
- import celery
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.test.utils import override_settings
8
+ from django.utils.timezone import now
9
9
 
10
- from killtracker.exceptions import WebhookTooManyRequests
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
- @override_settings(CELERY_ALWAYS_EAGER=True, CELERY_EAGER_PROPAGATES_EXCEPTIONS=True)
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.error_queue.enqueue(load_killmail(10000004).asjson())
88
+ self.webhook_1._error_queue.enqueue(load_killmail(10000004).asjson())
82
89
  # when
83
- run_killtracker.delay()
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.main_queue.size(), 1)
89
- self.assertEqual(self.webhook_1.error_queue.size(), 0)
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 test_should_stop_when_esi_is_offline(
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.delay()
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.delay()
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.delay()
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.main_queue.size(), 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.main_queue.size(), 0)
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
- @patch(MODULE_PATH + ".Webhook.send_message_to_webhook", spec=True)
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 test_one_message(self, mock_send_message_to_webhook):
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
- mock_send_message_to_webhook.return_value = dhooks_lite.WebhookResponse(
256
- {}, status_code=200
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.delay(self.webhook_1.pk)
321
+ send_messages_to_webhook(self.webhook_1.pk)
261
322
  # then
262
- self.assertEqual(mock_send_message_to_webhook.call_count, 1)
263
- self.assertEqual(self.webhook_1.main_queue.size(), 0)
264
- self.assertEqual(self.webhook_1.error_queue.size(), 0)
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 test_three_message(self, mock_send_message_to_webhook):
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
- mock_send_message_to_webhook.return_value = dhooks_lite.WebhookResponse(
270
- {}, status_code=200
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.delay(self.webhook_1.pk)
335
+ send_messages_to_webhook(self.webhook_1.pk)
277
336
  # then
278
- self.assertEqual(mock_send_message_to_webhook.call_count, 3)
279
- self.assertEqual(self.webhook_1.main_queue.size(), 0)
280
- self.assertEqual(self.webhook_1.error_queue.size(), 0)
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 test_no_messages(self, mock_send_message_to_webhook):
283
- """when no messages in queue, then do nothing"""
341
+ def test_should_do_nothing_when_queue_is_empty(
342
+ self, mock_send_message, mock_is_shutting_down
343
+ ):
284
344
  # given
285
- mock_send_message_to_webhook.return_value = dhooks_lite.WebhookResponse(
286
- {}, status_code=200
287
- )
345
+ mock_is_shutting_down.return_value = False
288
346
  # when
289
- send_messages_to_webhook.delay(self.webhook_1.pk)
347
+ send_messages_to_webhook(self.webhook_1.pk)
290
348
  # then
291
- self.assertEqual(mock_send_message_to_webhook.call_count, 0)
292
- self.assertEqual(self.webhook_1.main_queue.size(), 0)
293
- self.assertEqual(self.webhook_1.error_queue.size(), 0)
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 test_failed_message(self, mock_send_message_to_webhook):
296
- """when message sending failed, then put message in error queue"""
353
+ def test_should_put_failed_message_in_error_queue(
354
+ self, mock_send_message, mock_is_shutting_down
355
+ ):
297
356
  # given
298
- mock_send_message_to_webhook.return_value = dhooks_lite.WebhookResponse(
299
- {}, status_code=404
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.delay(self.webhook_1.pk)
361
+ send_messages_to_webhook(self.webhook_1.pk)
304
362
  # then
305
- self.assertEqual(mock_send_message_to_webhook.call_count, 1)
306
- self.assertEqual(self.webhook_1.main_queue.size(), 0)
307
- self.assertEqual(self.webhook_1.error_queue.size(), 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 test_abort_on_too_many_requests(self, mock_send_message_to_webhook):
310
- """
311
- when WebhookTooManyRequests exception is raised
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
- mock_send_message_to_webhook.side_effect = WebhookTooManyRequests(10)
316
- self.webhook_1.enqueue_message(content="Test message")
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
- send_messages_to_webhook.delay(self.webhook_1.pk)
375
+ with self.assertRaises(Retry):
376
+ send_messages_to_webhook(self.webhook_1.pk)
319
377
  # then
320
- self.assertEqual(mock_send_message_to_webhook.call_count, 1)
321
- self.assertEqual(self.webhook_1.main_queue.size(), 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.killmails import (
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.killmails import Killmail
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."""