diff --git a/devservices/ingest-router.yaml b/devservices/ingest-router.yaml index 058bb41..7d2650e 100644 --- a/devservices/ingest-router.yaml +++ b/devservices/ingest-router.yaml @@ -20,7 +20,7 @@ ingest_router: locality_to_default_cell: "--monolith--": "--monolith--" - locales: + localities: "--monolith--": - id: "--monolith--" sentry_url: http://host.docker.internal:8000 @@ -33,35 +33,35 @@ ingest_router: method: POST action: handler: relay_project_configs - locale: "--monolith--" + locality: "--monolith--" - match: host: localhost path: /api/0/relays/live/ method: GET action: handler: health - locale: "--monolith--" + locality: "--monolith--" - match: host: localhost path: /api/0/relays/register/challenge/ method: POST action: handler: register_challenge - locale: "--monolith--" + locality: "--monolith--" - match: host: localhost path: /api/0/relays/register/response/ method: POST action: handler: register_response - locale: "--monolith--" + locality: "--monolith--" - match: host: localhost path: /api/0/relays/publickeys/ method: POST action: handler: public_keys - locale: "--monolith--" + locality: "--monolith--" metrics: statsd_host: "127.0.0.1" diff --git a/example_config_ingest_router.yaml b/example_config_ingest_router.yaml index 43b9ea6..cff6dbb 100644 --- a/example_config_ingest_router.yaml +++ b/example_config_ingest_router.yaml @@ -23,7 +23,7 @@ ingest_router: us: us1 de: de1 - locales: + localities: us: - id: us1 sentry_url: "http://10.0.0.1:8080" @@ -43,56 +43,56 @@ ingest_router: method: POST action: handler: relay_project_configs - locale: us + locality: us - match: host: de.sentry.io path: /api/0/relays/projectconfigs/ method: POST action: handler: relay_project_configs - locale: de + locality: de - match: host: us.sentry.io path: /api/0/relays/live/ method: GET action: handler: health - locale: us + locality: us - match: host: de.sentry.io path: /api/0/relays/live/ method: GET action: handler: health - locale: de + locality: de - match: host: us.sentry.io path: /api/0/relays/register/challenge/ method: POST action: handler: register_challenge - locale: us + locality: us - match: host: de.sentry.io path: /api/0/relays/register/challenge/ method: POST action: handler: register_challenge - locale: de + locality: de - match: host: us.sentry.io path: /api/0/relays/register/response/ method: POST action: handler: register_response - locale: us + locality: us - match: host: de.sentry.io path: /api/0/relays/register/response/ method: POST action: handler: register_response - locale: de + locality: de # Public keys endpoint - match: host: us.sentry.io @@ -100,14 +100,14 @@ ingest_router: method: POST action: handler: public_keys - locale: us + locality: us - match: host: de.sentry.io path: /api/0/relays/publickeys/ method: POST action: handler: public_keys - locale: de + locality: de # logging: diff --git a/ingest-router/src/api/any_cell_handler.rs b/ingest-router/src/api/any_cell_handler.rs index 5478272..74b5c33 100644 --- a/ingest-router/src/api/any_cell_handler.rs +++ b/ingest-router/src/api/any_cell_handler.rs @@ -1,7 +1,7 @@ use crate::api::utils::normalize_headers; use crate::errors::IngestRouterError; use crate::handler::{CellId, ExecutionMode, Handler, SplitMetadata}; -use crate::locale::Cells; +use crate::locality::Cells; use async_trait::async_trait; use http::StatusCode; use hyper::body::Bytes; @@ -103,12 +103,12 @@ impl Handler for AnyCellHandler { mod tests { use super::*; use crate::config::CellConfig; - use crate::locale::Locales; + use crate::locality::Localities; use std::collections::HashMap; use url::Url; fn create_test_cells() -> Cells { - let locales = HashMap::from([( + let localities = HashMap::from([( "us".to_string(), vec![ CellConfig { @@ -123,7 +123,7 @@ mod tests { }, ], )]); - Locales::new(locales).get_cells("us").unwrap() + Localities::new(localities).get_cells("us").unwrap() } #[tokio::test] diff --git a/ingest-router/src/api/project_config.rs b/ingest-router/src/api/project_config.rs index c3c5b65..63a5005 100644 --- a/ingest-router/src/api/project_config.rs +++ b/ingest-router/src/api/project_config.rs @@ -284,7 +284,7 @@ use crate::api::utils::{deserialize_body, normalize_headers, serialize_to_body}; use crate::errors::IngestRouterError; use crate::handler::{CellId, ExecutionMode, Handler, SplitMetadata}; -use crate::locale::Cells; +use crate::locality::Cells; use async_trait::async_trait; use http::StatusCode; use http::response::Parts; @@ -576,7 +576,7 @@ impl Handler for ProjectConfigsHandler { mod tests { use super::*; use crate::config::CellConfig; - use crate::locale::Locales; + use crate::locality::Localities; use crate::testutils::create_test_locator; use std::collections::HashMap; use url::Url; @@ -604,7 +604,7 @@ mod tests { ]); let locator = create_test_locator(key_to_cell).await; - let locales = HashMap::from([( + let localities = HashMap::from([( "us".to_string(), vec![ CellConfig { @@ -620,8 +620,8 @@ mod tests { ], )]); - let locales_obj = Locales::new(locales); - let cells = locales_obj.get_cells("us").unwrap(); + let localities_obj = Localities::new(localities); + let cells = localities_obj.get_cells("us").unwrap(); let handler = ProjectConfigsHandler::new(locator); @@ -653,7 +653,7 @@ mod tests { ]); let locator = create_test_locator(key_to_cell).await; let handler = ProjectConfigsHandler::new(locator); - let locales = HashMap::from([( + let localities = HashMap::from([( "us".to_string(), vec![ CellConfig { @@ -668,8 +668,8 @@ mod tests { }, ], )]); - let locales_obj = Locales::new(locales); - let cells = locales_obj.get_cells("us").unwrap(); + let localities_obj = Localities::new(localities); + let cells = localities_obj.get_cells("us").unwrap(); let request2 = build_request(ProjectConfigsRequest { public_keys: vec!["key1".to_string(), "key2".to_string(), "key3".to_string()], extra_fields: extra.clone(), @@ -704,7 +704,7 @@ mod tests { async fn test_split_request_unknown_key_goes_to_pending() { let key_to_cell = HashMap::from([("key1".to_string(), "us1".to_string())]); let locator = create_test_locator(key_to_cell).await; - let locales = HashMap::from([( + let localities = HashMap::from([( "us".to_string(), vec![CellConfig { id: "us1".to_string(), @@ -713,8 +713,8 @@ mod tests { }], )]); - let locales_obj = Locales::new(locales); - let cells = locales_obj.get_cells("us").unwrap(); + let localities_obj = Localities::new(localities); + let cells = localities_obj.get_cells("us").unwrap(); let handler = ProjectConfigsHandler::new(locator); diff --git a/ingest-router/src/config.rs b/ingest-router/src/config.rs index 5a89369..18a0542 100644 --- a/ingest-router/src/config.rs +++ b/ingest-router/src/config.rs @@ -10,8 +10,8 @@ pub enum ValidationError { #[error("Port cannot be 0")] InvalidPort, - #[error("Route action references unknown locale: {0}")] - UnknownLocale(String), + #[error("Route action references unknown locality: {0}")] + UnknownLocality(String), #[error("Duplicate upstream id: {0}")] DuplicateUpstream(String), @@ -19,11 +19,11 @@ pub enum ValidationError { #[error("Empty upstream id")] EmptyUpstreamId, - #[error("Empty locale in action")] - EmptyLocale, + #[error("Empty locality in action")] + EmptyLocality, - #[error("Locale '{0}' has no valid cells (none of its cells match any upstream)")] - LocaleHasNoValidCells(String), + #[error("Locality '{0}' has no valid cells (none of its cells match any upstream)")] + LocalityHasNoValidCells(String), #[error("Invalid timeout configuration: {0}")] InvalidTimeouts(String), @@ -114,7 +114,7 @@ impl RelayTimeouts { } /// Cell/upstream configuration -/// Note: The cell id is the HashMap key in Config.locales +/// Note: The cell id is the HashMap key in Config.localities #[derive(Clone, Debug, Deserialize, PartialEq)] pub struct CellConfig { /// Identifier of the cell @@ -180,7 +180,7 @@ pub struct Config { pub admin_listener: AdminListener, /// Cells are stored as a Vec to maintain priority order - the first cell /// in the list has highest priority for global config responses. - pub locales: HashMap>, + pub localities: HashMap>, /// Request routing rules pub routes: Vec, /// Locator service configuration @@ -199,11 +199,11 @@ impl Config { self.relay_timeouts.validate()?; - // Validate locales and cells - for (locale, cells) in &self.locales { - // Check that locale has at least one cell + // Validate localities and cells + for (locality, cells) in &self.localities { + // Check that locality has at least one cell if cells.is_empty() { - return Err(ValidationError::LocaleHasNoValidCells(locale.clone())); + return Err(ValidationError::LocalityHasNoValidCells(locality.clone())); } // Check for empty cell ids and collect for duplicate checking @@ -218,13 +218,13 @@ impl Config { } } - // Collect valid locales - let valid_locales: HashSet<&String> = self.locales.keys().collect(); + // Collect valid localities + let valid_localities: HashSet<&String> = self.localities.keys().collect(); for r in &self.routes { - // Validate that action locale exists - if valid_locales.is_empty() || !valid_locales.contains(&r.locale) { - return Err(ValidationError::UnknownLocale(r.locale.clone())); + // Validate that action locality exists + if valid_localities.is_empty() || !valid_localities.contains(&r.locality) { + return Err(ValidationError::UnknownLocality(r.locality.clone())); } } @@ -294,8 +294,8 @@ pub struct Route { pub r#match: Match, /// Action to take when the match conditions are met pub action: HandlerAction, - // Locale that the route applies to - pub locale: String, + // Locality that the route applies to + pub locality: String, } /// Request matching criteria @@ -325,7 +325,7 @@ admin_listener: locator: type: url url: "http://localhost:8000" -locales: +localities: us: - id: us1 sentry_url: "http://127.0.0.1:8080" @@ -344,12 +344,12 @@ routes: method: POST action: handler: relay_project_configs - locale: us + locality: us - match: path: /api/0/relays/live/ action: handler: health - locale: us + locality: us "#; let config: Config = serde_yaml::from_str(yaml).unwrap(); @@ -357,11 +357,11 @@ routes: // Verify key config values assert_eq!(config.listener.port, 3000); - assert_eq!(config.locales.len(), 2); - assert_eq!(config.locales.get("us").unwrap().len(), 2); - assert_eq!(config.locales.get("de").unwrap().len(), 1); - assert_eq!(config.locales.get("us").unwrap()[0].id, "us1"); - assert_eq!(config.locales.get("us").unwrap()[1].id, "us2"); + assert_eq!(config.localities.len(), 2); + assert_eq!(config.localities.get("us").unwrap().len(), 2); + assert_eq!(config.localities.get("de").unwrap().len(), 1); + assert_eq!(config.localities.get("us").unwrap()[0].id, "us1"); + assert_eq!(config.localities.get("us").unwrap()[1].id, "us2"); assert_eq!(config.routes.len(), 2); assert_eq!(config.routes[0].r#match.method, Some(HttpMethod::Post)); assert_eq!(config.routes[1].r#match.host, None); @@ -378,7 +378,7 @@ routes: host: "127.0.0.1".to_string(), port: 3001, }, - locales: HashMap::from([( + localities: HashMap::from([( "us".to_string(), vec![CellConfig { id: "us1".to_string(), @@ -394,7 +394,7 @@ routes: method: None, }, action: HandlerAction::RelayProjectConfigs, - locale: "us".to_string(), + locality: "us".to_string(), }], locator: Locator { r#type: LocatorType::Url { @@ -413,7 +413,7 @@ routes: // Test empty cell id let mut config = base_config.clone(); - config.locales.get_mut("us").unwrap().push(CellConfig { + config.localities.get_mut("us").unwrap().push(CellConfig { id: "".to_string(), sentry_url: Url::parse("http://10.0.0.2:8080").unwrap(), relay_url: Url::parse("http://10.0.0.2:8090").unwrap(), @@ -425,7 +425,7 @@ routes: // Test duplicate cell id let mut config = base_config.clone(); - config.locales.get_mut("us").unwrap().push(CellConfig { + config.localities.get_mut("us").unwrap().push(CellConfig { id: "us1".to_string(), sentry_url: Url::parse("http://10.0.0.2:8080").unwrap(), relay_url: Url::parse("http://10.0.0.2:8090").unwrap(), @@ -435,22 +435,20 @@ routes: ValidationError::DuplicateUpstream(_) )); - // Test unknown locale in action + // Test unknown locality in action let mut config = base_config.clone(); - config.routes[0].locale = "invalid".to_string(); + config.routes[0].locality = "invalid".to_string(); assert!(matches!( config.validate().unwrap_err(), - ValidationError::UnknownLocale(_) + ValidationError::UnknownLocality(_) )); - // Test locale with no cells + // Test locality with no cells let mut config = base_config.clone(); - config - .locales - .insert("invalid_locale".to_string(), Vec::new()); + config.localities.insert("locality".to_string(), Vec::new()); assert!(matches!( config.validate().unwrap_err(), - ValidationError::LocaleHasNoValidCells(_) + ValidationError::LocalityHasNoValidCells(_) )); // Test invalid timeouts: task_initial < http @@ -486,7 +484,7 @@ routes: r#" listener: {host: "0.0.0.0", port: 3000} admin_listener: {host: "127.0.0.1", port: 3001} -locale_to_cells: {us: [us1]} +locality_to_cells: {us: [us1]} upstreams: [{id: us1, sentry_url: "not-a-url", relay_url: "http://127.0.0.1:8090"}] routes: [] "# diff --git a/ingest-router/src/executor.rs b/ingest-router/src/executor.rs index 56a270d..d92ac64 100644 --- a/ingest-router/src/executor.rs +++ b/ingest-router/src/executor.rs @@ -2,7 +2,7 @@ use crate::config::RelayTimeouts; use crate::errors::IngestRouterError; use crate::handler::{CellId, ExecutionMode, Handler}; use crate::http::send_to_upstream; -use crate::locale::Cells; +use crate::locality::Cells; use crate::metrics_defs::UPSTREAM_REQUEST_DURATION; use http::StatusCode; use http_body_util::Full; diff --git a/ingest-router/src/handler.rs b/ingest-router/src/handler.rs index a510a6c..c4bd9c7 100644 --- a/ingest-router/src/handler.rs +++ b/ingest-router/src/handler.rs @@ -1,5 +1,5 @@ use crate::errors::IngestRouterError; -use crate::locale::Cells; +use crate::locality::Cells; use async_trait::async_trait; use hyper::body::Bytes; use hyper::{Request, Response}; diff --git a/ingest-router/src/ingest_router_service.rs b/ingest-router/src/ingest_router_service.rs index aa27b8e..d371e95 100644 --- a/ingest-router/src/ingest_router_service.rs +++ b/ingest-router/src/ingest_router_service.rs @@ -153,7 +153,7 @@ mod tests { method: Some(HttpMethod::Post), }, action: HandlerAction::RelayProjectConfigs, - locale: "us".to_string(), + locality: "us".to_string(), }, Route { r#match: Match { @@ -162,11 +162,11 @@ mod tests { method: Some(HttpMethod::Get), }, action: HandlerAction::Health, - locale: "us".to_string(), + locality: "us".to_string(), }, ]; - let locales = HashMap::from([( + let localities = HashMap::from([( "us".to_string(), vec![CellConfig { id: "us1".to_string(), @@ -182,7 +182,7 @@ mod tests { .await; let service = IngestRouterService::new( - router::Router::new(routes_config, locales, locator), + router::Router::new(routes_config, localities, locator), config::RelayTimeouts { http_timeout_secs: 5000, task_initial_timeout_secs: 10000, diff --git a/ingest-router/src/lib.rs b/ingest-router/src/lib.rs index d618ca6..69a110e 100644 --- a/ingest-router/src/lib.rs +++ b/ingest-router/src/lib.rs @@ -5,7 +5,7 @@ mod executor; pub mod handler; pub mod http; pub mod ingest_router_service; -pub mod locale; +pub mod locality; pub mod metrics_defs; pub mod router; @@ -22,7 +22,7 @@ pub async fn run(config: config::Config) -> Result<(), IngestRouterError> { let locator = Locator::new(config.locator.to_client_config()).await?; let ingest_router_service = ingest_router_service::IngestRouterService::new( - router::Router::new(config.routes, config.locales, locator.clone()), + router::Router::new(config.routes, config.localities, locator.clone()), config.relay_timeouts, ); let admin_service = AdminService::new({ diff --git a/ingest-router/src/locale.rs b/ingest-router/src/locality.rs similarity index 71% rename from ingest-router/src/locale.rs rename to ingest-router/src/locality.rs index 339f2ba..e6de227 100644 --- a/ingest-router/src/locale.rs +++ b/ingest-router/src/locality.rs @@ -1,18 +1,18 @@ -//! Locale-based Routing Infrastructure +//! Locality-based Routing Infrastructure //! -//! Maps locales to cells and cells to upstreams for request routing. +//! Maps localities to cells and cells to upstreams for request routing. //! //! # Model //! //! The routing system uses a two-level hierarchy: //! -//! 1. **Locale → Cells**: Each locale (e.g., "us", "de") maps to cell names +//! 1. **Locality → Cells**: Each locality (e.g., "us", "de") maps to cell names //! 2. **Cell → Upstream**: Each cell name maps to an `Upstream` with URLs //! //! ## Example //! //! ```text -//! Locale "us" → Cells ["us-1", "us-2"] +//! Locality "us" → Cells ["us-1", "us-2"] //! ├─ "us-1" → Upstream { //! │ relay_url: "http://us1-relay.example.com", //! │ sentry_url: "http://us1-sentry.example.com" @@ -20,7 +20,7 @@ //! └─ "us-2" → Upstream { ... } //! ``` //! -//! The `Locales` is built at startup from configuration and remains immutable +//! `Localties` is built at startup from configuration and remains immutable //! during request processing. use indexmap::IndexMap; @@ -98,30 +98,30 @@ impl Cells { } } -/// Maps locales to their cells (which map to upstreams) -pub struct Locales { - /// Mapping from locale to cells - locale_to_cells: HashMap, +/// Maps localities to their cells (which map to upstreams) +pub struct Localities { + /// Mapping from locality to cells + locality_to_cells: HashMap, } -impl Locales { - /// Build locale mappings from configuration - pub fn new(locales: HashMap>) -> Self { - // Build locale -> cells mapping - let locale_to_cells = locales +impl Localities { + /// Build locality mappings from configuration + pub fn new(localities: HashMap>) -> Self { + // Build locality -> cells mapping + let locality_to_cells = localities .into_iter() - .map(|(locale, cells)| { - let cells = Cells::from_config(locale.clone(), cells); - (locale, cells) + .map(|(locality, cells_config)| { + let cells = Cells::from_config(locality.clone(), cells_config); + (locality, cells) }) .collect(); - Self { locale_to_cells } + Self { locality_to_cells } } - /// Get the cells for a specific locale - pub fn get_cells(&self, locale: &str) -> Option { - self.locale_to_cells.get(locale).cloned() + /// Get the cells for a specific locality + pub fn get_cells(&self, locality: &str) -> Option { + self.locality_to_cells.get(locality).cloned() } } @@ -138,9 +138,9 @@ mod tests { } #[test] - fn test_locales() { - let mut locales_config = HashMap::new(); - locales_config.insert( + fn test_localities() { + let mut localities_config = HashMap::new(); + localities_config.insert( "us".to_string(), vec![ cell_config( @@ -155,7 +155,7 @@ mod tests { ), ], ); - locales_config.insert( + localities_config.insert( "de".to_string(), vec![cell_config( "de1", @@ -164,10 +164,10 @@ mod tests { )], ); - let locales = Locales::new(locales_config); + let localities = Localities::new(localities_config); - // Verify US locale has 2 cells - let us_cells = locales.get_cells("us").unwrap(); + // Verify US locality has 2 cells + let us_cells = localities.get_cells("us").unwrap(); let cell_list: Vec<_> = us_cells.cell_list().collect(); assert_eq!(cell_list.len(), 2); assert!(us_cells.contains_cell("us1")); @@ -178,15 +178,15 @@ mod tests { assert_eq!(cell_list[0], "us1"); assert_eq!(cell_list[1], "us2"); - // Verify DE locale has 1 cell - let de_cells = locales.get_cells("de").unwrap(); + // Verify DE locality has 1 cell + let de_cells = localities.get_cells("de").unwrap(); let cell_list: Vec<_> = de_cells.cell_list().collect(); assert_eq!(cell_list.len(), 1); assert!(de_cells.contains_cell("de1")); assert!(de_cells.get_upstream("de1").is_some()); assert_eq!(cell_list[0], "de1"); - // Verify unknown locale returns None - assert!(locales.get_cells("unknown").is_none()); + // Verify unknown locality returns None + assert!(localities.get_cells("unknown").is_none()); } } diff --git a/ingest-router/src/router.rs b/ingest-router/src/router.rs index 7537e1b..b7a46ac 100644 --- a/ingest-router/src/router.rs +++ b/ingest-router/src/router.rs @@ -2,7 +2,7 @@ use crate::api::any_cell_handler::AnyCellHandler; use crate::api::project_config::ProjectConfigsHandler; use crate::config::{CellConfig, HandlerAction, Route}; use crate::handler::Handler; -use crate::locale::{Cells, Locales}; +use crate::locality::{Cells, Localities}; use hyper::Request; use locator::client::Locator; use std::collections::HashMap; @@ -12,14 +12,14 @@ use std::sync::Arc; pub struct Router { routes: Arc>, action_to_handler: HashMap>, - locales_to_cells: Locales, + localities_to_cells: Localities, } impl Router { /// Creates a new router with the given routes pub fn new( routes: Vec, - locales: HashMap>, + localities: HashMap>, locator: Locator, ) -> Self { let action_to_handler = HashMap::from([ @@ -48,7 +48,7 @@ impl Router { Self { routes: Arc::new(routes), action_to_handler, - locales_to_cells: Locales::new(locales), + localities_to_cells: Localities::new(localities), } } @@ -58,7 +58,7 @@ impl Router { .iter() .find(|route| self.matches_route(req, route)) .and_then(|route| { - let cells = self.locales_to_cells.get_cells(&route.locale)?; + let cells = self.localities_to_cells.get_cells(&route.locality)?; let handler = self.action_to_handler.get(&route.action)?.clone(); Some((handler, cells)) }) @@ -126,7 +126,7 @@ mod tests { method: Some(HttpMethod::Post), }, action: HandlerAction::RelayProjectConfigs, - locale: "us".to_string(), + locality: "us".to_string(), }, Route { r#match: Match { @@ -135,13 +135,13 @@ mod tests { method: Some(HttpMethod::Get), }, action: HandlerAction::Health, - locale: "us".to_string(), + locality: "us".to_string(), }, ]; let routes = routes.unwrap_or(default_routes); - let locales = HashMap::from([( + let localities = HashMap::from([( "us".to_string(), vec![CellConfig { id: "us1".to_string(), @@ -160,7 +160,7 @@ mod tests { ); let locator = Locator::from_in_process_service(locator_service); - Router::new(routes, locales, locator) + Router::new(routes, localities, locator) } fn test_request( @@ -213,7 +213,7 @@ mod tests { method: None, }, action: HandlerAction::RelayProjectConfigs, - locale: "us".to_string(), + locality: "us".to_string(), }]; let router = test_router(Some(routes)).await; @@ -233,7 +233,7 @@ mod tests { method: Some(HttpMethod::Post), }, action: HandlerAction::RelayProjectConfigs, - locale: "us".to_string(), + locality: "us".to_string(), }]; let router = test_router(Some(routes)).await; diff --git a/synapse/src/config.rs b/synapse/src/config.rs index 3863e4a..1c5931e 100644 --- a/synapse/src/config.rs +++ b/synapse/src/config.rs @@ -149,7 +149,7 @@ mod tests { assert_eq!(ingest_router_config.listener.port, 3000); assert_eq!(ingest_router_config.admin_listener.port, 3001); - assert!(!ingest_router_config.locales.is_empty()); + assert!(!ingest_router_config.localities.is_empty()); assert!(!ingest_router_config.routes.is_empty()); }