threadmill 0.8.2__tar.gz → 0.8.4__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.
- {threadmill-0.8.2 → threadmill-0.8.4}/PKG-INFO +1 -1
- {threadmill-0.8.2 → threadmill-0.8.4}/threadmill/_version.py +3 -3
- {threadmill-0.8.2 → threadmill-0.8.4}/threadmill/executor.py +24 -27
- {threadmill-0.8.2 → threadmill-0.8.4}/LICENSE +0 -0
- {threadmill-0.8.2 → threadmill-0.8.4}/README.md +0 -0
- {threadmill-0.8.2 → threadmill-0.8.4}/pyproject.toml +0 -0
- {threadmill-0.8.2 → threadmill-0.8.4}/threadmill/__init__.py +0 -0
- {threadmill-0.8.2 → threadmill-0.8.4}/threadmill/apps.py +0 -0
- {threadmill-0.8.2 → threadmill-0.8.4}/threadmill/backends/__init__.py +0 -0
- {threadmill-0.8.2 → threadmill-0.8.4}/threadmill/backends/base.py +0 -0
- {threadmill-0.8.2 → threadmill-0.8.4}/threadmill/backends/lua/acknowledge.lua +0 -0
- {threadmill-0.8.2 → threadmill-0.8.4}/threadmill/backends/lua/acquire.lua +0 -0
- {threadmill-0.8.2 → threadmill-0.8.4}/threadmill/backends/lua/mover.lua +0 -0
- {threadmill-0.8.2 → threadmill-0.8.4}/threadmill/backends/lua/reaper.lua +0 -0
- {threadmill-0.8.2 → threadmill-0.8.4}/threadmill/backends/redis.py +0 -0
- {threadmill-0.8.2 → threadmill-0.8.4}/threadmill/exceptions.py +0 -0
- {threadmill-0.8.2 → threadmill-0.8.4}/threadmill/inspector/__init__.py +0 -0
- {threadmill-0.8.2 → threadmill-0.8.4}/threadmill/inspector/app.py +0 -0
- {threadmill-0.8.2 → threadmill-0.8.4}/threadmill/inspector/inspector.scss +0 -0
- {threadmill-0.8.2 → threadmill-0.8.4}/threadmill/inspector/screens.py +0 -0
- {threadmill-0.8.2 → threadmill-0.8.4}/threadmill/inspector/telemetry.py +0 -0
- {threadmill-0.8.2 → threadmill-0.8.4}/threadmill/management/__init__.py +0 -0
- {threadmill-0.8.2 → threadmill-0.8.4}/threadmill/management/commands/__init__.py +0 -0
- {threadmill-0.8.2 → threadmill-0.8.4}/threadmill/management/commands/threadmill.py +0 -0
- {threadmill-0.8.2 → threadmill-0.8.4}/threadmill/retry.py +0 -0
- {threadmill-0.8.2 → threadmill-0.8.4}/threadmill/signals.py +0 -0
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.8.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 8,
|
|
21
|
+
__version__ = version = '0.8.4'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 8, 4)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g071a4ce76'
|
|
@@ -12,7 +12,6 @@ import socket
|
|
|
12
12
|
import sys
|
|
13
13
|
import sysconfig
|
|
14
14
|
import threading
|
|
15
|
-
import time
|
|
16
15
|
import typing
|
|
17
16
|
from concurrent.futures import Future, ThreadPoolExecutor
|
|
18
17
|
from inspect import iscoroutinefunction
|
|
@@ -129,7 +128,12 @@ class TaskExecutor:
|
|
|
129
128
|
prefetch_count: int | None = None
|
|
130
129
|
poll_interval: datetime.timedelta = datetime.timedelta(seconds=0.01)
|
|
131
130
|
poll_max_interval: datetime.timedelta = datetime.timedelta(seconds=1)
|
|
132
|
-
|
|
131
|
+
shutdown_requested: threading.Event = dataclasses.field(
|
|
132
|
+
default_factory=threading.Event, init=False
|
|
133
|
+
)
|
|
134
|
+
pool_maintainer: threading.Thread | None = dataclasses.field(
|
|
135
|
+
default=None, init=False
|
|
136
|
+
)
|
|
133
137
|
worker_processes: list[WorkerProcess] = dataclasses.field(
|
|
134
138
|
default_factory=list, init=False
|
|
135
139
|
)
|
|
@@ -176,9 +180,10 @@ class TaskExecutor:
|
|
|
176
180
|
self.worker_processes = [
|
|
177
181
|
self.create_worker_process() for _ in range(self.process_count)
|
|
178
182
|
]
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
183
|
+
self.pool_maintainer = threading.Thread(
|
|
184
|
+
target=self.maintain_worker_pool, daemon=True
|
|
185
|
+
)
|
|
186
|
+
threads = [self.pool_maintainer]
|
|
182
187
|
if self.backend.broker_class:
|
|
183
188
|
self.broker = self.backend.broker_class(self.backend)
|
|
184
189
|
threads.append(self.broker)
|
|
@@ -189,17 +194,24 @@ class TaskExecutor:
|
|
|
189
194
|
thread.join()
|
|
190
195
|
|
|
191
196
|
def shutdown(self) -> None:
|
|
192
|
-
"""Stop queue consumption and
|
|
197
|
+
"""Stop pool maintenance first, then queue consumption and all workers."""
|
|
193
198
|
logger.info("Shutting down task executor")
|
|
199
|
+
self.shutdown_requested.set()
|
|
200
|
+
if (
|
|
201
|
+
self.pool_maintainer is not None
|
|
202
|
+
and self.pool_maintainer.is_alive()
|
|
203
|
+
# The maintainer calls shutdown() itself on exit_empty.
|
|
204
|
+
and self.pool_maintainer is not threading.current_thread()
|
|
205
|
+
):
|
|
206
|
+
self.pool_maintainer.join()
|
|
194
207
|
if self.broker is not None:
|
|
195
208
|
self.broker.shutdown()
|
|
196
209
|
with ThreadPoolExecutor(max_workers=self.process_count) as executor:
|
|
197
210
|
executor.map(lambda worker: worker.shutdown(), self.worker_processes)
|
|
198
|
-
self.is_publishing = False
|
|
199
211
|
|
|
200
212
|
def maintain_worker_pool(self) -> None:
|
|
201
|
-
"""Restart worker processes that have exited."""
|
|
202
|
-
while self.
|
|
213
|
+
"""Restart worker processes that have exited, until shutdown is requested."""
|
|
214
|
+
while not self.shutdown_requested.is_set():
|
|
203
215
|
all_dead = True
|
|
204
216
|
for index, worker in enumerate(self.worker_processes):
|
|
205
217
|
if worker.is_alive():
|
|
@@ -218,7 +230,7 @@ class TaskExecutor:
|
|
|
218
230
|
if all_dead and self.exit_empty:
|
|
219
231
|
self.shutdown()
|
|
220
232
|
return
|
|
221
|
-
|
|
233
|
+
self.shutdown_requested.wait(1)
|
|
222
234
|
|
|
223
235
|
|
|
224
236
|
class WorkerProcess(multiprocessing.Process):
|
|
@@ -414,11 +426,6 @@ class WorkerThread(threading.Thread):
|
|
|
414
426
|
|
|
415
427
|
def execute_task_result(self, task_result: TaskResult) -> TaskResult:
|
|
416
428
|
"""Execute task from task result and update result lifecycle state."""
|
|
417
|
-
logger.info(
|
|
418
|
-
"Executing task '%s@%s'",
|
|
419
|
-
task_result.id,
|
|
420
|
-
task_result.task.module_path,
|
|
421
|
-
)
|
|
422
429
|
started_at = timezone.now()
|
|
423
430
|
task_result = dataclasses.replace(
|
|
424
431
|
task_result,
|
|
@@ -430,7 +437,7 @@ class WorkerThread(threading.Thread):
|
|
|
430
437
|
|
|
431
438
|
try:
|
|
432
439
|
return_value = WorkerThread.call_task(task_result)
|
|
433
|
-
except Exception as exception:
|
|
440
|
+
except Exception as exception: # noqa: BLE001
|
|
434
441
|
task_result = dataclasses.replace(
|
|
435
442
|
task_result,
|
|
436
443
|
status=TaskResultStatus.FAILED,
|
|
@@ -440,11 +447,7 @@ class WorkerThread(threading.Thread):
|
|
|
440
447
|
],
|
|
441
448
|
finished_at=timezone.now(),
|
|
442
449
|
)
|
|
443
|
-
|
|
444
|
-
"Task '%s@%s' failed",
|
|
445
|
-
task_result.id,
|
|
446
|
-
task_result.task.module_path,
|
|
447
|
-
)
|
|
450
|
+
task_finished.send(TaskExecutor, task_result=task_result)
|
|
448
451
|
else:
|
|
449
452
|
task_result = dataclasses.replace(
|
|
450
453
|
task_result,
|
|
@@ -454,12 +457,6 @@ class WorkerThread(threading.Thread):
|
|
|
454
457
|
object.__setattr__(
|
|
455
458
|
task_result, "_return_value", normalize_json(return_value)
|
|
456
459
|
)
|
|
457
|
-
logger.info(
|
|
458
|
-
"Task '%s@%s' succeeded",
|
|
459
|
-
task_result.id,
|
|
460
|
-
task_result.task.module_path,
|
|
461
|
-
)
|
|
462
|
-
finally:
|
|
463
460
|
task_finished.send(TaskExecutor, task_result=task_result)
|
|
464
461
|
|
|
465
462
|
return task_result
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|