|
10 | 10 | import pymongo |
11 | 11 | import traceback |
12 | 12 | from .utils import LazyObject, load_class_by_path |
13 | | -from itertools import count as itertools_count |
14 | 13 | from .config import get_config |
| 14 | +from .subpool import subpool_map, subpool_imap |
| 15 | + |
15 | 16 |
|
16 | 17 | # This should be MRQ's only Python object shared by all the jobs in the same process |
17 | 18 | _GLOBAL_CONTEXT = { |
@@ -202,121 +203,6 @@ def trace(*args): |
202 | 203 | greenlet.settrace(trace) # pylint: disable=no-member |
203 | 204 |
|
204 | 205 |
|
205 | | -def subpool_map(pool_size, func, iterable): |
206 | | - """ Starts a Gevent pool and run a map. Takes care of setting current_job and cleaning up. """ |
207 | | - |
208 | | - if not pool_size: |
209 | | - return [func(*args) for args in iterable] |
210 | | - |
211 | | - counter = itertools_count() |
212 | | - |
213 | | - current_job = get_current_job() |
214 | | - |
215 | | - def inner_func(*args): |
216 | | - """ As each call to 'func' will be done in a random greenlet of the subpool, we need to |
217 | | - register their IDs with set_current_job() to make get_current_job() calls work properly |
218 | | - inside 'func'. |
219 | | - """ |
220 | | - next(counter) |
221 | | - if current_job: |
222 | | - set_current_job(current_job) |
223 | | - |
224 | | - try: |
225 | | - ret = func(*args) |
226 | | - except Exception as exc: |
227 | | - trace = traceback.format_exc() |
228 | | - log.error("Error in subpool: %s \n%s" % (exc, trace)) |
229 | | - raise |
230 | | - |
231 | | - if current_job: |
232 | | - set_current_job(None) |
233 | | - return ret |
234 | | - |
235 | | - def inner_iterable(): |
236 | | - """ This will be called inside the pool's main greenlet, which ID also needs to be registered """ |
237 | | - if current_job: |
238 | | - set_current_job(current_job) |
239 | | - |
240 | | - for x in iterable: |
241 | | - yield x |
242 | | - |
243 | | - if current_job: |
244 | | - set_current_job(None) |
245 | | - |
246 | | - start_time = time.time() |
247 | | - pool = gevent.pool.Pool(size=pool_size) |
248 | | - ret = pool.map(inner_func, inner_iterable()) |
249 | | - pool.join(raise_error=True) |
250 | | - total_time = time.time() - start_time |
251 | | - |
252 | | - log.debug("SubPool ran %s greenlets in %0.6fs" % (counter, total_time)) |
253 | | - |
254 | | - return ret |
255 | | - |
256 | | - |
257 | | -def subpool_imap(pool_size, func, iterable, flatten=False, unordered=False, buffer_size=None): |
258 | | - """ Generator version of subpool_map. Should be used with unordered=True for optimal performance """ |
259 | | - |
260 | | - if not pool_size: |
261 | | - for args in iterable: |
262 | | - yield func(*args) |
263 | | - |
264 | | - counter = itertools_count() |
265 | | - |
266 | | - current_job = get_current_job() |
267 | | - |
268 | | - def inner_func(*args): |
269 | | - """ As each call to 'func' will be done in a random greenlet of the subpool, we need to |
270 | | - register their IDs with set_current_job() to make get_current_job() calls work properly |
271 | | - inside 'func'. |
272 | | - """ |
273 | | - next(counter) |
274 | | - if current_job: |
275 | | - set_current_job(current_job) |
276 | | - |
277 | | - try: |
278 | | - ret = func(*args) |
279 | | - except Exception as exc: |
280 | | - trace = traceback.format_exc() |
281 | | - log.error("Error in subpool: %s \n%s" % (exc, trace)) |
282 | | - raise |
283 | | - |
284 | | - if current_job: |
285 | | - set_current_job(None) |
286 | | - return ret |
287 | | - |
288 | | - def inner_iterable(): |
289 | | - """ This will be called inside the pool's main greenlet, which ID also needs to be registered """ |
290 | | - if current_job: |
291 | | - set_current_job(current_job) |
292 | | - |
293 | | - for x in iterable: |
294 | | - yield x |
295 | | - |
296 | | - if current_job: |
297 | | - set_current_job(None) |
298 | | - |
299 | | - start_time = time.time() |
300 | | - pool = gevent.pool.Pool(size=pool_size) |
301 | | - |
302 | | - if unordered: |
303 | | - iterator = pool.imap_unordered(inner_func, inner_iterable(), maxsize=buffer_size or pool_size) |
304 | | - else: |
305 | | - iterator = pool.imap(inner_func, inner_iterable()) |
306 | | - |
307 | | - for x in iterator: |
308 | | - if flatten: |
309 | | - for y in x: |
310 | | - yield y |
311 | | - else: |
312 | | - yield x |
313 | | - |
314 | | - pool.join(raise_error=True) |
315 | | - total_time = time.time() - start_time |
316 | | - |
317 | | - log.debug("SubPool ran %s greenlets in %0.6fs" % (counter, total_time)) |
318 | | - |
319 | | - |
320 | 206 | def run_task(path, params): |
321 | 207 | """ Runs a task code synchronously """ |
322 | 208 | task_class = load_class_by_path(path) |
|
0 commit comments