Initial commit

This commit is contained in:
2020-06-20 16:55:48 -07:00
commit d317e63a00
2 changed files with 90 additions and 0 deletions

30
README.md Normal file
View 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
View 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