[enh] can cancel job

This commit is contained in:
Laurent Peuch 2018-07-15 09:47:39 +02:00
parent 757de9e27a
commit f87fcb560f
3 changed files with 68 additions and 1 deletions

View file

@ -24,6 +24,7 @@ class Job(peewee.Model):
('runnning', 'Running'),
('done', 'Done'),
('failure', 'Failure'),
('canceled', 'Canceled'),
), default="scheduled")
log = peewee.TextField(default="")

60
run.py
View file

@ -32,6 +32,12 @@ APPS_LIST = [OFFICAL_APPS_LIST, COMMUNITY_APPS_LIST]
subscriptions = defaultdict(list)
# this will have the form:
# jobs_in_memory_state = {
# some_job_id: {"worker": some_worker_id, "task": some_aio_task},
# }
jobs_in_memory_state = {}
def reset_pending_jobs():
Job.update(state="scheduled").where(Job.state == "running").execute()
@ -118,7 +124,10 @@ async def jobs_dispatcher():
worker.state = "busy"
worker.save()
asyncio.ensure_future(run_job(worker, job))
jobs_in_memory_state[job.id] = {
"worker": worker.id,
"task": asyncio.ensure_future(run_job(worker, job)),
}
async def run_job(worker, job):
@ -159,6 +168,9 @@ async def run_job(worker, job):
job.state = "done"
job.save()
# remove ourself from the state
del jobs_in_memory_state[job.id]
worker.state = "available"
worker.save()
@ -258,6 +270,52 @@ async def api_new_job(request):
return response.text("ok")
@app.route("/api/job/<job_id>/stop", methods=['POST'])
async def api_stop_job(request, job_id):
# TODO auth or some kind
job = Job.select().where(Job.id == job_id)
if job.count == 0:
raise NotFound()
job = job[0]
if job.state == "scheduled":
job.state = "canceled"
job.save()
await broadcast({
"action": "update_job",
"data": model_to_dict(job),
}, ["jobs", f"job-{job.id}"])
return response.text("ok")
if job.state == "running":
job.state = "canceled"
job.save()
jobs_in_memory_state[job.id]["task"].cancel()
worker = Worker.select().where(Worker.id == jobs_in_memory_state[job.id]["worker"])[0]
worker.state = "available"
worker.save()
await broadcast({
"action": "update_job",
"data": model_to_dict(job),
}, ["jobs", f"job-{job.id}"])
return response.text("ok")
if job.state in ("done", "canceled", "failure"):
# nothing to do, task is already done
return response.text("ok")
raise Exception(f"Tryed to cancel a job with an unknown state: {job.state}")
@app.route('/job/<job_id>')
async def job(request, job_id):
job = Job.select().where(Job.id == job_id)

View file

@ -7,6 +7,9 @@
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.1/css/bulma.min.css">
<script defer src="https://use.fontawesome.com/releases/v5.1.0/js/all.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.1/css/bulma.min.css"></script>
</head>
<body>
@ -14,6 +17,8 @@
<div class="container">
<h1 class="title">Job '{{job.name}}'</h1>
<button v-on:click="cancelJob">Cancel job</button>
<table class="table is-bordered">
<tr><th>State</th><td>{{job.state}}</td></tr>
<tr><th>Target revision</th><td>{{job.target_revision}}</td></tr>
@ -37,6 +42,9 @@
methods: {
timestampToDate: function (timestamp) {
return new Date(timestamp * 1000).toLocaleString()
},
cancelJob: function() {
$.post("/api/job/" + this.job.id + "/stop")
}
}
})