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::fmt::Debug;
31use std::rc::{Rc, Weak};
32
33use zrx_scheduler::graph::Builder;
34use zrx_scheduler::Action;
35
36mod traits;
37mod workflow;
38
39use traits::With;
40pub use workflow::Workflow;
41
42// ----------------------------------------------------------------------------
43// Structs
44// ----------------------------------------------------------------------------
45
46/// Workspace.
47#[derive(Debug, Default)]
48pub struct Workspace<I> {
49 /// Shared inner state.
50 inner: Rc<RefCell<WorkspaceInner<I>>>,
51}
52
53/// Workspace.
54#[derive(Debug)]
55pub struct WorkspaceRef<I> {
56 /// Shared inner state.
57 inner: Weak<RefCell<WorkspaceInner<I>>>,
58}
59
60/// Workspace inner state.
61#[derive(Debug, Default)]
62pub struct WorkspaceInner<I> {
63 /// Workflows.
64 workflows: Vec<Workflow<I>>,
65 /// Workspace builder.
66 builder: Builder<I>,
67}
68
69// ----------------------------------------------------------------------------
70// Implementations
71// ----------------------------------------------------------------------------
72
73impl<I> Workspace<I>
74where
75 I: Debug,
76{
77 /// Creates a workspace.
78 #[must_use]
79 pub fn new() -> Self {
80 Self {
81 inner: Rc::new(RefCell::new(WorkspaceInner {
82 workflows: Vec::new(),
83 builder: Builder::new(),
84 })),
85 }
86 }
87
88 /// Adds a workflow to the workspace.
89 #[must_use]
90 pub fn add_workflow(&self) -> Workflow<I> {
91 self.with_mut(|workspace| {
92 let id = workspace.workflows.len();
93 let workflow = Workflow::new(
94 id,
95 WorkspaceRef {
96 inner: Rc::downgrade(&self.inner),
97 },
98 );
99 workspace.workflows.push(workflow.clone());
100 workflow
101 })
102 }
103
104 /// Adds a source to the workspace.
105 #[must_use]
106 pub fn add_source<T>(&self) -> usize
107 where
108 T: Any,
109 {
110 self.with_mut(|workspace| workspace.builder.add_source::<T>())
111 }
112
113 /// Adds an action to the workspace.
114 pub fn add_action<T, S, A>(&self, from: S, action: A) -> usize
115 where
116 T: 'static,
117 S: IntoIterator<Item = usize>,
118 A: Action<I> + 'static,
119 {
120 self.with_mut(|workspace| {
121 workspace.builder.add_action::<T>().with(from, action)
122 })
123 }
124
125 /// Consumes the workspace and returns the builder.
126 #[allow(clippy::missing_panics_doc)]
127 #[must_use]
128 pub fn into_builder(self) -> Builder<I> {
129 let inner = Rc::try_unwrap(self.inner).expect("couldnt unwrap");
130 let workspace = inner.into_inner();
131 workspace.builder
132 }
133}
134
135impl<I> WorkspaceRef<I> {
136 /// Upgrades the weak reference to a strong reference.
137 #[must_use]
138 pub fn upgrade(&self) -> Option<Workspace<I>> {
139 self.inner.upgrade().map(|inner| Workspace { inner })
140 }
141}
142
143// ----------------------------------------------------------------------------
144// Trait implementations
145// ----------------------------------------------------------------------------
146
147impl<I> With for Workspace<I> {
148 type Item = WorkspaceInner<I>;
149
150 /// Returns a reference to the inner state.
151 #[inline]
152 fn inner(&self) -> &RefCell<Self::Item> {
153 &self.inner
154 }
155}
156
157impl<I> Clone for Workspace<I> {
158 // relax trait bounds
159 fn clone(&self) -> Self {
160 let inner = Rc::clone(&self.inner);
161 Self { inner }
162 }
163}
164
165impl<I> Clone for WorkspaceRef<I> {
166 // relax trait bounds
167 fn clone(&self) -> Self {
168 let inner = Weak::clone(&self.inner);
169 Self { inner }
170 }
171}