""""""
import importlib
import web
app = web.application(
__name__,
prefix="jobs",
args={
"job_module": r"[\w.]+",
"job_object": r"\w+",
"job_arghash": r"\w+",
"job_run_id": r"\!+",
},
model={
"job_signatures": {
"module": "TEXT",
"object": "TEXT",
"args": "BLOB",
"kwargs": "BLOB",
"arghash": "TEXT",
"unique": ("module", "object", "arghash"),
},
"job_runs": {
"job_signature_id": "INTEGER",
"job_id": "TEXT UNIQUE",
"created": """DATETIME NOT NULL
DEFAULT(STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW'))""",
"started": "DATETIME",
"finished": "DATETIME",
"start_time": "REAL",
"run_time": "REAL",
"status": "INTEGER",
"output": "TEXT",
},
"job_schedules": {
"job_signature_id": "INTEGER",
"minute": "TEXT",
"hour": "TEXT",
"day_of_month": "TEXT",
"month": "TEXT",
"day_of_week": "TEXT",
"unique": (
"job_signature_id",
"minute",
"hour",
"day_of_month",
"month",
"day_of_week",
),
},
},
)
@app.control("")
class Jobs:
""""""
owner_only = ["get"]
def get(self):
active = web.tx.db.select(
"job_runs AS jr",
join="job_signatures AS js ON js.rowid = jr.job_signature_id",
where="started IS NOT NULL AND finished IS NULL",
)
finished = web.tx.db.select(
"job_runs AS jr",
join="job_signatures AS js ON js.rowid = jr.job_signature_id",
where="finished IS NOT NULL",
order="finished DESC",
limit=20,
)
return app.view.index(active, finished)
@app.control("slow")
class SlowJobs:
""""""
owner_only = ["get"]
def get(self):
duration = web.form(duration=60).duration
slowest = web.tx.db.select(
"job_runs AS jr",
join="job_signatures AS js ON js.rowid = jr.job_signature_id",
where="finished IS NOT NULL AND run_time > ?",
vals=[duration],
order="run_time DESC",
)
return app.view.slow(slowest)
@app.control("schedules")
class Schedules:
""""""
owner_only = ["get"]
def get(self):
schedules = web.tx.db.select(
"job_schedules AS sc",
join="job_signatures AS si ON si.rowid = sc.job_signature_id",
)
return app.view.schedules(schedules)
@app.control("{job_module}")
class ByModule:
""""""
owner_only = ["get"]
def get(self, job_module):
jobs = web.tx.db.select(
"job_signatures",
what="rowid AS id, *",
where="module = ?",
vals=[job_module],
)
return app.view.by_module(job_module, jobs)
@app.control("{job_module}/{job_object}")
class ByObject:
""""""
owner_only = ["get"]
def get(self, job_module, job_object):
callable = getattr(importlib.import_module(job_module), job_object)
jobs = web.tx.db.select(
"job_signatures",
what="rowid AS id, *",
where="module = ? AND object = ?",
vals=[job_module, job_object],
)
return app.view.by_object(job_module, job_object, callable, jobs)
@app.control("{job_module}/{job_object}/{job_arghash}")
class Job:
""""""
owner_only = ["get"]
def get(self, job_module, job_object, job_arghash):
callable = getattr(importlib.import_module(job_module), job_object)
job = web.tx.db.select(
"job_signatures",
what="rowid AS id, *",
where="module = ? AND object = ? AND arghash LIKE ?",
vals=[job_module, job_object, job_arghash + "%"],
)[0]
runs = web.tx.db.select(
"job_runs",
where="job_signature_id = ?",
vals=[job["id"]],
order="finished DESC",
limit=100,
)
total = web.tx.db.select(
"job_runs",
what="count(*) AS count",
where="job_signature_id = ?",
vals=[job["id"]],
order="finished DESC",
)[0]["count"]
return app.view.job(job_module, job_object, callable, job, runs, total)
@app.control("{job_module}/{job_object}/{job_arghash}/{job_run_id}")
class JobRun:
""""""
owner_only = ["get"]
def get(self, job_module, job_object, job_arghash, job_run_id):
callable = getattr(importlib.import_module(job_module), job_object)
job = web.tx.db.select(
"job_signatures",
what="rowid AS id, *",
where="module = ? AND object = ? AND arghash LIKE ?",
vals=[job_module, job_object, job_arghash + "%"],
)[0]
run = web.tx.db.select(
"job_runs",
what="rowid, *",
where="job_id = ?",
vals=[job_run_id],
order="finished DESC",
)[0]
return app.view.run(job_module, job_object, callable, job, run)