hyperstack_server/view/
registry.rs1use crate::sorted_cache::{SortOrder, SortedViewCache};
2use crate::view::ViewSpec;
3use std::collections::HashMap;
4use std::sync::Arc;
5use tokio::sync::RwLock;
6
7#[derive(Clone)]
8pub struct ViewIndex {
9 by_export: HashMap<String, Vec<ViewSpec>>,
10 by_id: HashMap<String, ViewSpec>,
11 sorted_caches: Arc<RwLock<HashMap<String, SortedViewCache>>>,
12 derived_by_source: HashMap<String, Vec<String>>,
14}
15
16impl ViewIndex {
17 pub fn new() -> Self {
18 Self {
19 by_export: HashMap::new(),
20 by_id: HashMap::new(),
21 sorted_caches: Arc::new(RwLock::new(HashMap::new())),
22 derived_by_source: HashMap::new(),
23 }
24 }
25
26 pub fn add_spec(&mut self, spec: ViewSpec) {
27 if let Some(ref source) = spec.source_view {
28 self.derived_by_source
29 .entry(source.clone())
30 .or_default()
31 .push(spec.id.clone());
32 }
33
34 if let Some(ref pipeline) = spec.pipeline {
35 if let Some(ref sort_config) = pipeline.sort {
36 self.init_sorted_cache_sync(
37 &spec.id,
38 sort_config.field_path.clone(),
39 sort_config.order.into(),
40 );
41 }
42 }
43
44 if !spec.is_derived() {
48 self.by_export
49 .entry(spec.export.clone())
50 .or_default()
51 .push(spec.clone());
52 }
53 self.by_id.insert(spec.id.clone(), spec);
54 }
55
56 pub fn by_export(&self, entity: &str) -> &[ViewSpec] {
57 self.by_export
58 .get(entity)
59 .map(|v| v.as_slice())
60 .unwrap_or(&[])
61 }
62
63 pub fn get_view(&self, id: &str) -> Option<&ViewSpec> {
64 self.by_id.get(id)
65 }
66
67 pub fn get_derived_views(&self) -> Vec<&ViewSpec> {
68 self.by_id.values().filter(|s| s.is_derived()).collect()
69 }
70
71 pub fn get_derived_views_for_source(&self, source_view_id: &str) -> Vec<&ViewSpec> {
72 self.derived_by_source
73 .get(source_view_id)
74 .map(|ids| ids.iter().filter_map(|id| self.by_id.get(id)).collect())
75 .unwrap_or_default()
76 }
77
78 pub fn sorted_caches(&self) -> Arc<RwLock<HashMap<String, SortedViewCache>>> {
79 self.sorted_caches.clone()
80 }
81
82 pub async fn init_sorted_cache(
83 &self,
84 view_id: &str,
85 sort_field: Vec<String>,
86 order: SortOrder,
87 ) {
88 let mut caches = self.sorted_caches.write().await;
89 if !caches.contains_key(view_id) {
90 caches.insert(
91 view_id.to_string(),
92 SortedViewCache::new(view_id.to_string(), sort_field, order),
93 );
94 }
95 }
96
97 fn init_sorted_cache_sync(&mut self, view_id: &str, sort_field: Vec<String>, order: SortOrder) {
98 let cache = SortedViewCache::new(view_id.to_string(), sort_field, order);
99 let caches = Arc::get_mut(&mut self.sorted_caches)
100 .expect("Cannot initialize sorted cache: Arc is shared");
101 let caches = caches.get_mut();
102 if !caches.contains_key(view_id) {
103 caches.insert(view_id.to_string(), cache);
104 }
105 }
106}
107
108impl Default for ViewIndex {
109 fn default() -> Self {
110 Self::new()
111 }
112}