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}