Tweaking find all metars
This commit is contained in:
2
.env
2
.env
@@ -28,7 +28,7 @@ MINIO_BROWSER_REDIRECT_URL=${NGINX_PROTOCOL}://${NGINX_HOST}:${NGINX_HTTP_PORT}/
|
||||
|
||||
UI_PORT=3000
|
||||
API_PORT=5000
|
||||
API_METAR_TIME_OFFSET=3000
|
||||
API_METAR_TIME_OFFSET=1800
|
||||
|
||||
SSL_CA_NAME=ca
|
||||
SSL_CA_PATH=../ssl/${SSL_CA_NAME}.pem
|
||||
|
||||
@@ -214,7 +214,7 @@ impl Airport {
|
||||
|
||||
let metar_fut = async {
|
||||
if metar {
|
||||
match Metar::find_all(client, &vec![icao.to_string()], &false).await {
|
||||
match Metar::find_all_distinct(client, &vec![icao.to_string()]).await {
|
||||
Ok(m) => Some(m.into_iter().nth(0)),
|
||||
Err(err) => {
|
||||
log::error!("{}", err);
|
||||
@@ -345,7 +345,7 @@ impl Airport {
|
||||
let runway_future = Runway::select_all_map(icaos.clone());
|
||||
let frequency_future = Frequency::select_all_map(icaos.clone());
|
||||
let metar_future = if query.metars.unwrap_or(false) {
|
||||
Some(Metar::find_all(client, &icaos, &false))
|
||||
Some(Metar::find_all_distinct(client, &icaos))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
@@ -3,20 +3,31 @@ use redis::{AsyncCommands, RedisResult};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::db::redis_async_connection;
|
||||
use crate::error::ApiResult;
|
||||
use crate::metars::Metar;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct MetarCheck {
|
||||
pub icao: String,
|
||||
pub status: bool,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub last_metar: Option<Metar>,
|
||||
}
|
||||
|
||||
impl MetarCheck {
|
||||
pub fn new(icao: String, status: bool) -> Self {
|
||||
Self {
|
||||
pub async fn new(icao: String, status: bool) -> Self {
|
||||
match Self::get(&icao).await {
|
||||
Some(c) => Self {
|
||||
icao,
|
||||
status,
|
||||
updated_at: Utc::now(),
|
||||
last_metar: c.last_metar,
|
||||
},
|
||||
None => Self {
|
||||
icao,
|
||||
status,
|
||||
updated_at: Utc::now(),
|
||||
last_metar: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ use crate::metars::MetarCheck;
|
||||
|
||||
const TABLE_NAME: &str = "metars";
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Metar {
|
||||
pub icao: String,
|
||||
pub raw_text: String,
|
||||
@@ -60,7 +60,7 @@ pub struct Metar {
|
||||
pub density_altitude: Option<f64>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum ReportModifier {
|
||||
#[serde(rename = "AUTO")]
|
||||
Auto,
|
||||
@@ -88,7 +88,7 @@ impl Display for ReportModifier {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct RunwayVisualRange {
|
||||
pub runway: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
@@ -110,7 +110,7 @@ impl Default for RunwayVisualRange {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum AutomatedStationType {
|
||||
#[serde(rename = "AO1")]
|
||||
WithoutPrecipitationDiscriminator,
|
||||
@@ -141,7 +141,7 @@ impl Display for AutomatedStationType {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Remarks {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub peak_wind: Option<PeakWind>,
|
||||
@@ -165,7 +165,7 @@ pub struct Remarks {
|
||||
pub sky_condition_at_secondary_location_not_available: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PeakWind {
|
||||
pub degrees: i32,
|
||||
pub speed: i32,
|
||||
@@ -190,7 +190,7 @@ impl Default for Remarks {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SkyCondition {
|
||||
pub sky_cover: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
@@ -209,7 +209,7 @@ impl Default for SkyCondition {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum FlightCategory {
|
||||
VFR,
|
||||
MVFR,
|
||||
@@ -993,10 +993,9 @@ impl Metar {
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn find_all(
|
||||
pub async fn find_all_distinct(
|
||||
client: &Client,
|
||||
icao_list: &Vec<String>,
|
||||
_force: &bool,
|
||||
icao_list: &Vec<String>
|
||||
) -> ApiResult<Vec<Self>> {
|
||||
if icao_list.is_empty() {
|
||||
return Ok(Vec::new());
|
||||
@@ -1017,9 +1016,9 @@ impl Metar {
|
||||
|
||||
let current_time = Utc::now().timestamp();
|
||||
let time_offset = env::var("API_METAR_TIME_OFFSET")
|
||||
.unwrap_or("3000".to_string())
|
||||
.unwrap_or("1800".to_string())
|
||||
.parse::<i64>()
|
||||
.unwrap_or(3000);
|
||||
.unwrap_or(1800);
|
||||
let short_time_offset: i64 = 300;
|
||||
|
||||
// Setup metars and missing metar structures
|
||||
@@ -1042,8 +1041,8 @@ impl Metar {
|
||||
};
|
||||
// If the metar was cached more than short_time_offset minutes ago, refresh it
|
||||
if refresh_seconds >= short_time_offset {
|
||||
log::trace!("{} METAR data is outdated, refreshing now", &icao);
|
||||
missing_metar_icaos.push(icao);
|
||||
log::trace!("{} METAR data is outdated, marked for refresh", &icao);
|
||||
missing_metar_icaos.push(icao.clone());
|
||||
}
|
||||
// Otherwise return outdated data and wait
|
||||
else {
|
||||
@@ -1058,7 +1057,7 @@ impl Metar {
|
||||
// Otherwise add the metar to the vector
|
||||
else {
|
||||
found_metar_icaos.insert(icao.clone());
|
||||
let metar_check = MetarCheck::new(icao, true);
|
||||
let metar_check = MetarCheck::new(icao, true).await;
|
||||
metar_check.insert(time_offset as u64).await?;
|
||||
metars.push(Metar::from_db(metar_row)?);
|
||||
}
|
||||
@@ -1092,21 +1091,29 @@ impl Metar {
|
||||
|
||||
if remote_metars.len() > 0 {
|
||||
// Insert missing METARs
|
||||
for remote_metar in &remote_metars {
|
||||
found_metar_icaos.insert(remote_metar.icao.to_string());
|
||||
let metar_check = MetarCheck::new(remote_metar.icao.clone(), true);
|
||||
metar_check.insert(time_offset as u64).await?;
|
||||
for remote_metar in remote_metars.clone() {
|
||||
remote_metar.insert().await?;
|
||||
found_metar_icaos.insert(remote_metar.icao.to_string());
|
||||
let mut metar_check = MetarCheck::new(remote_metar.icao.clone(), true).await;
|
||||
metar_check.last_metar = Some(remote_metar);
|
||||
metar_check.insert(time_offset as u64).await?;
|
||||
}
|
||||
metars.append(&mut remote_metars)
|
||||
metars.append(&mut remote_metars);
|
||||
}
|
||||
|
||||
// Update still missing metars
|
||||
let mut still_missing_metar_icaos: Vec<String> = vec![];
|
||||
// let mut still_missing_metar_icaos: Vec<String> = vec![];
|
||||
for difference in found_metar_icaos.symmetric_difference(&requested_icaos) {
|
||||
still_missing_metar_icaos.push(difference.to_string());
|
||||
let metar_check = MetarCheck::new(difference.to_string(), false);
|
||||
metar_check.insert(short_time_offset as u64).await?
|
||||
// still_missing_metar_icaos.push(difference.to_string());
|
||||
let metar_check = MetarCheck::new(difference.to_string(), false).await;
|
||||
metar_check.insert(short_time_offset as u64).await?;
|
||||
// Only add cached metar data if it's less than 4 hours old
|
||||
if let Some(last_metar) = metar_check.last_metar {
|
||||
let four_hours_ago = Utc::now() - chrono::Duration::hours(4);
|
||||
if last_metar.observation_time < four_hours_ago {
|
||||
metars.push(last_metar);
|
||||
}
|
||||
}
|
||||
}
|
||||
// if !still_missing_metar_icaos.is_empty() {
|
||||
// log::trace!("Still missing METAR data from {:?}", still_missing_metar_icaos);
|
||||
|
||||
@@ -7,7 +7,6 @@ use crate::AppState;
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct FindAllParameters {
|
||||
icaos: Option<String>,
|
||||
force: Option<bool>,
|
||||
}
|
||||
|
||||
#[get("metars")]
|
||||
@@ -19,10 +18,9 @@ async fn find_all(data: web::Data<AppState>, req: HttpRequest) -> HttpResponse {
|
||||
None => return HttpResponse::UnprocessableEntity().body("Missing icaos parameter"),
|
||||
};
|
||||
let icaos: Vec<String> = icao_string.split(',').map(|s| s.to_string()).collect();
|
||||
let force = ¶meters.force.unwrap_or(false);
|
||||
|
||||
let client = &data.client;
|
||||
let metars = match Metar::find_all(client, &icaos, force).await {
|
||||
let metars = match Metar::find_all_distinct(client, &icaos).await {
|
||||
Ok(a) => a,
|
||||
Err(err) => {
|
||||
error!("{}", err);
|
||||
|
||||
Reference in New Issue
Block a user