Skip to content

Commit 320b42f

Browse files
committed
WIP: refactoring everything outside entity and descriptors
1 parent 000b714 commit 320b42f

File tree

15 files changed

+1435
-917
lines changed

15 files changed

+1435
-917
lines changed

lib/runtime/src/component.rs

Lines changed: 593 additions & 593 deletions
Large diffs are not rendered by default.

lib/runtime/src/component/client.rs

Lines changed: 0 additions & 224 deletions
This file was deleted.

lib/runtime/src/descriptor.rs

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@
7777
use once_cell::sync::Lazy;
7878
use std::str::FromStr;
7979
use validator::ValidationError;
80+
use serde::{Deserialize, Serialize};
81+
82+
use crate::slug::Slug;
8083

8184
pub const ETCD_ROOT_PATH: &str = "dynamo://";
8285
pub const COMPONENT_KEYWORD: &str = "_component_";
@@ -308,7 +311,7 @@ impl DynamoPath {
308311

309312
/// Pure data descriptor for component identification
310313
/// Owns the canonical path format and validation logic
311-
#[derive(Debug, Clone, PartialEq, Eq)]
314+
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
312315
pub struct Identifier {
313316
namespace: String,
314317
component: Option<String>,
@@ -383,6 +386,29 @@ impl Identifier {
383386

384387
Ok(())
385388
}
389+
390+
/// Generate a slugified subject string for event publishing
391+
pub fn slug(&self) -> Slug {
392+
Slug::slugify_unique(&self.to_string())
393+
}
394+
395+
/// Create a namespace-only identifier from this identifier
396+
pub fn to_namespace(&self) -> Identifier {
397+
Identifier {
398+
namespace: self.namespace.clone(),
399+
component: None,
400+
endpoint: None,
401+
}
402+
}
403+
404+
/// Create a component identifier from this identifier (requires component to be present)
405+
pub fn to_component(&self) -> Option<Identifier> {
406+
self.component.as_ref().map(|comp| Identifier {
407+
namespace: self.namespace.clone(),
408+
component: Some(comp.clone()),
409+
endpoint: None,
410+
})
411+
}
386412
}
387413

388414
impl std::fmt::Display for Identifier {
@@ -421,7 +447,7 @@ impl TryFrom<&str> for Identifier {
421447

422448
/// Identifier extended with instance_id (lease_id)
423449
/// Immutable - identifier cannot be changed after construction
424-
#[derive(Debug, Clone, PartialEq, Eq)]
450+
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
425451
pub struct Instance {
426452
identifier: Identifier, // Private to enforce immutability
427453
instance_id: Option<i64>,
@@ -481,6 +507,15 @@ impl Instance {
481507
pub fn instance_id(&self) -> Option<i64> {
482508
self.instance_id
483509
}
510+
511+
pub fn is_static(&self) -> bool {
512+
self.is_static
513+
}
514+
515+
/// Generate a slugified subject string for event publishing
516+
pub fn slug(&self) -> Slug {
517+
Slug::slugify_unique(&self.to_string())
518+
}
484519
}
485520

486521
impl std::fmt::Display for Instance {
@@ -525,14 +560,14 @@ impl TryFrom<&str> for Instance {
525560

526561
/// Descriptor with additional path segments for extended paths
527562
/// Always inserts _path_ before the segments
528-
#[derive(Debug, Clone, PartialEq, Eq)]
563+
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
529564
pub struct Keys {
530565
base: KeysBase, // Either Identifier or Instance
531566
keys: Vec<String>,
532567
}
533568

534569
/// Base can be either Identifier or Instance
535-
#[derive(Debug, Clone, PartialEq, Eq)]
570+
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
536571
pub enum KeysBase {
537572
Identifier(Identifier),
538573
Instance(Instance),
@@ -579,6 +614,11 @@ impl Keys {
579614
&self.keys
580615
}
581616

617+
/// Generate a slugified subject string for event publishing
618+
pub fn slug(&self) -> Slug {
619+
Slug::slugify_unique(&self.to_string())
620+
}
621+
582622
}
583623

584624
impl std::fmt::Display for Keys {
@@ -774,6 +814,47 @@ mod tests {
774814
assert_eq!(id.endpoint_name(), Some("http"));
775815
}
776816

817+
#[test]
818+
fn test_identifier_conversions() {
819+
// Create a full endpoint identifier
820+
let full_id = Identifier::new_endpoint("production.api", "gateway", "http").unwrap();
821+
assert_eq!(full_id.to_string(), "dynamo://production.api/_component_/gateway/_endpoint_/http");
822+
823+
// Convert to namespace-only
824+
let ns_id = full_id.to_namespace();
825+
assert_eq!(ns_id.to_string(), "dynamo://production.api");
826+
assert_eq!(ns_id.namespace_name(), "production.api");
827+
assert_eq!(ns_id.component_name(), None);
828+
assert_eq!(ns_id.endpoint_name(), None);
829+
830+
// Convert to component-only
831+
let comp_id = full_id.to_component().unwrap();
832+
assert_eq!(comp_id.to_string(), "dynamo://production.api/_component_/gateway");
833+
assert_eq!(comp_id.namespace_name(), "production.api");
834+
assert_eq!(comp_id.component_name(), Some("gateway"));
835+
assert_eq!(comp_id.endpoint_name(), None);
836+
837+
// Test with component-only identifier
838+
let comp_only = Identifier::new_component("ns", "comp").unwrap();
839+
840+
let ns_from_comp = comp_only.to_namespace();
841+
assert_eq!(ns_from_comp.to_string(), "dynamo://ns");
842+
843+
let comp_from_comp = comp_only.to_component().unwrap();
844+
assert_eq!(comp_from_comp.to_string(), "dynamo://ns/_component_/comp");
845+
assert_eq!(comp_from_comp, comp_only);
846+
847+
// Test with namespace-only identifier
848+
let ns_only = Identifier::new_namespace("ns").unwrap();
849+
850+
let ns_from_ns = ns_only.to_namespace();
851+
assert_eq!(ns_from_ns.to_string(), "dynamo://ns");
852+
assert_eq!(ns_from_ns, ns_only);
853+
854+
// Should return None when trying to get component from namespace-only
855+
assert!(ns_only.to_component().is_none());
856+
}
857+
777858
#[test]
778859
fn test_instance_dynamic_and_static_creation_and_parsing() {
779860
// Dynamic instance creation

lib/runtime/src/discovery.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ pub struct Storage<'a> {
135135
}
136136

137137
impl<'a> Storage<'a> {
138+
139+
pub fn primary_lease(&self) -> Lease {
140+
self.client.primary_lease()
141+
}
138142
/// Create a new lease with specified TTL
139143
pub async fn create_lease(&self, ttl: i64) -> Result<Lease> {
140144
self.client.create_lease(ttl).await
@@ -194,6 +198,11 @@ impl<'a> Storage<'a> {
194198
pub fn key(&self) -> &str {
195199
&self.key
196200
}
201+
202+
/// Public constructor so other modules can create a `Storage` scoped to a custom key.
203+
pub fn new(client: &'a etcd::Client, key: String) -> Self {
204+
Self { client, key }
205+
}
197206
}
198207

199208
/// Minimal trait for entities that have etcd storage

0 commit comments

Comments
 (0)