aboutsummaryrefslogtreecommitdiff
path: root/gn3/jobs.py
diff options
context:
space:
mode:
authorFrederick Muriuki Muriithi2023-04-17 14:42:05 +0300
committerFrederick Muriuki Muriithi2023-04-17 14:42:05 +0300
commit8af8105444522c2c71b5ddd36a550e964cddffbf (patch)
tree1ba8f2e7da47efd9cb878794f95cfbb35ab3f0ed /gn3/jobs.py
parent85abf12d364c626af9177deb0398849845bcc6c3 (diff)
downloadgenenetwork3-8af8105444522c2c71b5ddd36a550e964cddffbf.tar.gz
Hook up code to use external search script for phenotypes
Diffstat (limited to 'gn3/jobs.py')
-rw-r--r--gn3/jobs.py58
1 files changed, 58 insertions, 0 deletions
diff --git a/gn3/jobs.py b/gn3/jobs.py
new file mode 100644
index 0000000..8854a61
--- /dev/null
+++ b/gn3/jobs.py
@@ -0,0 +1,58 @@
+"""Handle external processes in a consistent manner."""
+import json
+from typing import Any
+from uuid import UUID, uuid4
+from datetime import datetime
+
+from redis import Redis
+
+from pymonad.either import Left, Right, Either
+
+JOBS_NAMESPACE = "GN3::JOBS"
+
+class InvalidCommand(Exception):
+ """Raise if the command to run is invalid."""
+
+def job_key(job_id: UUID, namespace_prefix: str = JOBS_NAMESPACE):
+ """Build the namespace key for a specific job."""
+ return f"{namespace_prefix}::{job_id}"
+
+def job(redisconn: Redis, job_id: UUID) -> Either:
+ """Retrive the job details of a job identified by `job_id`."""
+ the_job = redisconn.hgetall(job_key(job_id))
+ if the_job:
+ return Right({
+ **the_job,
+ "search_results": json.loads(the_job["search_results"])
+ })
+ return Left({
+ "error": "NotFound",
+ "error_description": f"Job '{job_id}' was not found."
+ })
+
+def __command_valid__(job_command: Any) -> Either:
+ if not isinstance(job_command, list):
+ return Left({
+ "error": "InvalidJobCommand",
+ "error_description": "The job command MUST be a list."
+ })
+ if not all((isinstance(val, str) for val in job_command)):
+ return Left({
+ "error": "InvalidJobCommand",
+ "error_description": "All parts of the command MUST be strings."
+ })
+ return Right(job_command)
+
+def create_job(redisconn: Redis, job_details: dict[str, Any]) -> UUID:
+ """Create a new job and put it on Redis."""
+ def __create__(_job_command):
+ job_id = job_details.get("job_id", uuid4())
+ redisconn.hset(job_key(job_id), mapping={
+ **job_details, "job_id": job_id, "created": datetime.now(), "stdout": "",
+ "stderr": "", "status": "queued"
+ })
+ return job_id
+ def __raise__(err):
+ raise InvalidCommand(err["error_description"])
+ return __command_valid__(job_details.get("command")).either(
+ __raise__, __create__)