Skip to content

Commit 1b9f83c

Browse files
authored
Use configurable root directory for fallback tracking
And implement locking in memory instead of relying on filesystem. Still won't protect against files being modified by external processes but simplifies preventing two requests interfering.
1 parent c96b12c commit 1b9f83c

9 files changed

+136
-175
lines changed

.sqlx/query-02d6faf0ffd8fb96031f7a8e824de4e4552ea72176c5e885cea3e517316e7774.json renamed to .sqlx/query-77054c7c20195a2a7766eb83bf39add56ec84bb502ce39d26cd9394703bdd71a.json

Lines changed: 4 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.sqlx/query-7b769dea685f49e8ff6d24a69e69e7037c1dc197db8bd273ec53e63a85e85351.json

Lines changed: 1 addition & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.sqlx/query-e45d346b58374c69e4f3bb59935719177993012eb03ce8f2d9bcca00290690be.json

Lines changed: 1 addition & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.sqlx/query-e671001b8f5b99f025043d31fcc036c58692913de6a6fd1ef4bdb8177f1235fa.json

Lines changed: 0 additions & 62 deletions
This file was deleted.

migrations/0001_init.up.sql

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,6 @@ CREATE TABLE beamline (
99
scan TEXT NOT NULL CHECK (length(scan) > 0),
1010
detector TEXT NOT NULL CHECK (length(detector) > 0),
1111

12-
fallback_directory TEXT,
13-
fallback_extension TEXT,
14-
15-
-- Ensure fallback number files don't collide
16-
UNIQUE(fallback_directory, fallback_extension),
17-
18-
-- Require a directory to be set if the extension is present
19-
CHECK (fallback_extension ISNULL OR fallback_directory NOTNULL)
12+
-- Override file tracker extension - defaults to beamline name
13+
fallback_extension TEXT
2014
);

src/cli.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ pub struct ServeOptions {
5858
/// The port to open for requests
5959
#[clap(short, long, default_value_t = 8000, env = "NUMTRACKER_PORT")]
6060
port: u16,
61+
/// The root directory for external number tracking
62+
#[clap(long, env = "NUMTRACKER_ROOT_DIRECTORY")]
63+
root_directory: Option<PathBuf>,
6164
}
6265

6366
#[derive(Debug, Args)]
@@ -110,6 +113,9 @@ impl ServeOptions {
110113
pub(crate) fn addr(&self) -> (Ipv4Addr, u16) {
111114
(self.host, self.port)
112115
}
116+
pub(crate) fn root_directory(&self) -> Option<PathBuf> {
117+
self.root_directory.clone()
118+
}
113119
}
114120

