assemblyline-core 4.5.1.dev132__tar.gz → 4.5.1.dev135__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.

Potentially problematic release.


This version of assemblyline-core might be problematic. Click here for more details.

Files changed (88) hide show
  1. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/PKG-INFO +1 -1
  2. assemblyline-core-4.5.1.dev135/assemblyline_core/VERSION +1 -0
  3. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/expiry/run_expiry.py +78 -86
  4. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core.egg-info/PKG-INFO +1 -1
  5. assemblyline-core-4.5.1.dev132/assemblyline_core/VERSION +0 -1
  6. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/LICENCE.md +0 -0
  7. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/README.md +0 -0
  8. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/__init__.py +0 -0
  9. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/alerter/__init__.py +0 -0
  10. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/alerter/processing.py +0 -0
  11. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/alerter/run_alerter.py +0 -0
  12. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/archiver/__init__.py +0 -0
  13. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/archiver/run_archiver.py +0 -0
  14. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/badlist_client.py +0 -0
  15. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/dispatching/__init__.py +0 -0
  16. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/dispatching/__main__.py +0 -0
  17. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/dispatching/client.py +0 -0
  18. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/dispatching/dispatcher.py +0 -0
  19. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/dispatching/schedules.py +0 -0
  20. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/dispatching/timeout.py +0 -0
  21. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/expiry/__init__.py +0 -0
  22. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/ingester/__init__.py +0 -0
  23. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/ingester/__main__.py +0 -0
  24. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/ingester/constants.py +0 -0
  25. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/ingester/ingester.py +0 -0
  26. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/metrics/__init__.py +0 -0
  27. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/metrics/es_metrics.py +0 -0
  28. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/metrics/heartbeat_formatter.py +0 -0
  29. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/metrics/helper.py +0 -0
  30. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/metrics/metrics_server.py +0 -0
  31. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/metrics/run_heartbeat_manager.py +0 -0
  32. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/metrics/run_metrics_aggregator.py +0 -0
  33. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/metrics/run_statistics_aggregator.py +0 -0
  34. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/plumber/__init__.py +0 -0
  35. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/plumber/run_plumber.py +0 -0
  36. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/replay/__init__.py +0 -0
  37. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/replay/client.py +0 -0
  38. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/replay/creator/__init__.py +0 -0
  39. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/replay/creator/run.py +0 -0
  40. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/replay/creator/run_worker.py +0 -0
  41. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/replay/loader/__init__.py +0 -0
  42. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/replay/loader/run.py +0 -0
  43. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/replay/loader/run_worker.py +0 -0
  44. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/replay/replay.py +0 -0
  45. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/safelist_client.py +0 -0
  46. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/scaler/__init__.py +0 -0
  47. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/scaler/collection.py +0 -0
  48. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/scaler/controllers/__init__.py +0 -0
  49. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/scaler/controllers/docker_ctl.py +0 -0
  50. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/scaler/controllers/interface.py +0 -0
  51. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/scaler/controllers/kubernetes_ctl.py +0 -0
  52. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/scaler/run_scaler.py +0 -0
  53. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/scaler/scaler_server.py +0 -0
  54. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/server_base.py +0 -0
  55. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/signature_client.py +0 -0
  56. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/submission_client.py +0 -0
  57. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/tasking_client.py +0 -0
  58. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/updater/__init__.py +0 -0
  59. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/updater/helper.py +0 -0
  60. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/updater/run_updater.py +0 -0
  61. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/vacuum/__init__.py +0 -0
  62. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/vacuum/crawler.py +0 -0
  63. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/vacuum/department_map.py +0 -0
  64. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/vacuum/safelist.py +0 -0
  65. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/vacuum/stream_map.py +0 -0
  66. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/vacuum/worker.py +0 -0
  67. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/workflow/__init__.py +0 -0
  68. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core/workflow/run_workflow.py +0 -0
  69. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core.egg-info/SOURCES.txt +0 -0
  70. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core.egg-info/dependency_links.txt +0 -0
  71. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core.egg-info/requires.txt +0 -0
  72. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/assemblyline_core.egg-info/top_level.txt +0 -0
  73. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/setup.cfg +0 -0
  74. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/setup.py +0 -0
  75. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/test/test_alerter.py +0 -0
  76. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/test/test_badlist_client.py +0 -0
  77. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/test/test_dispatcher.py +0 -0
  78. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/test/test_expiry.py +0 -0
  79. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/test/test_plumber.py +0 -0
  80. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/test/test_replay.py +0 -0
  81. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/test/test_safelist_client.py +0 -0
  82. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/test/test_scaler.py +0 -0
  83. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/test/test_scheduler.py +0 -0
  84. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/test/test_signature_client.py +0 -0
  85. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/test/test_simulation.py +0 -0
  86. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/test/test_vacuum.py +0 -0
  87. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/test/test_worker_ingest.py +0 -0
  88. {assemblyline-core-4.5.1.dev132 → assemblyline-core-4.5.1.dev135}/test/test_worker_submit.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: assemblyline-core
