calc_effect/
calc_effect.rs1use std::sync::{Arc, Mutex};
2use std::thread;
3
4use rs_store::{DispatchOp, Dispatcher, Effect, EffectResult, StoreBuilder};
5use rs_store::{Reducer, Subscriber};
6
7#[derive(Debug, Clone)]
8enum CalcAction {
9 AddWillProduceThunk(i32),
10 SubtractWillProduceEffectFunction(i32),
11}
12
13struct CalcReducer {}
14
15impl Default for CalcReducer {
16 fn default() -> CalcReducer {
17 CalcReducer {}
18 }
19}
20
21#[derive(Debug, Clone)]
22struct CalcState {
23 count: i32,
24}
25
26impl Default for CalcState {
27 fn default() -> CalcState {
28 CalcState { count: 0 }
29 }
30}
31
32impl Reducer<CalcState, CalcAction> for CalcReducer {
33 fn reduce(&self, state: &CalcState, action: &CalcAction) -> DispatchOp<CalcState, CalcAction> {
34 match action {
35 CalcAction::AddWillProduceThunk(i) => {
36 println!("CalcReducer::reduce: + {}", i);
37 DispatchOp::Dispatch(
38 CalcState {
39 count: state.count + i,
40 },
41 Some(Effect::Thunk(subtract_effect_thunk(*i))),
42 )
43 }
44 CalcAction::SubtractWillProduceEffectFunction(i) => {
45 println!("CalcReducer::reduce: - {}", i);
46 DispatchOp::Dispatch(
47 CalcState {
48 count: state.count - i,
49 },
50 Some(Effect::Function(
52 "subtract".to_string(),
53 subtract_effect_fn(*i),
54 )),
55 )
56 }
57 }
58 }
59}
60
61struct CalcSubscriber {
62 id: i32,
63 last: Mutex<CalcState>,
64}
65
66impl Default for CalcSubscriber {
67 fn default() -> Self {
68 Self {
69 id: 0,
70 last: Mutex::new(CalcState::default()),
71 }
72 }
73}
74
75impl Subscriber<CalcState, CalcAction> for CalcSubscriber {
76 fn on_notify(&self, state: &CalcState, action: &CalcAction) {
77 match action {
78 CalcAction::AddWillProduceThunk(_i) => {
79 println!(
80 "CalcSubscriber::on_notify: id:{}, state: {:?} <- last: {:?} + action: {:?}",
81 self.id,
82 state,
83 self.last.lock().unwrap(),
84 action,
85 );
86 }
87 CalcAction::SubtractWillProduceEffectFunction(_i) => {
88 println!(
89 "CalcSubscriber::on_notify: id:{}, state: {:?} <- last: {:?} + action: {:?}",
90 self.id,
91 state,
92 self.last.lock().unwrap(),
93 action,
94 );
95 }
96 }
97
98 *self.last.lock().unwrap() = state.clone();
99 }
100}
101
102fn subtract_effect_thunk(i: i32) -> Box<dyn FnOnce(Box<dyn Dispatcher<CalcAction>>) + Send> {
103 Box::new(move |dispatcher| {
104 println!("effect: working on long running task....");
105 thread::sleep(std::time::Duration::from_secs(1));
106
107 println!("effect: dispatching action...");
108 dispatcher
109 .dispatch(CalcAction::SubtractWillProduceEffectFunction(i))
110 .expect("no dispatch failed");
111 })
112}
113
114fn subtract_effect_fn(_i: i32) -> Box<dyn FnOnce() -> EffectResult + Send> {
115 Box::new(move || {
116 println!("effect: working on long running task again....");
117 thread::sleep(std::time::Duration::from_secs(1));
118
119 println!("effect: now returns result");
120 Ok(Box::new(CalcState { count: 0 }))
121 })
122}
123
124pub fn main() {
125 println!("Hello, Effect!");
126
127 let store =
128 StoreBuilder::new_with_reducer(CalcState::default(), Box::new(CalcReducer::default()))
129 .with_name("store-effect".into())
130 .build()
131 .unwrap();
132
133 store.add_subscriber(Arc::new(CalcSubscriber::default()));
134 let _ = store.dispatch(CalcAction::AddWillProduceThunk(1));
135
136 store.stop();
137}