Skip to content

Commit

Permalink
[wip, feat] Action dispatcher state machine
Browse files Browse the repository at this point in the history
Signed-off-by: dd di cesare <[email protected]>
  • Loading branch information
didierofrivia committed Aug 30, 2024
1 parent ed8eec1 commit 51bb020
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 0 deletions.
150 changes: 150 additions & 0 deletions src/action_dispatcher.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
#[derive(PartialEq, Debug, Clone)]
enum State {
Pending,
Waiting,
Done,
}

impl State {
fn next(&mut self) {
match self {
State::Pending => *self = State::Waiting,
State::Waiting => *self = State::Done,
_ => {}
}
}
}
#[derive(PartialEq, Clone)]
enum Action {
Auth { state: State },
RateLimit { state: State },
}

impl Action {
pub fn trigger(&mut self) {
match self {
Action::Auth { .. } => self.auth(),
Action::RateLimit { .. } => self.rate_limit(),
}
}

fn get_state(&self) -> &State {
match self {
Action::Auth { state } => state,
Action::RateLimit { state } => state,
}
}

fn rate_limit(&mut self) {
// Specifics for RL, returning State
if let Action::RateLimit { state } = self {
match state {
State::Pending => {
println!("Trigger the request and return State::Waiting");
state.next();
}
State::Waiting => {
println!(
"When got on_grpc_response, process RL response and return State::Done"
);
state.next();
}
State::Done => {
println!("Done for RL... calling next action (?)");
}
}
}
}

fn auth(&mut self) {
// Specifics for Auth, returning State
if let Action::Auth { state } = self {
match state {
State::Pending => {
println!("Trigger the request and return State::Waiting");
state.next();
}
State::Waiting => {
println!(
"When got on_grpc_response, process Auth response and return State::Done"
);
state.next();
}
State::Done => {
println!("Done for Auth... calling next action (?)");
}
}
}
}
}

pub struct ActionDispatcher {
actions: Vec<Action>,
}

impl ActionDispatcher {
pub fn default() -> ActionDispatcher {
ActionDispatcher { actions: vec![] }
}

pub fn new(/*vec of PluginConfig actions*/) -> ActionDispatcher {
ActionDispatcher::default()
}

pub fn next(&mut self) -> bool {
if let Some((i, action)) = self.actions.iter_mut().enumerate().next() {
if let State::Done = action.get_state() {
self.actions.remove(i);
self.actions.len() > 0
} else {
action.trigger();
true
}
} else {
false
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn action_transition() {
let mut action = Action::Auth {
state: State::Pending,
};
assert_eq!(*action.get_state(), State::Pending);
action.trigger();
assert_eq!(*action.get_state(), State::Waiting);
action.trigger();
assert_eq!(*action.get_state(), State::Done);
}

#[test]
fn action_dispatcher_next() {
let mut action_dispatcher = ActionDispatcher{
actions: vec![
Action::RateLimit {state: State::Pending}
],
};
let mut res = action_dispatcher.next();
let mut binding = action_dispatcher.actions.clone();
let mut current_action_state = binding.first().unwrap().get_state();

assert_eq!(res, true);
assert_eq!(*current_action_state, State::Waiting);

res = action_dispatcher.next();
binding = action_dispatcher.actions.clone();
current_action_state = binding.first().unwrap().get_state();

assert_eq!(res, true);
assert_eq!(*current_action_state, State::Done);

res = action_dispatcher.next();
assert_eq!(res, false);
assert_eq!(action_dispatcher.actions.len(), 0);
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod action_dispatcher;
mod attribute;
mod configuration;
mod envoy;
Expand Down

0 comments on commit 51bb020

Please sign in to comment.