3
- Version: 4.5.1.dev132
3
+ Version: 4.5.1.dev135
4
4
  Summary: Assemblyline 4 - Core components
5
5
  Home-page: https://github.com/CybercentreCanada/assemblyline-core/
6
6
  Author: CCCS Assemblyline development team
@@ -0,0 +1 @@
1
+ 4.5.1.dev135
@@ -1,16 +1,17 @@
1
1
  #!/usr/bin/env python
2
2
  from __future__ import annotations
3
+
3
4
  import concurrent.futures
4
- from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor, Future, as_completed
5
- from concurrent.futures.process import BrokenProcessPool
6
5
  import functools
7
- from typing import Callable, Optional, Union, TYPE_CHECKING
8
6
  import elasticapm
9
7
  import time
10
8
 
9
+ from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor, Future, as_completed
10
+ from concurrent.futures.process import BrokenProcessPool
11
11
  from datemath import dm
12
+ from typing import Callable, Optional, TYPE_CHECKING
12
13
 
13
- from assemblyline.common.isotime import epoch_to_iso, now_as_iso, iso_to_epoch
14
+ from assemblyline.common.isotime import epoch_to_iso, now_as_iso
14
15
  from assemblyline_core.server_base import ServerBase
15
16
  from assemblyline_core.dispatching.dispatcher import BAD_SID_HASH
16
17
  from assemblyline.common import forge
@@ -181,9 +182,43 @@ class ExpiryManager(ServerBase):
181
182
  if self.apm_client:
182
183
  self.apm_client.end_transaction("canceled_submissions", 'deleted')
183
184
 
185
+ def _process_chunk(self, collection: ESCollection, start, end, final_date, number_to_delete):
186
+ # We assume that no records are ever inserted such that their expiry_ts is in the past.
187
+ # We also assume that the `end` dates are also in the past.
188
+ # As long as these two things are true, the set returned by this query should be consistent.
189
+ # The one race condition is that a record might be refreshed while the file
190
+ # blob would be deleted anyway, leaving a file record with no filestore object
191
+ self.log.info(f"Processing collection: {collection.name}")
192
+ delete_query = f"expiry_ts:{{{start} TO {end}]"
193
+
194
+ # check if we are dealing with an index that needs file cleanup
195
+ if self.config.core.expiry.delete_storage and collection.name in self.fs_hashmap:
196
+ # Delete associated files
197
+ delete_objects: list[str] = []
198
+ for item in collection.stream_search(delete_query, fl='id', as_obj=False):
199
+ self.heartbeat()
200
+ delete_objects.append(item['id'])
201
+
202
+ # Filter archived documents if archive filestore is the same as the filestore
203
+ expire_only = []
204
+ if self.same_storage and self.config.datastore.archive.enabled and collection.name == 'file':
205
+ archived_files = self.datastore.file.multiexists_in_archive(delete_objects)
206
+ delete_objects = [k for k, v in archived_files.items() if not v]
207
+ expire_only = [k for k, v in archived_files.items() if v]
208
+
209
+ delete_tasks = self.fs_hashmap[collection.name](delete_objects, final_date)
210
+
211
+ # Proceed with deletion, but only after all the scheduled deletes for this
212
+ self.log.info(f"Scheduled {len(delete_objects)}/{number_to_delete} "
213
+ f"files to be removed for: {collection.name}")
214
+ self._finish_delete(collection, delete_tasks, expire_only)
215
+
216
+ else:
217
+ # Proceed with deletion
218
+ self._simple_delete(collection, delete_query, number_to_delete)
219
+
184
220
  def run_expiry_once(self, pool: ThreadPoolExecutor):
