phase 1 complete
This commit is contained in:
+25
-34
@@ -55,13 +55,9 @@ pub async fn fetch_metadata(client: &Client, url: &str) -> Result<LookupMap> {
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if !resp.status().is_success() {
|
if !resp.status().is_success() {
|
||||||
|
let status = resp.status().as_u16();
|
||||||
let body = resp.text().await.unwrap_or_default();
|
let body = resp.text().await.unwrap_or_default();
|
||||||
return Err(IngestError::HttpError(reqwest::Error::from(
|
return Err(IngestError::ApiStatus { status, body });
|
||||||
std::io::Error::new(
|
|
||||||
std::io::ErrorKind::Other,
|
|
||||||
format!("API returned error: {}", body),
|
|
||||||
),
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let meta: MetadataResponse = resp.json().await?;
|
let meta: MetadataResponse = resp.json().await?;
|
||||||
@@ -194,14 +190,9 @@ pub async fn fetch_data(client: &Client, url: &str, query: &Query) -> Result<Dat
|
|||||||
let resp = client.post(url).json(query).send().await?;
|
let resp = client.post(url).json(query).send().await?;
|
||||||
|
|
||||||
if !resp.status().is_success() {
|
if !resp.status().is_success() {
|
||||||
|
let status = resp.status().as_u16();
|
||||||
let body = resp.text().await.unwrap_or_default();
|
let body = resp.text().await.unwrap_or_default();
|
||||||
warn!("API error response: {}", body);
|
return Err(IngestError::ApiStatus { status, body });
|
||||||
return Err(IngestError::HttpError(reqwest::Error::from(
|
|
||||||
std::io::Error::new(
|
|
||||||
std::io::ErrorKind::Other,
|
|
||||||
format!("API returned error: {}", body),
|
|
||||||
),
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let data: DataResponse = resp.json().await?;
|
let data: DataResponse = resp.json().await?;
|
||||||
@@ -323,7 +314,7 @@ pub fn parse_row(
|
|||||||
.unwrap_or_else(|| ("".to_string(), "".to_string()))
|
.unwrap_or_else(|| ("".to_string(), "".to_string()))
|
||||||
};
|
};
|
||||||
|
|
||||||
let (month_code, month_label) = get(DIM_MONTH);
|
let (month_code, _month_label) = get(DIM_MONTH);
|
||||||
let (species_code, species_label) = get(DIM_SPECIES);
|
let (species_code, species_label) = get(DIM_SPECIES);
|
||||||
let (gear_code, gear_label) = get(DIM_GEAR);
|
let (gear_code, gear_label) = get(DIM_GEAR);
|
||||||
let (zone_code, zone_label) = get(DIM_ZONE);
|
let (zone_code, zone_label) = get(DIM_ZONE);
|
||||||
@@ -451,61 +442,61 @@ mod tests {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Dimension order: measure, species, gear, zone, processing,
|
// Dimension order from API: month, species, gear, zone, processing,
|
||||||
// preservation, shipsize, month
|
// preservation, shipsize, measure
|
||||||
// Sizes: 2, 2, 1, 1, 1, 1, 1, 2 = 8 values
|
|
||||||
DataResponse {
|
DataResponse {
|
||||||
dataset: Dataset {
|
dataset: Dataset {
|
||||||
dimension: DimInfo {
|
dimension: DimInfo {
|
||||||
id: vec![
|
id: vec![
|
||||||
DIM_MEASURE.to_string(),
|
DIM_MONTH.to_string(),
|
||||||
DIM_SPECIES.to_string(),
|
DIM_SPECIES.to_string(),
|
||||||
DIM_GEAR.to_string(),
|
DIM_GEAR.to_string(),
|
||||||
DIM_ZONE.to_string(),
|
DIM_ZONE.to_string(),
|
||||||
DIM_PROCESSING.to_string(),
|
DIM_PROCESSING.to_string(),
|
||||||
DIM_PRESERVATION.to_string(),
|
DIM_PRESERVATION.to_string(),
|
||||||
DIM_SHIPSIZE.to_string(),
|
DIM_SHIPSIZE.to_string(),
|
||||||
DIM_MONTH.to_string(),
|
DIM_MEASURE.to_string(),
|
||||||
],
|
],
|
||||||
size: vec![2, 2, 1, 1, 1, 1, 1, 2],
|
size: vec![2, 2, 1, 1, 1, 1, 1, 2],
|
||||||
dimensions,
|
dimensions,
|
||||||
},
|
},
|
||||||
value: vec![
|
value: vec![
|
||||||
Some(1234.5), // MASS, Sild, ..., 2015M01
|
Some(1234.5), // 2015M01, Sild, ..., MASS
|
||||||
Some(2345.6), // MASS, Sild, ..., 2015M02
|
Some(2345.6), // 2015M01, Sild, ..., VALUE
|
||||||
Some(-1.0), // MASS, Þorskur, ..., 2015M01 (sentinel)
|
Some(-1.0), // 2015M01, Þorskur, ..., MASS (sentinel)
|
||||||
Some(3456.7), // MASS, Þorskur, ..., 2015M02
|
Some(3456.7), // 2015M01, Þorskur, ..., VALUE
|
||||||
Some(4567.8), // VALUE, Sild, ..., 2015M01
|
Some(4567.8), // 2015M02, Sild, ..., MASS
|
||||||
Some(5678.9), // VALUE, Sild, ..., 2015M02
|
Some(5678.9), // 2015M02, Sild, ..., VALUE
|
||||||
None, // VALUE, Þorskur, ..., 2015M01 (null)
|
None, // 2015M02, Þorskur, ..., MASS (null)
|
||||||
Some(6789.0), // VALUE, Þorskur, ..., 2015M02
|
Some(6789.0), // 2015M02, Þorskur, ..., VALUE
|
||||||
],
|
],
|
||||||
status: vec![],
|
status: vec![],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Test fixture: mock lookup maps with Faroese labels.
|
||||||
fn mock_lookup_maps() -> LookupMap {
|
fn mock_lookup_maps() -> LookupMap {
|
||||||
let mut maps = LookupMap::new();
|
let mut maps = LookupMap::new();
|
||||||
maps.insert(
|
maps.insert(
|
||||||
DIM_MONTH.to_string(),
|
"0".to_string(), // Tid / Month
|
||||||
HashMap::from([
|
HashMap::from([
|
||||||
("2015M01".to_string(), "Januar 2015".to_string()),
|
("2015M01".to_string(), "Januar 2015".to_string()),
|
||||||
("2015M02".to_string(), "Februar 2015".to_string()),
|
("2015M02".to_string(), "Februar 2015".to_string()),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
maps.insert(
|
maps.insert(
|
||||||
DIM_SPECIES.to_string(),
|
"1".to_string(), // Art / Species
|
||||||
HashMap::from([
|
HashMap::from([
|
||||||
("148XXXXXXX00000".to_string(), "Sild".to_string()),
|
("Sild".to_string(), "Sild".to_string()),
|
||||||
("183XXXXXXX00000".to_string(), "Þorskur".to_string()),
|
("Þorskur".to_string(), "Þorskur".to_string()),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
maps.insert(
|
maps.insert(
|
||||||
DIM_MEASURE.to_string(),
|
"7".to_string(), // Måleenhed / Measure
|
||||||
HashMap::from([
|
HashMap::from([
|
||||||
("MASS".to_string(), "Nøgd".to_string()),
|
("MASS".to_string(), "Kilo".to_string()),
|
||||||
("VALUE".to_string(), "Virði".to_string()),
|
("VALUE".to_string(), "Krónur".to_string()),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
maps
|
maps
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
mod ingest;
|
||||||
|
mod types;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("hagfish — not yet wired. Run tests with: cargo test");
|
println!("hagfish — not yet wired. Run tests with: cargo test");
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-3
@@ -251,17 +251,20 @@ pub enum IngestError {
|
|||||||
#[error("JSON parsing failed: {0}")]
|
#[error("JSON parsing failed: {0}")]
|
||||||
JsonError(#[from] serde_json::Error),
|
JsonError(#[from] serde_json::Error),
|
||||||
|
|
||||||
|
#[error("API returned status {status}: {body}")]
|
||||||
|
ApiStatus { status: u16, body: String },
|
||||||
|
|
||||||
#[error("Missing dimension in response: {0}")]
|
#[error("Missing dimension in response: {0}")]
|
||||||
MissingDimension(String),
|
MissingDimension(String),
|
||||||
|
|
||||||
#[error("Invalid value: {0}")]
|
#[error("Invalid value code: {0}")]
|
||||||
InvalidValueCode(String),
|
InvalidValueCode(String),
|
||||||
|
|
||||||
#[error("API returned empty data set")]
|
#[error("API returned empty data set")]
|
||||||
EmptyDataset,
|
EmptyDataset,
|
||||||
|
|
||||||
#[error("Dimension '{0}' not found in metadata")]
|
#[error("Unicode decode error: {0}")]
|
||||||
DimensionNotFound(String),
|
UnicodeError(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user