Initial commit
This commit is contained in:
30
README.md
Normal file
30
README.md
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# Go-Do
|
||||||
|
Implement a simple way to "toss" a job to be run
|
||||||
|
in parallel with your main application logic
|
||||||
|
and when you're ready to use the results of
|
||||||
|
that job query if it's finished.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from go_do import Do
|
||||||
|
|
||||||
|
## From a docker hub api bit of code.
|
||||||
|
|
||||||
|
def get_all(url):
|
||||||
|
"Retrieve all paged results"
|
||||||
|
rsp = urllib.request.urlopen(url)
|
||||||
|
while 200 <= int(rsp.getcode()) < 300:
|
||||||
|
data = json.loads(rsp.read())
|
||||||
|
url = data.get("next")
|
||||||
|
next = Do(urllib.request.urlopen, url) if url else None
|
||||||
|
for item in data['results']:
|
||||||
|
yield item
|
||||||
|
if next is None:
|
||||||
|
break
|
||||||
|
# If the result is not ready yet, wait for it.
|
||||||
|
rsp = next.wait_for_it()
|
||||||
|
print("Done")
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
60
go_do.py
Normal file
60
go_do.py
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
#!python3
|
||||||
|
"""
|
||||||
|
go_do.py
|
||||||
|
========
|
||||||
|
Implement a simple parallel work class.
|
||||||
|
"""
|
||||||
|
# Uses low level threading.
|
||||||
|
import sys
|
||||||
|
import _thread as _t
|
||||||
|
|
||||||
|
class NotReadyError(RuntimeError):
|
||||||
|
"Job is still running"
|
||||||
|
|
||||||
|
class Do:
|
||||||
|
"""
|
||||||
|
Easy to use multi-threading.
|
||||||
|
"""
|
||||||
|
_tid = None
|
||||||
|
_running = None
|
||||||
|
_result = None
|
||||||
|
_exc_info = None
|
||||||
|
|
||||||
|
def __init__(self, func, *args, **kwarg):
|
||||||
|
assert callable(func)
|
||||||
|
self._running = _t.allocate_lock()
|
||||||
|
self._tid = _t.start_new_thread(self.run, args, kwarg)
|
||||||
|
|
||||||
|
def run(self, func, args, kwarg):
|
||||||
|
"Acquire locks, start thread, return thread id"
|
||||||
|
self._running.acquire()
|
||||||
|
try:
|
||||||
|
self._result = func(*args, **kwarg)
|
||||||
|
except:
|
||||||
|
self._exc_info = sys.exc_info()
|
||||||
|
finally:
|
||||||
|
self._running.release()
|
||||||
|
|
||||||
|
def done(self):
|
||||||
|
"Return True if the job finished running"
|
||||||
|
return not self._running.locked()
|
||||||
|
|
||||||
|
def running(self):
|
||||||
|
"Return True if the job is still running"
|
||||||
|
return self._running.locked()
|
||||||
|
|
||||||
|
def wait_for_it(self, _timeout=-1):
|
||||||
|
"Wait for the result to be available"
|
||||||
|
if self._running.acquire(True, _timeout):
|
||||||
|
self._running.release()
|
||||||
|
return self._result
|
||||||
|
raise NotReadyError("Exceeded the timeout")
|
||||||
|
|
||||||
|
def result(self):
|
||||||
|
"Return the result if available, raise NotReadyError if not"
|
||||||
|
if self._running.acquire(False):
|
||||||
|
self._running.release()
|
||||||
|
return self._result
|
||||||
|
raise NotReadyError("Result is not ready yet")
|
||||||
|
|
||||||
|
# Fin
|
||||||
Reference in New Issue
Block a user