Skip to main content

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}