python toy.py
curl -X PUT localhost:8080/[name]
curl localhost:8080/[name]
import subprocess | |
from concurrent.futures import ThreadPoolExecutor | |
from time import sleep | |
from aiohttp import web | |
def job_run(name): | |
if name.startswith("x"): | |
raise Exception("I don't like jobs that start with 'x'") | |
sleep(10) | |
return subprocess.run("cat", text=True, input=f"Hello from {name}", capture_output=True) | |
async def job_start(request): | |
jobs = request.app["jobs"] | |
pool = request.app["pool"] | |
job_id = request.match_info["job"] | |
if job_id not in jobs: | |
jobs[job_id] = pool.submit(job_run, job_id) | |
return await job_status(request) | |
async def job_status(request): | |
try: | |
job_id = request.match_info["job"] | |
job = request.app["jobs"][job_id] | |
except KeyError: | |
raise web.HTTPNotFound(text=f"No such job: {job_id}") | |
if job.running(): | |
return web.json_response({ | |
"status": "pending" | |
}) | |
if job.done(): | |
if (exc := job.exception()) is not None: | |
return web.json_response({ | |
"status": "failed", | |
"output": str(exc) | |
}) | |
return web.json_response({ | |
"status": "done", | |
"output": job.result().stdout | |
}) | |
return web.json_response({ | |
"status": "submitted" | |
}) | |
async def shutdown(app): | |
app["pool"].shutdown() | |
if __name__ == "__main__": | |
app = web.Application() | |
app.on_shutdown.append(shutdown) | |
app["jobs"] = {} | |
app["pool"] = ThreadPoolExecutor() | |
app.router.add_get("/{job}", job_status) | |
app.router.add_put("/{job}", job_start) | |
web.run_app(app) |