1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
use crate;
use ;
use Rc;
/// A dependency injection factory for creating single-instance nodes with lazy initialization.
///
/// `SimpleFactory<T>` provides build-time configuration for nodes that should only
/// be created once per factory instance. Uses `OnceCell` for thread-safe lazy
/// initialization - the factory function is called exactly once on the first
/// `get()` request, and subsequent calls return the cached node.
///
/// # Use Cases
///
/// - **Singleton services**: Database connections, configuration managers, loggers
/// - **Expensive initialization**: Nodes that load large datasets or establish connections
/// - **Shared resources**: Nodes that multiple parts of the graph need to reference
/// - **Environment abstraction**: Different implementations based on build-time configuration
///
/// # Example: Configuration Service
///
/// ```rust, ignore
/// // Build-time: Configure different config sources
/// let config_factory = match environment {
/// Environment::Production => SimpleFactory::default()
/// .attach(|executor| {
/// NodeBuilder::new(ProductionConfig::load())
/// .with_name("prod_config".to_string())
/// .build(executor, |config, ctx| {
/// // Handle config reload requests
/// Control::Broadcast
/// })
/// }),
/// Environment::Test => SimpleFactory::default()
/// .attach(|executor| {
/// NodeBuilder::new(MockConfig::default())
/// .with_name("test_config".to_string())
/// .build(executor, |config, ctx| Control::Unchanged)
/// }),
/// };
///
/// // Runtime: Multiple nodes can depend on the same config instance
/// let config_node = config_factory.get(&mut executor);
///
/// let processor1 = NodeBuilder::new(DataProcessor::new())
/// .observer_of(&config_node) // Read config but don't react to changes
/// .build(&mut executor, process_data);
///
/// let processor2 = NodeBuilder::new(AnotherProcessor::new())
/// .observer_of(&config_node) // Same config instance
/// .build(&mut executor, process_other_data);
/// ```
///
/// # Lifecycle
///
/// 1. **Attach**: Configure the factory function at build time
/// 2. **Get**: Request the node during graph construction
/// 3. **Initialize**: First `get()` call executes the factory function
/// 4. **Reuse**: All subsequent `get()` calls return the same node instance
///
/// # Comparison with KeyedFactory
///
/// - `SimpleFactory`: One node per factory instance (singleton pattern)
/// - `KeyedFactory`: One node per unique key (multi-instance with caching)
///
/// Choose `SimpleFactory` when you need exactly one instance of a particular
/// node type in your graph.
;