-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #88 from smart-on-fhir/mikix/last-run
etl: add new context.json file in the PHI/build dir
- Loading branch information
Showing
6 changed files
with
185 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
""" | ||
ETL job context, holding some persistent state between runs. | ||
""" | ||
|
||
import datetime | ||
from typing import Optional | ||
|
||
from cumulus import common | ||
|
||
|
||
class JobContext: | ||
""" | ||
Context for an ETL job. | ||
This is not really settings or config in the sense of user-derived values. | ||
A prime example is "last successful run time" which the next run might want to use as part of its work | ||
(like to only extract the changed data since the last run) but is otherwise ephemeral information. | ||
Another possible (but not yet implemented) use might be to store some past config values, | ||
like the last used output format. To either give the user a chance to correct a mistake or to know | ||
how to change from one format to another. | ||
This is stored in the phi/build directory and is thus safe to store possible PHI. | ||
""" | ||
|
||
_LAST_SUCCESSFUL_DATETIME = 'last_successful_datetime' | ||
_LAST_SUCCESSFUL_INPUT_DIR = 'last_successful_input_dir' | ||
_LAST_SUCCESSFUL_OUTPUT_DIR = 'last_successful_output_dir' | ||
|
||
def __init__(self, path: str): | ||
""" | ||
:param path: path to context file | ||
""" | ||
self._path: str = path | ||
try: | ||
self._data = common.read_json(path) | ||
except (FileNotFoundError, PermissionError): | ||
self._data = {} | ||
|
||
@property | ||
def last_successful_datetime(self) -> Optional[datetime.datetime]: | ||
value = self._data.get(self._LAST_SUCCESSFUL_DATETIME) | ||
if value is not None: | ||
return datetime.datetime.fromisoformat(value) | ||
return None | ||
|
||
@last_successful_datetime.setter | ||
def last_successful_datetime(self, value: datetime.datetime) -> None: | ||
self._data[self._LAST_SUCCESSFUL_DATETIME] = value.isoformat() | ||
|
||
@property | ||
def last_successful_input_dir(self) -> Optional[str]: | ||
return self._data.get(self._LAST_SUCCESSFUL_INPUT_DIR) | ||
|
||
@last_successful_input_dir.setter | ||
def last_successful_input_dir(self, value: str) -> None: | ||
self._data[self._LAST_SUCCESSFUL_INPUT_DIR] = value | ||
|
||
@property | ||
def last_successful_output_dir(self) -> Optional[str]: | ||
return self._data.get(self._LAST_SUCCESSFUL_OUTPUT_DIR) | ||
|
||
@last_successful_output_dir.setter | ||
def last_successful_output_dir(self, value: str) -> None: | ||
self._data[self._LAST_SUCCESSFUL_OUTPUT_DIR] = value | ||
|
||
def save(self) -> None: | ||
common.write_json(self._path, self.as_json(), indent=4) # pretty-print this since it isn't large | ||
|
||
def as_json(self) -> dict: | ||
return dict(self._data) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
"""Tests for context.py""" | ||
|
||
import datetime | ||
import json | ||
import tempfile | ||
import unittest | ||
|
||
from cumulus.context import JobContext | ||
|
||
|
||
class TestJobContext(unittest.TestCase): | ||
"""Test case for JobContext""" | ||
|
||
def test_missing_file_context(self): | ||
context = JobContext('nope') | ||
self.assertEqual({}, context.as_json()) | ||
|
||
def test_save_and_load(self): | ||
with tempfile.NamedTemporaryFile(mode='w+') as f: | ||
json.dump({ | ||
'last_successful_input_dir': '/input/dir', | ||
}, f) | ||
f.flush() | ||
|
||
context = JobContext(f.name) | ||
self.assertEqual({ | ||
'last_successful_input_dir': '/input/dir', | ||
}, context.as_json()) | ||
|
||
context.last_successful_datetime = datetime.datetime(2008, 5, 1, 14, 30, 30, tzinfo=datetime.timezone.utc) | ||
self.assertEqual({ | ||
'last_successful_datetime': '2008-05-01T14:30:30+00:00', | ||
'last_successful_input_dir': '/input/dir', | ||
}, context.as_json()) | ||
|
||
context.save() | ||
context2 = JobContext(f.name) | ||
self.assertEqual(context.as_json(), context2.as_json()) | ||
|
||
def test_last_successful_props(self): | ||
context = JobContext('nope') | ||
context.last_successful_datetime = datetime.datetime(2008, 5, 1, 14, 30, 30, tzinfo=datetime.timezone.utc) | ||
context.last_successful_input_dir = '/input' | ||
context.last_successful_output_dir = '/output' | ||
self.assertEqual({ | ||
'last_successful_datetime': '2008-05-01T14:30:30+00:00', | ||
'last_successful_input_dir': '/input', | ||
'last_successful_output_dir': '/output', | ||
}, context.as_json()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters