Rust의 오케스트레이션

Rust의 객체 지향 개념에서 패턴을 이식하는 것이 항상 작동하는 것은 아니지만, 특정 경우에는 작동할 뿐만 아니라 원래 OOP 구현과 비교할 때 더 쉽게 따를 수 있습니다.

여기서는 Rust에서 오케스트레이션의 개념을 설명하겠습니다.

한 단계 뒤로 오케스트레이션을 취하는 것은 redux와 어렴풋이 비슷하지만, 리듀서가 상태뿐만 아니라 페이로드도 처리해야 한다는 주요 차이점이 있습니다.

오케스트레이션은 기본적으로 이전 상태가 다음 작업에서 전달되는 파이프라인입니다. 오케스트레이션의 핵심은 일시 중지 및 재개 기능입니다.

나는 이 예제를 중간 예제로 분류하지만 따라하기가 그리 어렵지는 않습니다.

State 객체에 대해 이야기하고 정의하는 것으로 시작하겠습니다.

#[derive(Debug, Clone)]
pub struct State {
    pub proceed: bool,
    pub outcome: f32,
    pub stage: Vec<bool>,
}


우리 주에는 다음이 있습니다.
  • 계속: 각 단계를 성공 여부로 표시하고, 진행을 false로 표시하여 나머지 단계의 실행을 중지합니다
  • .
  • 결과 : 각 단계의 결과
  • 단계 : 단계의 결과를 기록

  • 그런 다음 Orchestrate 특성을 정의합니다.

    trait Orchestrate {
        fn execute(self, state: State) -> State;
    }
    


    그리고 우리는 벡터 함수에 대해 Orchestrate 트레잇을 구현할 것입니다.

    impl Orchestrate for Vec<fn(State) -> Result<State, Error>> {
         fn execute(self, state: State) -> State {
            self.iter().enumerate().fold(state, |output, (i, func)| {
                let new_state = output.clone();
                if new_state.stage.len() > i {
                    if new_state.stage[i] {
                        return new_state;
                    } else {
                        let mut next_state = func(new_state).unwrap();
                        next_state.stage[i] = next_state.proceed;
                        return next_state;
                    }
                }
                let mut next_state = func(new_state).unwrap();
                next_state.stage.push(next_state.proceed);
                return next_state;
            })
        }
    }
    


    이것이 어디로 가고 있는지는 이미 쉽게 알 수 있습니다.
  • 함수 배열을 받았습니다
  • 각 실행에 대해 이전 실행(단계)에서 작업이 완료되었는지 확인합니다
  • .
  • 단계를 실행하거나 무시합니다.

  • 다음으로 이 오케스트레이션에서 수행하려는 3가지 간단한 작업을 정의합니다. 그것들이 어떻게 사용될 것인지 궁금해 할 것입니다.

    fn pow2(n: f32) -> f32 {
        n.powf(2.0)
    }
    
    fn pow3(n: f32) -> f32 {
        n.powf(3.0)
    }
    
    fn sqrt(n: f32) -> f32 {
        n.sqrt()
    }
    


    이제 내가 가장 좋아하는 부분은 상태를 가져오고 상태를 반환하고 일시 중지 재개 논리가 포함된 함수를 만드는 대신 함수를 인수로 받아 함수를 만드는 매크로를 만들 것입니다.

    macro_rules! state_function {
        ( $func:expr ) => {{
            pub fn state_fn(c: State) -> Result<State, Error> {
                let stage: Vec<bool> = c.stage.to_vec();
                if c.proceed == false {
                    Ok(State {
                        proceed: false,
                        outcome: c.outcome,
                        stage: stage,
                    })
                } else {
                    let mut rng = rand::thread_rng();
                    let y: bool = rng.gen();
                    Ok(State {
                        proceed: y,
                        outcome: $func(c.outcome),
                        stage: stage,
                    })
                }
            }
    
            state_fn
        }};
    }
    


  • 진행이 거짓이면 아무 것도 하지 마십시오
  • 그렇지 않으면 새 결과와 함께 상태를 반환합니다.

  • 그리고 약간의 재미를 더하기 위해 임의의 부울을 사용하여 처리를 방해하고 좀 더 흥미롭게 만들었습니다.

    마지막으로 주요 기능에서
    1단계: 함수 생성

        let a: fn(State) -> Result<State, Error> = state_function!(pow2);
        let b: fn(State) -> Result<State, Error> = state_function!(pow3);
        let c: fn(State) -> Result<State, Error> = state_function!(sqrt);
    


    2단계: 체인 정의

        let chain: Vec<fn(State) -> Result<State, Error>> =  vec![a, b, c];
    


    3단계: 체인을 실행합니다.

        let result = chain
            .execute(State {
                proceed: true,
                outcome: 6.,
                stage: Vec::<bool>::new(),
            });
    
        println!("{:?}", result);
    


    보너스
    4단계: 일부 단계가 완료되었다고 가정하고 체인을 실행합니다.

        let result = chain
            .execute(State {
                proceed: true,
                outcome: 6.,
                stage: vec![true, false, false],
            });
    
        println!("{:?}", result);
    


    즐감하셨길 바랍니다... :D

    업데이트: 이 패턴의 일반 버전은 여기https://github.com/elasticrash/orchestrator에서 찾을 수 있습니다.

    좋은 웹페이지 즐겨찾기