zrx_stream/stream/workspace.rs
1// Copyright (c) 2025-2026 Zensical and contributors
2
3// SPDX-License-Identifier: MIT
4// All contributions are certified under the DCO
5
6// Permission is hereby granted, free of charge, to any person obtaining a copy
7// of this software and associated documentation files (the "Software"), to
8// deal in the Software without restriction, including without limitation the
9// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10// sell copies of the Software, and to permit persons to whom the Software is
11// furnished to do so, subject to the following conditions:
12
13// The above copyright notice and this permission notice shall be included in
14// all copies or substantial portions of the Software.
15
16// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
19// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22// IN THE SOFTWARE.
23
24// ----------------------------------------------------------------------------
25
26//! Workspace.
27
28use std::any::Any;
29use std::cell::RefCell;
30use std::rc::{Rc, Weak};
31
32use zrx_scheduler::graph::Builder;
33use zrx_scheduler::Action;
34
35mod traits;
36mod workflow;
37
38use traits::With;
39pub use workflow::Workflow;
40
41// ----------------------------------------------------------------------------
42// Structs
43// ----------------------------------------------------------------------------
44
45/// Workspace.
46#[derive(Debug, Default)]
47pub struct Workspace<I> {
48 /// Shared inner state.
49 inner: Rc<RefCell<WorkspaceInner<I>>>,
50}
51
52/// Workspace.
53#[derive(Debug)]
54pub struct WorkspaceRef<I> {
55 /// Shared inner state.
56 inner: Weak<RefCell<WorkspaceInner<I>>>,
57}
58
59/// Workspace inner state.
60#[derive(Debug, Default)]
61pub struct WorkspaceInner<I> {
62 /// Workflows.
63 workflows: Vec<Workflow<I>>,
64 /// Workspace builder.
65 builder: Builder<I>,
66}
67
68// ----------------------------------------------------------------------------
69// Implementations
70// ----------------------------------------------------------------------------
71
72impl<I> Workspace<I>
73where
74 I: std::fmt::Debug,
75{
76 /// Creates a workspace.
77 #[must_use]
78 pub fn new() -> Self {
79 Self {
80 inner: Rc::new(RefCell::new(WorkspaceInner {
81 workflows: Vec::new(),
82 builder: Builder::new(),
83 })),
84 }
85 }
86
87 /// Adds a workflow to the workspace.
88 #[must_use]
89 pub fn add_workflow(&self) -> Workflow<I> {
90 self.with_mut(|workspace| {
91 let id = workspace.workflows.len();
92 let workflow = Workflow::new(
93 id,
94 WorkspaceRef {
95 inner: Rc::downgrade(&self.inner),
96 },
97 );
98 workspace.workflows.push(workflow.clone());
99 workflow
100 })
101 }
102
103 /// Adds a source to the workspace.
104 #[must_use]
105 pub fn add_source<T>(&self) -> usize
106 where
107 T: Any,
108 {
109 self.with_mut(|workspace| workspace.builder.add_source::<T>())
110 }
111
112 /// Adds an action to the workspace.
113 pub fn add_action<T, S, A>(&self, from: S, action: A) -> usize
114 where
115 T: 'static,
116 S: IntoIterator<Item = usize>,
117 A: Action<I> + 'static,
118 {
119 self.with_mut(|workspace| {
120 workspace.builder.add_action::<T>().with(from, action)
121 })
122 }
123
124 /// Consumes the workspace and returns the builder.
125 #[allow(clippy::missing_panics_doc)]
126 #[must_use]
127 pub fn into_builder(self) -> Builder<I> {
128 let inner = Rc::try_unwrap(self.inner).expect("couldnt unwrap");
129 let workspace = inner.into_inner();
130 workspace.builder
131 }
132}
133
134impl<I> WorkspaceRef<I> {
135 /// Upgrades the weak reference to a strong reference.
136 #[must_use]
137 pub fn upgrade(&self) -> Option<Workspace<I>> {
138 self.inner.upgrade().map(|inner| Workspace { inner })
139 }
140}
141
142// ----------------------------------------------------------------------------
143// Trait implementations
144// ----------------------------------------------------------------------------
145
146impl<I> With for Workspace<I> {
147 type Item = WorkspaceInner<I>;
148
149 /// Returns a reference to the inner state.
150 #[inline]
151 fn inner(&self) -> &RefCell<Self::Item> {
152 &self.inner
153 }
154}
155
156impl<I> Clone for Workspace<I> {
157 // relax trait bounds
158 fn clone(&self) -> Self {
159 let inner = Rc::clone(&self.inner);
160 Self { inner }
161 }
162}
163
164impl<I> Clone for WorkspaceRef<I> {
165 // relax trait bounds
166 fn clone(&self) -> Self {
167 let inner = Weak::clone(&self.inner);
168 Self { inner }
169 }
170}