115121
impl TracingOptions {

src/db_service.rs

Lines changed: 18 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ pub struct BeamlineConfiguration {
6565
visit: RawPathTemplate<VisitTemplate>,
6666
scan: RawPathTemplate<ScanTemplate>,
6767
detector: RawPathTemplate<DetectorTemplate>,
68-
fallback: Option<NumtrackerConfig>,
68+
extension: Option<String>,
6969
}
7070

7171
impl BeamlineConfiguration {
@@ -77,8 +77,8 @@ impl BeamlineConfiguration {
7777
self.scan_number
7878
}
7979

80-
pub fn fallback(&self) -> Option<&NumtrackerConfig> {
81-
self.fallback.as_ref()
80+
pub fn extension(&self) -> Option<&str> {
81+
self.extension.as_deref()
8282
}
8383

8484
pub fn visit(&self) -> SqliteTemplateResult<BeamlineField> {
@@ -104,7 +104,6 @@ impl<'r> FromRow<'r, SqliteRow> for BeamlineConfiguration {
104104
scan: row.try_get::<String, _>("scan")?,
105105
detector: row.try_get::<String, _>("detector")?,
106106
fallback_extension: row.try_get::<Option<String>, _>("fallback_extension")?,
107-
fallback_directory: row.try_get::<Option<String>, _>("fallback_directory")?,
108107
}
109108
.into())
110109
}
@@ -117,7 +116,6 @@ pub struct BeamlineConfigurationUpdate {
117116
pub visit: Option<PathTemplate<BeamlineField>>,
118117
pub scan: Option<PathTemplate<ScanField>>,
119118
pub detector: Option<PathTemplate<DetectorField>>,
120-
pub directory: Option<String>,
121119
pub extension: Option<String>,
122120
}
123121

@@ -127,7 +125,6 @@ impl BeamlineConfigurationUpdate {
127125
&& self.visit.is_none()
128126
&& self.scan.is_none()
129127
&& self.detector.is_none()
130-
&& self.directory.is_none()
131128
&& self.extension.is_none()
132129
}
133130

@@ -160,10 +157,6 @@ impl BeamlineConfigurationUpdate {
160157
fields.push("detector=");
161158
fields.push_bind_unseparated(detector.to_string());
162159
}
163-
if let Some(dir) = &self.directory {
164-
fields.push("fallback_directory=");
165-
fields.push_bind_unseparated(dir);
166-
}
167160
if let Some(ext) = &self.extension {
168161
if ext != &self.name {
169162
// extension defaults to beamline name
@@ -194,7 +187,6 @@ impl BeamlineConfigurationUpdate {
194187
visit: self.visit.ok_or("visit")?.to_string(),
195188
scan: self.scan.ok_or("scan")?.to_string(),
196189
detector: self.detector.ok_or("detector")?.to_string(),
197-
fallback_directory: self.directory,
198190
fallback_extension: self.extension,
199191
};
200192
Ok(dbc.insert_into(db).await?)
@@ -207,7 +199,6 @@ impl BeamlineConfigurationUpdate {
207199
visit: None,
208200
scan: None,
209201
detector: None,
210-
directory: None,
211202
extension: None,
212203
}
213204
}
@@ -222,7 +213,6 @@ struct DbBeamlineConfig {
222213
visit: String,
223214
scan: String,
224215
detector: String,
225-
fallback_directory: Option<String>,
226216
fallback_extension: Option<String>,
227217
}
228218

@@ -234,16 +224,15 @@ impl DbBeamlineConfig {
234224
let bc = query_as!(
235225
DbBeamlineConfig,
236226
"INSERT INTO beamline
237-
(name, scan_number, visit, scan, detector, fallback_directory, fallback_extension)
227+
(name, scan_number, visit, scan, detector, fallback_extension)
238228
VALUES
239-
(?,?,?,?,?,?,?)
229+
(?,?,?,?,?,?)
240230
RETURNING *",
241231
self.name,
242232
self.scan_number,
243233
self.visit,
244234
self.scan,
245235
self.detector,
246-
self.fallback_directory,
247236
self.fallback_extension
248237
)
249238
.fetch_one(&db.pool)
@@ -254,24 +243,13 @@ impl DbBeamlineConfig {
254243

255244
impl From<DbBeamlineConfig> for BeamlineConfiguration {
256245
fn from(value: DbBeamlineConfig) -> Self {
257-
let fallback = match (value.fallback_directory, value.fallback_extension) {
258-
(None, _) => None,
259-
(Some(dir), None) => Some(NumtrackerConfig {
260-
directory: dir,
261-
extension: value.name.clone(),
262-
}),
263-
(Some(dir), Some(ext)) => Some(NumtrackerConfig {
264-
directory: dir,
265-
extension: ext,
266-
}),
267-
};
268246
Self {
269247
name: value.name,
270-
scan_number: u32::try_from(value.scan_number).expect("Run out of scan numbers"),
248+
scan_number: u32::try_from(value.scan_number).expect("Out of scan numbers"),
271249
visit: value.visit.into(),
272250
scan: value.scan.into(),
273251
detector: value.detector.into(),
274-
fallback,
252+
extension: value.fallback_extension,
275253
}
276254
}
277255
}
@@ -461,7 +439,6 @@ mod db_tests {
461439
"{subdirectory}/{instrument}-{scan_number}-{detector}",
462440
)
463441
.ok(),
464-
directory: Some("/tmp/trackers".into()),
465442
extension: Some("ext".into()),
466443
}
467444
}
@@ -506,16 +483,6 @@ mod db_tests {
506483
assert_eq!(bc.name(), "i22");
507484
}
508485

509-
#[rstest]
510-
#[test]
511-
async fn extension_requires_directory(mut update: BeamlineConfigurationUpdate) {
512-
let db = SqliteScanPathService::memory().await;
513-
update.directory = None;
514-
let e = err!(NewConfigurationError::Db, update.insert_new(&db));
515-
let e = *e.into_database_error().unwrap().downcast::<SqliteError>();
516-
assert_eq!(e.kind(), ErrorKind::CheckViolation)
517-
}
518-
519486
#[rstest]
520487
#[test]
521488
async fn read_only_db_propagates_errors(update: BeamlineConfigurationUpdate) {
@@ -597,11 +564,10 @@ mod db_tests {
597564
conf.detector().unwrap().to_string(),
598565
"{subdirectory}/{instrument}-{scan_number}-{detector}"
599566
);
600-
let Some(fb) = conf.fallback() else {
601-
panic!("Missing fallback configuration");
567+
let Some(ext) = conf.extension() else {
568+
panic!("Missing extension");
602569
};
603-
assert_eq!(fb.directory, "/tmp/trackers");
604-
assert_eq!(fb.extension, "ext");
570+
assert_eq!(ext, "ext");
605571
}
606572

607573
type Update = BeamlineConfigurationUpdate;
@@ -619,12 +585,9 @@ mod db_tests {
619585
#[case::scan_number(
620586
|u: &mut Update| u.scan_number = Some(42),
621587
|u: BeamlineConfiguration| assert_eq!(u.scan_number(), 42))]
622-
#[case::directory(
623-
|u: &mut Update| u.directory = Some("/new_trackers".into()),
624-
|u: BeamlineConfiguration| assert_eq!(u.fallback().unwrap().directory, "/new_trackers"))]
625588
#[case::extension(
626589
|u: &mut Update| u.extension = Some("new".into()),
627-
|u: BeamlineConfiguration| assert_eq!(u.fallback().unwrap().extension, "new"))]
590+
|u: BeamlineConfiguration| assert_eq!(u.extension().unwrap(), "new"))]
628591
#[tokio::test]
629592
async fn update_existing(
630593
#[future(awt)] db: SqliteScanPathService,
@@ -636,4 +599,11 @@ mod db_tests {
636599
let bc = ok!(upd.update_beamline(&db)).expect("Updated beamline missing");
637600
check(bc)
638601
}
602+
603+
#[rstest]
604+
#[tokio::test]
605+
async fn empty_update(#[future(awt)] db: SqliteScanPathService) {
606+
let upd = BeamlineConfigurationUpdate::empty("b21");
607+
assert!(ok!(upd.update_beamline(&db)).is_none());
608+
}
639609
}

0 commit comments

Comments
 (0)