Skip to content

Commit

Permalink
Refactor element to area mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
bubelov committed Sep 12, 2024
1 parent f9b45bb commit a4f31df
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 67 deletions.
45 changes: 17 additions & 28 deletions src/area/service.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::collections::{HashMap, HashSet};

use super::Area;
use crate::{
area_element::model::AreaElement,
Expand All @@ -12,13 +10,13 @@ use geojson::GeoJson;
use rusqlite::Connection;
use serde::Serialize;
use serde_json::{Map, Value};
use std::collections::{HashMap, HashSet};
use time::OffsetDateTime;

pub fn insert(tags: Map<String, Value>, conn: &mut Connection) -> Result<Area> {
pub fn insert(tags: Map<String, Value>, conn: &Connection) -> Result<Area> {
if !tags.contains_key("geo_json") {
return Err(Error::HttpBadRequest("geo_json tag is missing".into()));
}
let sp = conn.savepoint()?;
let url_alias = tags
.get("url_alias")
.ok_or(Error::HttpBadRequest(
Expand All @@ -41,15 +39,14 @@ pub fn insert(tags: Map<String, Value>, conn: &mut Connection) -> Result<Area> {
if geo_json.is_err() {
Err(Error::HttpConflict("Invalid geo_json".into()))?
}
if Area::select_by_alias(url_alias, &sp)?.is_some() {
if Area::select_by_alias(url_alias, &conn)?.is_some() {
Err(Error::HttpConflict(
"This url_alias is already in use".into(),
))?
}
let area = Area::insert(tags, &sp)?;
let area_elements = element::service::find_in_area(&area, &sp)?;
element::service::update_areas_tag(&area_elements, &sp)?;
sp.commit()?;
let area = Area::insert(tags, &conn)?;
let area_elements = element::service::find_in_area(&area, conn)?;
element::service::generate_areas_mapping_old(&area_elements, conn)?;
Ok(area)
}

Expand All @@ -64,20 +61,14 @@ pub fn patch_tag(
patch_tags(id_or_alias, tags, conn)
}

pub fn patch_tags(
id_or_alias: &str,
tags: Map<String, Value>,
conn: &mut Connection,
) -> Result<Area> {
pub fn patch_tags(id_or_alias: &str, tags: Map<String, Value>, conn: &Connection) -> Result<Area> {
let area = Area::select_by_id_or_alias(id_or_alias, conn)?.unwrap();
if tags.contains_key("geo_json") {
let sp = conn.savepoint()?;
let area_elements = element::service::find_in_area(&area, &sp)?;
element::service::update_areas_tag(&area_elements, &sp)?;
let area = Area::patch_tags(area.id, tags, &sp)?;
let area_elements = element::service::find_in_area(&area, &sp)?;
element::service::update_areas_tag(&area_elements, &sp)?;
sp.commit()?;
let area_elements = element::service::find_in_area(&area, conn)?;
let area = Area::patch_tags(area.id, tags, conn)?;
element::service::generate_areas_mapping_old(&area_elements, conn)?;
let area_elements = element::service::find_in_area(&area, conn)?;
element::service::generate_areas_mapping_old(&area_elements, conn)?;
Ok(area)
} else {
Ok(Area::patch_tags(area.id, tags, conn)?)
Expand All @@ -94,13 +85,11 @@ pub fn remove_tag(area_id_or_alias: &str, tag_name: &str, conn: &mut Connection)
Ok(Area::remove_tag(area.id, tag_name, conn)?)
}

pub fn soft_delete(area_id_or_alias: &str, conn: &mut Connection) -> Result<Area> {
let sp = conn.savepoint()?;
let area = Area::select_by_id_or_alias(area_id_or_alias, &sp)?.unwrap();
let area_elements = element::service::find_in_area(&area, &sp)?;
let area = Area::set_deleted_at(area.id, Some(OffsetDateTime::now_utc()), &sp)?;
element::service::update_areas_tag(&area_elements, &sp)?;
sp.commit()?;
pub fn soft_delete(area_id_or_alias: &str, conn: &Connection) -> Result<Area> {
let area = Area::select_by_id_or_alias(area_id_or_alias, conn)?.unwrap();
let area_elements = element::service::find_in_area(&area, conn)?;
let area = Area::set_deleted_at(area.id, Some(OffsetDateTime::now_utc()), conn)?;
element::service::generate_areas_mapping_old(&area_elements, conn)?;
Ok(area)
}

Expand Down
1 change: 1 addition & 0 deletions src/area_element/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod model;
pub mod service;
37 changes: 37 additions & 0 deletions src/area_element/service.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use super::model::AreaElement;
use crate::{area::Area, element::Element};
use crate::{element, Result};
use rusqlite::Connection;
use time::OffsetDateTime;

pub struct Res {
pub has_changes: bool,
}

pub fn generate_areas_mapping(
element: &Element,
areas: &Vec<Area>,
conn: &Connection,
) -> Result<Res> {
let mut has_changes = false;
let element_areas = element::service::find_areas(&element, &areas)?;
let old_mappings = AreaElement::select_by_element_id(element.id, conn)?;
let mut old_area_ids: Vec<i64> = old_mappings.into_iter().map(|it| it.area_id).collect();
let mut new_area_ids: Vec<i64> = element_areas.into_iter().map(|it| it.id).collect();
old_area_ids.sort();
new_area_ids.sort();
if new_area_ids != old_area_ids {
for old_area_id in &old_area_ids {
if !new_area_ids.contains(&old_area_id) {
AreaElement::set_deleted_at(*old_area_id, Some(OffsetDateTime::now_utc()), conn)?;
}
}
for new_area_id in new_area_ids {
if !old_area_ids.contains(&new_area_id) {
AreaElement::insert(new_area_id, element.id, conn)?;
}
}
has_changes = true;
}
Ok(Res { has_changes })
}
4 changes: 2 additions & 2 deletions src/command/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ async fn process_elements(fresh_elements: Vec<OverpassElement>, mut db: Connecti
}

element::service::generate_issues(vec![&updated_element], &tx)?;
element::service::update_areas_tag(&vec![updated_element], &tx)?;
element::service::generate_areas_mapping_old(&vec![updated_element], &tx)?;
}

if cached_element.deleted_at.is_some() {
Expand Down Expand Up @@ -235,7 +235,7 @@ async fn process_elements(fresh_elements: Vec<OverpassElement>, mut db: Connecti
info!(category, android_icon);

element::service::generate_issues(vec![&element], &tx)?;
element::service::update_areas_tag(&vec![element], &tx)?;
element::service::generate_areas_mapping_old(&vec![element], &tx)?;

let message = format!("User {user_display_name} added https://www.openstreetmap.org/{element_type}/{osm_id}");
info!(
Expand Down
2 changes: 1 addition & 1 deletion src/command/update_areas_tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ pub fn run(args: Vec<String>) -> Result<()> {
let area = Area::select_by_id_or_alias(area_id_or_alias, &conn)?.unwrap();
info!(area.id, area_name = area.name(), area_alias = area.alias());
let area_elements = element::service::find_in_area(&area, &conn)?;
element::service::update_areas_tag(&area_elements, &conn)?;
element::service::generate_areas_mapping_old(&area_elements, &conn)?;
Ok(())
}
17 changes: 7 additions & 10 deletions src/element/service.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::Element;
use crate::area::Area;
use crate::area_element;
use crate::Result;
use geo::Contains;
use geo::LineString;
Expand Down Expand Up @@ -82,18 +83,15 @@ pub fn filter_by_area(all_elements: &Vec<Element>, area: &Area) -> Result<Vec<El
Ok(area_elements)
}

pub fn update_areas_tag(elements: &Vec<Element>, conn: &Connection) -> Result<Vec<Element>> {
pub fn generate_areas_mapping_old(
elements: &Vec<Element>,
conn: &Connection,
) -> Result<Vec<Element>> {
let mut res: Vec<Element> = vec![];

let all_areas: Vec<Area> = Area::select_all(None, &conn)?
.into_iter()
.filter(|it| it.deleted_at == None)
.collect();

let all_areas: Vec<Area> = Area::select_all(None, &conn)?;
for element in elements {
let element_areas = find_areas(element, &all_areas)?;
let element_areas = areas_to_areas_tag(element_areas);

let element = if element.tag("areas") != &element_areas {
info!(
element = element.id,
Expand All @@ -106,10 +104,9 @@ pub fn update_areas_tag(elements: &Vec<Element>, conn: &Connection) -> Result<Ve
info!(element = element.id, "No changes, skipping update");
element.clone()
};

area_element::service::generate_areas_mapping(&element, &all_areas, conn)?;
res.push(element);
}

Ok(res)
}

Expand Down
29 changes: 3 additions & 26 deletions src/rpc/generate_areas_elements_mapping.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
use crate::{
area::Area,
area_element::model::AreaElement,
area_element::{self},
auth::Token,
discord,
element::{self, Element},
element::Element,
Result,
};
use deadpool_sqlite::Pool;
use jsonrpc_v2::{Data, Params};
use rusqlite::Connection;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use time::OffsetDateTime;
use tracing::info;

#[derive(Deserialize)]
Expand Down Expand Up @@ -64,31 +63,9 @@ fn generate_areas_elements_mapping(
break;
}
let element = element.unwrap();
let element_areas = element::service::find_areas(&element, &areas)?;
let old_mappings = AreaElement::select_by_element_id(element_id, conn)?;
let mut old_area_ids: Vec<i64> = old_mappings.into_iter().map(|it| it.area_id).collect();
let mut new_area_ids: Vec<i64> = element_areas.into_iter().map(|it| it.id).collect();
old_area_ids.sort();
new_area_ids.sort();
let sp = conn.savepoint()?;
if new_area_ids != old_area_ids {
for old_area_id in &old_area_ids {
if !new_area_ids.contains(&old_area_id) {
AreaElement::set_deleted_at(
*old_area_id,
Some(OffsetDateTime::now_utc()),
&sp,
)?;
}
}
for new_area_id in new_area_ids {
if !old_area_ids.contains(&new_area_id) {
AreaElement::insert(new_area_id, element_id, &sp)?;
}
}
if area_element::service::generate_areas_mapping(&element, &areas, conn)?.has_changes {
elements_affected += 1;
}
sp.commit()?;
elements_processed += 1;
}
Ok(Res {
Expand Down

0 comments on commit a4f31df

Please sign in to comment.