185
- now = now_as_iso()
186
- reached_max = False
221
+ busy_iteration = False
187
222
 
188
223
  # Delete canceled submissions
189
224
  # Make sure we're not dedicating more then a quarter of the pool to this operation because it is costly
@@ -201,111 +236,68 @@ class ExpiryManager(ServerBase):
201
236
  if self.apm_client:
202
237
  self.apm_client.begin_transaction("Delete expired documents")
203
238
 
204
- if self.config.core.expiry.batch_delete:
205
- final_date = dm(f"{now}||-{self.config.core.expiry.delay}h/d").float_timestamp
206
- else:
207
- final_date = dm(f"{now}||-{self.config.core.expiry.delay}h").float_timestamp
208
- final_date_string = epoch_to_iso(final_date)
239
+ final_date = self._get_final_date()
209
240
 
210
241
  # Break down the expiry window into smaller chunks of data
211
- unchecked_chunks: list[tuple[float, float]] = [(self._find_expiry_start(collection), final_date)]
212
- ready_chunks: dict[tuple[float, float], int] = {}
213
- while unchecked_chunks and len(ready_chunks) < self.config.core.expiry.iteration_max_tasks:
242
+ start = "*"
243
+ iterations = 0
244
+ while iterations < self.config.core.expiry.iteration_max_tasks:
214
245
  self.heartbeat()
215
- start, end = unchecked_chunks.pop()
216
- chunk_size = self._count_expired(collection, start, end)
217
246
 
218
- # Empty chunks are fine
219
- if chunk_size == 0:
220
- continue
247
+ # Get the next chunk
248
+ end, number_to_delete = self._get_next_chunk(collection, start, final_date)
221
249
 
222
- # We found a small enough chunk to
223
- # run on
224
- if chunk_size < self.expiry_size:
225
- ready_chunks[(start, end)] = chunk_size
226
- continue
250
+ # Check if we got anything
251
+ if number_to_delete == 0:
252
+ break
227
253
 
228
- # Break this chunk into parts
229
- middle = (end + start)/2
230
- unchecked_chunks.append((middle, end))
231
- unchecked_chunks.append((start, middle))
254
+ # Tell the outer loop not to sleep between runs
255
+ if number_to_delete >= self.expiry_size:
256
+ busy_iteration = True
232
257
 
233
- # If there are still chunks we haven't checked, then we know there is more data
234
- if unchecked_chunks:
235
- reached_max = True
258
+ # Process the chunk in the threadpool
259
+ pool.submit(self.log_errors(self._process_chunk), collection, start, end, final_date, number_to_delete)
236
260
 
237
- for (start, end), number_to_delete in ready_chunks.items():
238
- self.heartbeat()
239
- # We assume that no records are ever inserted such that their expiry_ts is in the past.
240
- # We also assume that the `end` dates are also in the past.
241
- # As long as these two things are true, the set returned by this query should be consistent.
242
- # The one race condition is that a record might be refreshed while the file
243
- # blob would be deleted anyway, leaving a file record with no filestore object
244
- self.log.info(f"Processing collection: {collection.name}")
245
- delete_query = f"expiry_ts:[{epoch_to_iso(start) if start > 0 else '*'} TO {epoch_to_iso(end)}}}"
246
-
247
- # check if we are dealing with an index that needs file cleanup
248
- if self.config.core.expiry.delete_storage and collection.name in self.fs_hashmap:
249
- # Delete associated files
250
- delete_objects: list[str] = []
251
- for item in collection.stream_search(delete_query, fl='id', as_obj=False):
252
- self.heartbeat()
253
- delete_objects.append(item['id'])
254
-
255
- # Filter archived documents if archive filestore is the same as the filestore
256
- expire_only = []
257
- if self.same_storage and self.config.datastore.archive.enabled and collection.name == 'file':
258
- archived_files = self.datastore.file.multiexists_in_archive(delete_objects)
259
- delete_objects = [k for k, v in archived_files.items() if not v]
260
- expire_only = [k for k, v in archived_files.items() if v]
261
-
262
- delete_tasks = self.fs_hashmap[collection.name](delete_objects, final_date_string)
263
-
264
- # Proceed with deletion, but only after all the scheduled deletes for this
265
- self.log.info(f"Scheduled {len(delete_objects)}/{number_to_delete} "
266
- f"files to be removed for: {collection.name}")
267
- pool.submit(self.log_errors(self._finish_delete), collection, delete_tasks, expire_only)
268
-
269
- else:
270
- # Proceed with deletion
271
- pool.submit(self.log_errors(self._simple_delete),
272
- collection, delete_query, number_to_delete)
261
+ # Prepare for next chunk
262
+ start = end
263
+ iterations += 1
273
264
 
