From 3f28b11be97ae0afd10b1aa08e297a31f23c4b6d Mon Sep 17 00:00:00 2001 From: PatchOfScotland Date: Fri, 14 Apr 2023 16:15:36 +0200 Subject: [PATCH] added a proper version of job update protection --- functionality/file_io.py | 19 +++++++++- tests/test_functionality.py | 69 ++++++++++++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/functionality/file_io.py b/functionality/file_io.py index 1737a66..7fd627e 100644 --- a/functionality/file_io.py +++ b/functionality/file_io.py @@ -12,6 +12,8 @@ from os import makedirs, remove, rmdir, walk from os.path import exists, isfile, join from typing import Any, Dict, List +from meow_base.core.vars import JOB_END_TIME, JOB_ERROR, JOB_STATUS, \ + STATUS_FAILED, STATUS_DONE, JOB_CREATE_TIME, JOB_START_TIME from meow_base.functionality.validation import valid_path @@ -131,7 +133,22 @@ def threadsafe_update_status(updates:dict[str,Any], filepath:str): try: status = read_yaml(filepath) - write_yaml({**status, **updates}, filepath) + for k, v in status.items(): + if k in updates: + # Do not overwrite final job status + if k == JOB_STATUS \ + and v in [STATUS_DONE, STATUS_FAILED]: + continue + # Do not overwrite an existing time + elif k in [JOB_START_TIME, JOB_CREATE_TIME, JOB_END_TIME]: + continue + # Do not overwrite an existing error messages + elif k == JOB_ERROR: + updates[k] = f"{v} {updates[k]}" + + status[k] = updates[k] + + write_yaml(status, filepath) except Exception as e: lock_handle.close() raise e diff --git a/tests/test_functionality.py b/tests/test_functionality.py index f951e80..746ba7a 100644 --- a/tests/test_functionality.py +++ b/tests/test_functionality.py @@ -15,7 +15,7 @@ from meow_base.core.rule import Rule from meow_base.core.vars import CHAR_LOWERCASE, CHAR_UPPERCASE, \ SHA256, EVENT_TYPE, EVENT_PATH, EVENT_TYPE_WATCHDOG, \ WATCHDOG_BASE, WATCHDOG_HASH, EVENT_RULE, JOB_PARAMETERS, \ - PYTHON_FUNC, JOB_ID, JOB_EVENT, \ + PYTHON_FUNC, JOB_ID, JOB_EVENT, JOB_ERROR, STATUS_DONE, \ JOB_TYPE, JOB_PATTERN, JOB_RECIPE, JOB_RULE, JOB_STATUS, JOB_CREATE_TIME, \ JOB_REQUIREMENTS, STATUS_QUEUED, JOB_TYPE_PAPERMILL from meow_base.functionality.debug import setup_debugging @@ -493,6 +493,73 @@ data""" self.assertEqual(data, expected_bytes) + def testThreadsafeUpdateProctectedStatus(self)->None: + first_yaml_dict = { + JOB_CREATE_TIME: "now", + JOB_STATUS: "Wham", + JOB_ERROR: "first error.", + JOB_ID: "id" + } + + filepath = os.path.join(TEST_MONITOR_BASE, "file.yaml") + + self.assertFalse(os.path.exists(filepath)) + threadsafe_write_status(first_yaml_dict, filepath) + self.assertTrue(os.path.exists(filepath)) + self.assertTrue(os.path.exists(f"{filepath}.lock")) + + status = threadsafe_read_status(filepath) + + self.assertEqual(first_yaml_dict, status) + + second_yaml_dict = { + JOB_CREATE_TIME: "changed", + JOB_STATUS: STATUS_DONE, + JOB_ERROR: "changed.", + JOB_ID: "changed" + } + + filepath = os.path.join(TEST_MONITOR_BASE, "file.yaml") + + threadsafe_update_status(second_yaml_dict, filepath) + self.assertTrue(os.path.exists(filepath)) + self.assertTrue(os.path.exists(f"{filepath}.lock")) + + status = threadsafe_read_status(filepath) + + expected_second_yaml_dict = { + JOB_CREATE_TIME: "now", + JOB_STATUS: STATUS_DONE, + JOB_ERROR: "first error. changed.", + JOB_ID: "changed" + } + + self.assertEqual(expected_second_yaml_dict, status) + + third_yaml_dict = { + JOB_CREATE_TIME: "editted", + JOB_STATUS: "editted", + JOB_ERROR: "editted.", + JOB_ID: "editted" + } + + filepath = os.path.join(TEST_MONITOR_BASE, "file.yaml") + + threadsafe_update_status(third_yaml_dict, filepath) + self.assertTrue(os.path.exists(filepath)) + self.assertTrue(os.path.exists(f"{filepath}.lock")) + + status = threadsafe_read_status(filepath) + + expected_third_yaml_dict = { + JOB_CREATE_TIME: "now", + JOB_STATUS: STATUS_DONE, + JOB_ERROR: "first error. changed. editted.", + JOB_ID: "editted" + } + + self.assertEqual(expected_third_yaml_dict, status) + class HashingTests(unittest.TestCase): def setUp(self)->None: