tidied up job creation a bit more

This commit is contained in:
PatchOfScotland
2023-02-01 15:04:06 +01:00
parent deb24f33ff
commit 5acb8c230e
7 changed files with 57 additions and 26 deletions

View File

@ -290,12 +290,12 @@ def create_event(event_type:str, path:str, source:dict[Any,Any]={}
def create_job(job_type:str, event:dict[str,Any], source:dict[Any,Any]={} def create_job(job_type:str, event:dict[str,Any], source:dict[Any,Any]={}
)->dict[Any,Any]: )->dict[Any,Any]:
job_dict = { job_dict = {
#TODO compress pattern, recipe, rule? #TODO compress event?
JOB_ID: generate_id(prefix="job_"), JOB_ID: generate_id(prefix="job_"),
JOB_EVENT: event, JOB_EVENT: event,
JOB_TYPE: job_type, JOB_TYPE: job_type,
JOB_PATTERN: event[WATCHDOG_RULE].pattern, JOB_PATTERN: event[WATCHDOG_RULE].pattern.name,
JOB_RECIPE: event[WATCHDOG_RULE].recipe, JOB_RECIPE: event[WATCHDOG_RULE].recipe.name,
JOB_RULE: event[WATCHDOG_RULE].name, JOB_RULE: event[WATCHDOG_RULE].name,
JOB_STATUS: STATUS_QUEUED, JOB_STATUS: STATUS_QUEUED,
JOB_CREATE_TIME: datetime.now(), JOB_CREATE_TIME: datetime.now(),

View File

@ -6,6 +6,7 @@ with monitors, handlers, and conductors being swappable at initialisation.
Author(s): David Marchant Author(s): David Marchant
""" """
import os
import sys import sys
import threading import threading
@ -15,10 +16,10 @@ from random import randrange
from typing import Any, Union from typing import Any, Union
from core.correctness.vars import DEBUG_WARNING, DEBUG_INFO, EVENT_TYPE, \ from core.correctness.vars import DEBUG_WARNING, DEBUG_INFO, EVENT_TYPE, \
VALID_CHANNELS, JOB_TYPE, JOB_ID VALID_CHANNELS, JOB_TYPE, JOB_ID, META_FILE
from core.correctness.validation import setup_debugging, check_type, \ from core.correctness.validation import setup_debugging, check_type, \
valid_list valid_list
from core.functionality import print_debug, wait from core.functionality import print_debug, wait, read_yaml
from core.meow import BaseHandler, BaseMonitor, BaseConductor from core.meow import BaseHandler, BaseMonitor, BaseConductor
@ -134,7 +135,7 @@ class MeowRunner:
"Could not process event as no relevent " "Could not process event as no relevent "
f"handler for '{event[EVENT_TYPE]}'", f"handler for '{event[EVENT_TYPE]}'",
DEBUG_INFO) DEBUG_INFO)
return continue
# If we've only one handler, use that # If we've only one handler, use that
if len(self.handlers[event[EVENT_TYPE]]) == 1: if len(self.handlers[event[EVENT_TYPE]]) == 1:
handler = self.handlers[event[EVENT_TYPE]][0] handler = self.handlers[event[EVENT_TYPE]][0]
@ -160,15 +161,23 @@ class MeowRunner:
else: else:
for from_handler in self.from_handlers: for from_handler in self.from_handlers:
if from_handler in ready: if from_handler in ready:
# Read event from the handler channel # Read job directory from the handler channel
message = from_handler.recv() job_dir = from_handler.recv()
job = message try:
metafile = os.path.join(job_dir, META_FILE)
job = read_yaml(metafile)
except Exception as e:
print_debug(self._print_target, self.debug_level,
"Could not load necessary job definitions for "
f"job at '{job_dir}'. {e}", DEBUG_INFO)
continue
# Abort if we don't have a relevent conductor. # Abort if we don't have a relevent conductor.
if not self.conductors[job[JOB_TYPE]]: if not self.conductors[job[JOB_TYPE]]:
print_debug(self._print_target, self.debug_level, print_debug(self._print_target, self.debug_level,
"Could not process job as no relevent " "Could not process job as no relevent "
f"conductor for '{job[JOB_TYPE]}'", DEBUG_INFO) f"conductor for '{job[JOB_TYPE]}'", DEBUG_INFO)
return continue
# If we've only one conductor, use that # If we've only one conductor, use that
if len(self.conductors[job[JOB_TYPE]]) == 1: if len(self.conductors[job[JOB_TYPE]]) == 1:
conductor = self.conductors[job[JOB_TYPE]][0] conductor = self.conductors[job[JOB_TYPE]][0]

View File

@ -140,12 +140,17 @@ class PapermillHandler(BaseHandler):
def setup_job(self, event:dict[str,Any], yaml_dict:dict[str,Any])->None: def setup_job(self, event:dict[str,Any], yaml_dict:dict[str,Any])->None:
"""Function to set up new job dict and send it to the runner to be """Function to set up new job dict and send it to the runner to be
executed.""" executed."""
meow_job = create_job(PYTHON_TYPE, event, { meow_job = create_job(
JOB_PARAMETERS:yaml_dict, PYTHON_TYPE,
JOB_HASH: event[WATCHDOG_HASH], event,
PYTHON_FUNC:job_func, {
PYTHON_OUTPUT_DIR:self.output_dir, JOB_PARAMETERS:yaml_dict,
PYTHON_EXECUTION_BASE:self.handler_base,}) JOB_HASH: event[WATCHDOG_HASH],
PYTHON_FUNC:job_func,
PYTHON_OUTPUT_DIR:self.output_dir,
PYTHON_EXECUTION_BASE:self.handler_base
}
)
print_debug(self._print_target, self.debug_level, print_debug(self._print_target, self.debug_level,
f"Creating job from event at {event[EVENT_PATH]} of type " f"Creating job from event at {event[EVENT_PATH]} of type "
f"{PYTHON_TYPE}.", DEBUG_INFO) f"{PYTHON_TYPE}.", DEBUG_INFO)
@ -180,7 +185,8 @@ class PapermillHandler(BaseHandler):
# update the status file with queued status # update the status file with queued status
write_yaml(meow_job, meta_file) write_yaml(meow_job, meta_file)
self.to_runner.send(meow_job) # Send job directory, as actual definitons will be read from within it
self.to_runner.send(job_dir)
# Papermill job execution code, to be run within the conductor # Papermill job execution code, to be run within the conductor
def job_func(job): def job_func(job):

View File

@ -270,3 +270,7 @@ class MeowTests(unittest.TestCase):
with self.assertRaises(Exception): with self.assertRaises(Exception):
lpc.execute(job_dict) lpc.execute(job_dict)
# TODO test job status funcs
# TODO test mangled status file reads
# TODO test missing input files

View File

@ -308,9 +308,9 @@ class CorrectnessTests(unittest.TestCase):
self.assertIn(JOB_TYPE, job_dict) self.assertIn(JOB_TYPE, job_dict)
self.assertEqual(job_dict[JOB_TYPE], PYTHON_TYPE) self.assertEqual(job_dict[JOB_TYPE], PYTHON_TYPE)
self.assertIn(JOB_PATTERN, job_dict) self.assertIn(JOB_PATTERN, job_dict)
self.assertEqual(job_dict[JOB_PATTERN], pattern) self.assertEqual(job_dict[JOB_PATTERN], pattern.name)
self.assertIn(JOB_RECIPE, job_dict) self.assertIn(JOB_RECIPE, job_dict)
self.assertEqual(job_dict[JOB_RECIPE], recipe) self.assertEqual(job_dict[JOB_RECIPE], recipe.name)
self.assertIn(JOB_RULE, job_dict) self.assertIn(JOB_RULE, job_dict)
self.assertEqual(job_dict[JOB_RULE], rule.name) self.assertEqual(job_dict[JOB_RULE], rule.name)
self.assertIn(JOB_STATUS, job_dict) self.assertIn(JOB_STATUS, job_dict)

View File

@ -12,7 +12,7 @@ from core.correctness.vars import EVENT_TYPE, WATCHDOG_BASE, WATCHDOG_RULE, \
RESULT_FILE RESULT_FILE
from core.correctness.validation import valid_job from core.correctness.validation import valid_job
from core.functionality import get_file_hash, create_job, create_event, \ from core.functionality import get_file_hash, create_job, create_event, \
make_dir, write_yaml, write_notebook make_dir, write_yaml, write_notebook, read_yaml
from core.meow import create_rules, create_rule from core.meow import create_rules, create_rule
from patterns.file_event_pattern import FileEventPattern, SWEEP_START, \ from patterns.file_event_pattern import FileEventPattern, SWEEP_START, \
SWEEP_STOP, SWEEP_JUMP SWEEP_STOP, SWEEP_JUMP
@ -156,10 +156,12 @@ class CorrectnessTests(unittest.TestCase):
ph.handle(event) ph.handle(event)
if from_handler_reader.poll(3): if from_handler_reader.poll(3):
job = from_handler_reader.recv() job_dir = from_handler_reader.recv()
self.assertIsNotNone(job[JOB_ID]) self.assertIsInstance(job_dir, str)
self.assertTrue(os.path.exists(job_dir))
job = read_yaml(os.path.join(job_dir, META_FILE))
valid_job(job) valid_job(job)
# Test PapermillHandler will create enough jobs from single sweep # Test PapermillHandler will create enough jobs from single sweep
@ -217,8 +219,13 @@ class CorrectnessTests(unittest.TestCase):
values = [0, 1, 2] values = [0, 1, 2]
self.assertEqual(len(jobs), 3) self.assertEqual(len(jobs), 3)
for job in jobs: for job_dir in jobs:
self.assertIsInstance(job_dir, str)
self.assertTrue(os.path.exists(job_dir))
job = read_yaml(os.path.join(job_dir, META_FILE))
valid_job(job) valid_job(job)
self.assertIn(JOB_PARAMETERS, job) self.assertIn(JOB_PARAMETERS, job)
self.assertIn("s", job[JOB_PARAMETERS]) self.assertIn("s", job[JOB_PARAMETERS])
if job[JOB_PARAMETERS]["s"] in values: if job[JOB_PARAMETERS]["s"] in values:
@ -291,8 +298,13 @@ class CorrectnessTests(unittest.TestCase):
"s1-0/s2-80", "s1-1/s2-80", "s1-2/s2-80", "s1-0/s2-80", "s1-1/s2-80", "s1-2/s2-80",
] ]
self.assertEqual(len(jobs), 15) self.assertEqual(len(jobs), 15)
for job in jobs: for job_dir in jobs:
self.assertIsInstance(job_dir, str)
self.assertTrue(os.path.exists(job_dir))
job = read_yaml(os.path.join(job_dir, META_FILE))
valid_job(job) valid_job(job)
self.assertIn(JOB_PARAMETERS, job) self.assertIn(JOB_PARAMETERS, job)
val1 = None val1 = None
val2 = None val2 = None
@ -305,8 +317,6 @@ class CorrectnessTests(unittest.TestCase):
val = f"{val1}/{val2}" val = f"{val1}/{val2}"
if val and val in values: if val and val in values:
values.remove(val) values.remove(val)
print([j[JOB_PARAMETERS] for j in jobs])
print(values)
self.assertEqual(len(values), 0) self.assertEqual(len(values), 0)
# Test jobFunc performs as expected # Test jobFunc performs as expected

View File

@ -359,3 +359,5 @@ class MeowTests(unittest.TestCase):
# TODO sweep tests # TODO sweep tests
# TODO adding tests with numpy # TODO adding tests with numpy
# TODO test getting job cannot handle
# TODO test getting event cannot handle