274
265
  # End of expiry transaction
275
266
  if self.apm_client:
276
267
  self.apm_client.end_transaction(collection.name, 'deleted')
277
268
 
278
- return reached_max
269
+ return busy_iteration
279
270
 
280
- def _find_expiry_start(self, container: ESCollection):
281
- """Find earliest expiring item in this container."""
282
- rows = container.search(f"expiry_ts: [* TO {epoch_to_iso(time.time())}]",
283
- rows=1, sort='expiry_ts asc', as_obj=False, fl='expiry_ts')
271
+ def _get_final_date(self):
272
+ now = now_as_iso()
273
+ if self.config.core.expiry.batch_delete:
274
+ final_date = dm(f"{now}||-{self.config.core.expiry.delay}h/d").float_timestamp
275
+ else:
276
+ final_date = dm(f"{now}||-{self.config.core.expiry.delay}h").float_timestamp
277
+ return epoch_to_iso(final_date)
278
+
279
+ def _get_next_chunk(self, collection: ESCollection, start, final_date):
280
+ """Find date of item at chunk size and the number of items that
281
+ will be affected in between start date and the date found"""
282
+ rows = collection.search(f"expiry_ts: {{{start} TO {final_date}]", rows=1,
283
+ offset=self.expiry_size - 1, sort='expiry_ts asc',
284
+ as_obj=False, fl='expiry_ts')
284
285
  if rows['items']:
285
- return iso_to_epoch(rows['items'][0]['expiry_ts'])
286
- return time.time()
287
-
288
- def _count_expired(self, container: ESCollection, start: Union[float, str], end: float) -> int:
289
- """Count how many items need to be erased in the given window."""
290
- if start == 0:
291
- start = '*'
292
- if isinstance(start, (float, int)):
293
- start = epoch_to_iso(start)
294
- query = f'expiry_ts:[{start} TO {epoch_to_iso(end)}}}'
295
- return container.search(query, rows=0, as_obj=False, track_total_hits=self.expiry_size)['total']
286
+ return rows['items'][0]['expiry_ts'], self.expiry_size
287
+ return final_date, rows['total']
296
288
 
297
289
  def try_run(self):
298
290
  while self.running:
299
291
  try:
300
- expiry_maxed_out = False
292
+ busy_iteration = False
301
293
 
302
294
  with ThreadPoolExecutor(self.config.core.expiry.workers) as pool:
303
295
  try:
304
- expiry_maxed_out = self.run_expiry_once(pool)
296
+ busy_iteration = self.run_expiry_once(pool)
305
297
  except Exception as e:
306
298
  self.log.exception(str(e))
307
299
 
308
- if not expiry_maxed_out:
300
+ if not busy_iteration:
309
301
  self.sleep_with_heartbeat(self.config.core.expiry.sleep_time)
310
302
 
311
303
  except BrokenProcessPool:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: assemblyline-core
3
- Version: 4.5.1.dev132
3
+ Version: 4.5.1.dev135
4
4
  Summary: Assemblyline 4 - Core components
5
5
  Home-page: https://github.com/CybercentreCanada/assemblyline-core/
6
6
  Author: CCCS Assemblyline development team
@@ -1 +0,0 @@
1
- 4.5.1.dev132