|
4 | 4 | import re |
5 | 5 | import time |
6 | 6 | from .utils import LazyObject |
| 7 | +from itertools import count as itertools_count |
7 | 8 |
|
8 | 9 |
|
9 | 10 | # greenletid => Job object |
|
19 | 20 |
|
20 | 21 | def set_current_job(job): |
21 | 22 | current = gevent.getcurrent() |
22 | | - _GREENLET_JOBS_REGISTRY[id(current)] = job |
23 | 23 |
|
24 | 24 | current.__dict__["_trace_time"] = 0 |
25 | 25 | current.__dict__["_trace_switches"] = 0 |
26 | 26 |
|
| 27 | + if job is None: |
| 28 | + if id(current) in _GREENLET_JOBS_REGISTRY: |
| 29 | + del _GREENLET_JOBS_REGISTRY[id(current)] |
| 30 | + else: |
| 31 | + _GREENLET_JOBS_REGISTRY[id(current)] = job |
| 32 | + |
27 | 33 |
|
28 | 34 | def get_current_job(greenlet_id=None): |
29 | 35 | if greenlet_id is None: |
@@ -199,3 +205,33 @@ def metric(name, incr=1, **kwargs): |
199 | 205 | cfg = get_current_config() |
200 | 206 | if cfg.get("metric_hook"): |
201 | 207 | return cfg.get("metric_hook")(name, incr=incr, **kwargs) |
| 208 | + |
| 209 | + |
| 210 | +def subpool_map(pool_size, func, iterable): |
| 211 | + """ Starts a Gevent pool and run a map. Takes care of setting current_job and cleaning up. """ |
| 212 | + |
| 213 | + if not pool_size: |
| 214 | + return [func(*args) for args in iterable] |
| 215 | + |
| 216 | + counter = itertools_count() |
| 217 | + |
| 218 | + current_job = get_current_job() |
| 219 | + |
| 220 | + def inner_func(*args): |
| 221 | + next(counter) |
| 222 | + if current_job: |
| 223 | + set_current_job(current_job) |
| 224 | + ret = func(*args) |
| 225 | + if current_job: |
| 226 | + set_current_job(None) |
| 227 | + return ret |
| 228 | + |
| 229 | + start_time = time.time() |
| 230 | + pool = gevent.pool.Pool(size=pool_size) |
| 231 | + ret = pool.map(inner_func, iterable) |
| 232 | + pool.join(raise_error=True) |
| 233 | + total_time = time.time() - start_time |
| 234 | + |
| 235 | + log.debug("SubPool ran %s greenlets in %0.6fs" % (counter, total_time)) |
| 236 | + |
| 237 | + return ret |
0 commit comments