Skip to content

Commit d969efb

Browse files
committed
instrument EPU Agent to send data to Core HTTP API
1 parent cc114ce commit d969efb

25 files changed

+1709
-675
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55

66
# smartem_decisions
77

8-
Project board: <https://github.com/orgs/DiamondLightSource/projects/33/views/1>
8+
- Project board: <https://github.com/orgs/DiamondLightSource/projects/33/views/1>
9+
- Test Datasets: https://gitlab.diamond.ac.uk/scisoft/cryoem/smartem-decisions-test-datasets
910

1011
This is where you should write a short paragraph that describes what your module does,
1112
how it does it, and why people should use it.

docs/software-architecture.mermaid

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,4 @@ graph LR
4444
class infrastructure infra
4545
class ext ext
4646
%% Link styling
47-
linkStyle 0,1,2,3,4,5,6,7,8 stroke:#666
47+
linkStyle 0,1,2,3,4,5,6,7,8 stroke:#666

setup.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#!/usr/bin/env python
22
"""Setup script to handle version file copying and dotenv instantiation."""
3+
34
import os
45
import shutil
56
from pathlib import Path
@@ -16,10 +17,7 @@ def copy_version_files():
1617
print(f"Warning: {source_file} does not exist, nothing to copy")
1718
return
1819

19-
target_files = [
20-
Path("src/smartem_decisions/_version.py"),
21-
Path("src/epu_data_intake/_version.py")
22-
]
20+
target_files = [Path("src/smartem_decisions/_version.py"), Path("src/epu_data_intake/_version.py")]
2321

2422
# Make sure target directories exist
2523
for target in target_files:
@@ -73,9 +71,9 @@ def run(self):
7371
setup(
7472
name="smartem-decisions", # Required for some setuptools versions
7573
cmdclass={
76-
'develop': CustomDevelop,
77-
'install': CustomInstall,
78-
'egg_info': CustomEggInfo,
74+
"develop": CustomDevelop,
75+
"install": CustomInstall,
76+
"egg_info": CustomEggInfo,
7977
},
8078
# We're using pyproject.toml for the rest
8179
)

src/epu_data_intake/__main__.py

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from pathlib import Path
99
from watchdog.observers import Observer
1010

11-
from src.epu_data_intake.data_model import EpuSession
11+
from src.epu_data_intake.data_model import EpuAcquisitionSessionStore
1212
from src.epu_data_intake.fs_parser import EpuParser
1313
from src.epu_data_intake.fs_watcher import (
1414
DEFAULT_PATTERNS,
@@ -23,7 +23,7 @@
2323
@parse_cli.command("dir")
2424
def parse_epu_output_dir(epu_output_dir: str):
2525
"""Parse an entire EPU output directory structure. May contain multiple grids"""
26-
datastore = EpuSession(epu_output_dir)
26+
datastore = EpuAcquisitionSessionStore(epu_output_dir)
2727
datastore = EpuParser.parse_epu_output_dir(datastore)
2828
logging.info(datastore)
2929

@@ -101,42 +101,42 @@ def validate_epu_dir(path: str):
101101

102102
@epu_data_intake_cli.command("watch")
103103
def watch_directory(
104-
path: Path = typer.Argument(..., help="Directory to watch"),
105-
patterns: list[str] = typer.Option(
106-
DEFAULT_PATTERNS,
107-
"--pattern", "-p",
108-
help="File patterns to watch (can be specified multiple times)"
109-
),
110-
# TODO currently unused because logging should come from `smartem_decisions` module,
111-
# and the log filename should be wired to `log_manager` instantiation once that's in place.
112-
log_file: str | None = typer.Option(
113-
"fs_changes.log",
114-
"--log-file", "-l",
115-
help="Log file path (optional)"
116-
),
117-
log_interval: float = typer.Option(
118-
10.0,
119-
"--interval", "-i",
120-
help="Minimum interval between log entries in seconds"
121-
),
122-
verbose: bool = typer.Option(
123-
False,
124-
"--verbose", "-v",
125-
help="Enable verbose output"
126-
),
104+
path: Path = typer.Argument(..., help="Directory to watch"),
105+
dry_run: bool = typer.Option(
106+
False, "--dry_run", "-n", "Enables dry run mode, writing data in-memory and not posting to Core's HTTP API"
107+
),
108+
# TODO provide via env but allow override via CLI, introduce a localhost default for local dev
109+
api_url: str = typer.Option(
110+
None, "--api-url", help="URL for the Core API (required unless in dry run mode)"
111+
),
112+
# TODO currently unused because logging should come from `~smartem_decisions~` `shared` module,
113+
# and the log filename should be wired to `log_manager` instantiation once that's in place.
114+
log_file: str | None = typer.Option("fs_changes.log", "--log-file", "-l", help="Log file path (optional)"),
115+
log_interval: float = typer.Option(
116+
10.0, "--interval", "-i", help="Minimum interval between log entries in seconds"
117+
),
118+
patterns: list[str] = typer.Option(
119+
DEFAULT_PATTERNS, "--pattern", "-p", help="File patterns to watch (can be specified multiple times)"
120+
),
121+
verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable verbose output"),
127122
):
128123
"""Watch directory for file changes and log them in JSON format."""
129124
path = Path(path).absolute()
130125
if not path.exists():
131126
logging.error(f"Error: Directory {path} does not exist")
132127
raise typer.Exit(1)
128+
129+
if not dry_run and not api_url:
130+
logging.error("Error: API URL must be provided when not in dry run mode")
131+
raise typer.Exit(1)
132+
133133
logging.info(f"Starting to watch directory: {str(path)} (including subdirectories) for patterns: {patterns}")
134134

135135
observer = Observer()
136136

137137
handler = RateLimitedHandler(patterns, log_interval, verbose)
138138
handler.set_watch_dir(path)
139-
handler.init_datastore()
139+
handler.init_datastore(dry_run, api_url)
140140

141141
logging.info("Parsing existing directory contents...")
142142
# TODO settle a potential race condition if one exists:
@@ -155,7 +155,7 @@ def handle_exit(signum, frame):
155155

156156
# Handle both CTRL+C and Windows signals
157157
signal.signal(signal.SIGINT, handle_exit)
158-
if platform.system() == 'Windows':
158+
if platform.system() == "Windows":
159159
signal.signal(signal.SIGBREAK, handle_exit)
160160

161161
observer.start()

0 commit comments

Comments
 (0)