Skip to content

Commit

Permalink
editoast: add attached objects endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
flomonster committed Feb 17, 2023
1 parent f3fd9df commit a00fe81
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 0 deletions.
41 changes: 41 additions & 0 deletions editoast/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ info:
tags:
- name: infra
description: Infra
- name: routes
description: Operations related to infra routes
- name: pathfinding
description: Pathfinding operations
- name: layers
description: Map layers
- name: electrical_profiles
description: Electrical profiles

Expand Down Expand Up @@ -557,6 +563,41 @@ paths:
format: float
example: [750.0, 1500.0, 2500.50]

/infra/{id}/attached/{track_id}/:
get:
tags:
- infra
summary: Retrieve all objects attached to a given track
parameters:
- in: path
name: id
schema:
type: integer
description: Infra ID
required: true
- in: path
name: track_id
schema:
type: string
description: Track ID
required: true
responses:
200:
description: All objects attached to the given track (arranged by types)
content:
application/json:
schema:
type: object
additionalProperties:
type: array
items:
type: string
description: Object IDs
example:
Switch: ["switch.0", "switch.1"]
Detector: ["detector.0"]
BufferStop: []

/infra/{id}/routes/{waypoint_type}/{waypoint_id}/:
get:
tags:
Expand Down
1 change: 1 addition & 0 deletions editoast/src/infra_cache/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,7 @@ impl InfraCache {
}

/// Get all track sections references of a given track and type
/// If the track is not found, it returns an empty vector
pub fn get_track_refs_type(&self, track_id: &String, obj_type: ObjectType) -> Vec<&ObjectRef> {
self.track_sections_refs
.get(track_id)
Expand Down
1 change: 1 addition & 0 deletions editoast/src/schema/track_section.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use serde::{Deserialize, Serialize};
#[derivative(Default)]
pub struct TrackSection {
pub id: Identifier,
#[derivative(Default(value = "100."))]
pub length: f64,
pub slopes: Vec<Slope>,
pub curves: Vec<Curve>,
Expand Down
137 changes: 137 additions & 0 deletions editoast/src/views/infra/attached.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
use std::collections::HashMap;

use crate::error::Result;
use crate::infra::Infra;
use crate::infra_cache::InfraCache;
use crate::schema::ObjectType;
use crate::DbPool;
use actix_web::dev::HttpServiceFactory;
use actix_web::get;
use actix_web::web::{block, Data, Json, Path};
use chashmap::CHashMap;
use editoast_derive::EditoastError;
use serde_json::{json, Map, Value};
use thiserror::Error;

/// Objects types that can be attached to a track
const ATTACHED_OBJECTS_TYPES: &[ObjectType] = &[
ObjectType::Signal,
ObjectType::SpeedSection,
ObjectType::Detector,
ObjectType::TrackSectionLink,
ObjectType::Switch,
ObjectType::BufferStop,
ObjectType::OperationalPoint,
ObjectType::Catenary,
];

/// Return `/infra/<infra_id>/attached` routes
pub fn routes() -> impl HttpServiceFactory {
attached
}

#[derive(Debug, Error, EditoastError)]
#[editoast_error(base_id = "attached", context = "Self::context")]
enum AttachedError {
#[error("Track '{0}' not found")]
#[editoast_error(status = 404)]
TrackNotFound(String),
}

impl AttachedError {
fn context(&self) -> Map<String, Value> {
match self {
Self::TrackNotFound(track_id) => json!({
"track_id": track_id,
})
.as_object()
.cloned()
.unwrap(),
}
}
}

/// This endpoint returns attached objects of given track
#[get("/attached/{track_id}")]
async fn attached(
infra: Path<(i64, String)>,
infra_caches: Data<CHashMap<i64, InfraCache>>,
db_pool: Data<DbPool>,
) -> Result<Json<HashMap<ObjectType, Vec<String>>>> {
let (infra, track_id) = infra.into_inner();

block::<_, Result<_>>(move || {
let mut conn = db_pool.get().expect("Failed to get DB connection");
let infra = Infra::retrieve_for_update(&mut conn, infra)?;
let infra_cache = InfraCache::get_or_load(&mut conn, &infra_caches, &infra)?;
// Check track existence
if !infra_cache.track_sections().contains_key(&track_id) {
return Err(AttachedError::TrackNotFound(track_id.clone()).into());
}
// Get attached objects
let res: HashMap<_, Vec<_>> = ATTACHED_OBJECTS_TYPES
.iter()
.map(|obj_type| {
(
*obj_type,
infra_cache
.get_track_refs_type(&track_id, *obj_type)
.into_iter()
.map(|obj_ref| obj_ref.obj_id.clone())
.collect(),
)
})
.collect();
Ok(Json(res))
})
.await
.unwrap()
}

#[cfg(test)]
mod tests {
use std::collections::HashMap;

use actix_http::StatusCode;
use actix_web::test as actix_test;
use actix_web::test::{call_and_read_body_json, call_service, TestRequest};

use crate::infra::Infra;
use crate::schema::operation::RailjsonObject;
use crate::schema::{Detector, OSRDIdentified, ObjectType, TrackSection};
use crate::views::infra::tests::{
create_infra_request, create_object_request, delete_infra_request,
};
use crate::views::tests::create_test_service;

#[actix_test]
async fn get_attached_detector() {
let app = create_test_service().await;

let infra: Infra =
call_and_read_body_json(&app, create_infra_request("get_speed_tags_test")).await;

// Create a track and a detector on it
let track: RailjsonObject = TrackSection::default().into();
let req = create_object_request(infra.id, track.clone());
assert_eq!(call_service(&app, req).await.status(), StatusCode::OK);
let req = create_object_request(
infra.id,
Detector {
track: track.get_id().clone().into(),
..Default::default()
}
.into(),
);
assert_eq!(call_service(&app, req).await.status(), StatusCode::OK);

let req = TestRequest::get()
.uri(format!("/infra/{}/attached/{}/", infra.id, track.get_id()).as_str())
.to_request();
let response: HashMap<ObjectType, Vec<String>> = call_and_read_body_json(&app, req).await;
assert_eq!(response.get(&ObjectType::Detector).unwrap().len(), 1);

let response = call_service(&app, delete_infra_request(infra.id)).await;
assert_eq!(response.status(), StatusCode::NO_CONTENT);
}
}
2 changes: 2 additions & 0 deletions editoast/src/views/infra/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod attached;
mod edition;
mod errors;
mod objects;
Expand Down Expand Up @@ -52,6 +53,7 @@ pub fn routes() -> impl HttpServiceFactory {
objects::routes(),
routes::routes(),
pathfinding::routes(),
attached::routes(),
)),
)
}
Expand Down

0 comments on commit a00fe81

Please sign in to comment.