threadmill 0.8.1__tar.gz → 0.8.3__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.1 → threadmill-0.8.3}/PKG-INFO +1 -1
- {threadmill-0.8.1 → threadmill-0.8.3}/threadmill/_version.py +3 -3
- {threadmill-0.8.1 → threadmill-0.8.3}/threadmill/executor.py +29 -11
- {threadmill-0.8.1 → threadmill-0.8.3}/LICENSE +0 -0
- {threadmill-0.8.1 → threadmill-0.8.3}/README.md +0 -0
- {threadmill-0.8.1 → threadmill-0.8.3}/pyproject.toml +0 -0
- {threadmill-0.8.1 → threadmill-0.8.3}/threadmill/__init__.py +0 -0
- {threadmill-0.8.1 → threadmill-0.8.3}/threadmill/apps.py +0 -0
- {threadmill-0.8.1 → threadmill-0.8.3}/threadmill/backends/__init__.py +0 -0
- {threadmill-0.8.1 → threadmill-0.8.3}/threadmill/backends/base.py +0 -0
- {threadmill-0.8.1 → threadmill-0.8.3}/threadmill/backends/lua/acknowledge.lua +0 -0
- {threadmill-0.8.1 → threadmill-0.8.3}/threadmill/backends/lua/acquire.lua +0 -0
- {threadmill-0.8.1 → threadmill-0.8.3}/threadmill/backends/lua/mover.lua +0 -0
- {threadmill-0.8.1 → threadmill-0.8.3}/threadmill/backends/lua/reaper.lua +0 -0
- {threadmill-0.8.1 → threadmill-0.8.3}/threadmill/backends/redis.py +0 -0
- {threadmill-0.8.1 → threadmill-0.8.3}/threadmill/exceptions.py +0 -0
- {threadmill-0.8.1 → threadmill-0.8.3}/threadmill/inspector/__init__.py +0 -0
- {threadmill-0.8.1 → threadmill-0.8.3}/threadmill/inspector/app.py +0 -0
- {threadmill-0.8.1 → threadmill-0.8.3}/threadmill/inspector/inspector.scss +0 -0
- {threadmill-0.8.1 → threadmill-0.8.3}/threadmill/inspector/screens.py +0 -0
- {threadmill-0.8.1 → threadmill-0.8.3}/threadmill/inspector/telemetry.py +0 -0
- {threadmill-0.8.1 → threadmill-0.8.3}/threadmill/management/__init__.py +0 -0
- {threadmill-0.8.1 → threadmill-0.8.3}/threadmill/management/commands/__init__.py +0 -0
- {threadmill-0.8.1 → threadmill-0.8.3}/threadmill/management/commands/threadmill.py +0 -0
- {threadmill-0.8.1 → threadmill-0.8.3}/threadmill/retry.py +0 -0
- {threadmill-0.8.1 → threadmill-0.8.3}/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.3'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 8, 3)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g0ef712225'
|
|
@@ -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():
|
|
@@ -208,11 +220,17 @@ class TaskExecutor:
|
|
|
208
220
|
worker.join(timeout=0)
|
|
209
221
|
if self.exit_empty:
|
|
210
222
|
continue
|
|
211
|
-
|
|
223
|
+
try:
|
|
224
|
+
self.worker_processes[index] = self.create_worker_process()
|
|
225
|
+
except OSError as error:
|
|
226
|
+
# Keep the dead worker and retry on the next tick.
|
|
227
|
+
logger.warning(
|
|
228
|
+
"Unable to start worker-%d. Retrying ...", index, exc_info=error
|
|
229
|
+
)
|
|
212
230
|
if all_dead and self.exit_empty:
|
|
213
231
|
self.shutdown()
|
|
214
232
|
return
|
|
215
|
-
|
|
233
|
+
self.shutdown_requested.wait(1)
|
|
216
234
|
|
|
217
235
|
|
|
218
236
|
class WorkerProcess(multiprocessing.Process):
|
|
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
|