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