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
/* Copyright 2023 Architect Financial Technologies LLC. This is free
 * software released under the GNU Affero Public License version 3. */
//! simplified open order wrapper

use crate::protocol::orderflow::{OrderId, OrderState};
use anyhow::Result;
use enumflags2::BitFlags;
use std::{future::Future, pin::Pin};
use tokio::sync::watch;

pub type Outcome = Pin<
    Box<
        dyn Future<Output = Result<(OrderId, BitFlags<OrderState>)>>
            + Send
            + Sync
            + 'static,
    >,
>;

pub struct ManagedOrder {
    order_id: OrderId,
    order_state: watch::Sender<BitFlags<OrderState>>,
}

impl ManagedOrder {
    pub(crate) fn new(order_id: OrderId) -> Self {
        let (order_state, _) = watch::channel(BitFlags::empty());
        Self { order_id, order_state }
    }

    pub(crate) fn set_order_state(&self, state: BitFlags<OrderState>) {
        self.order_state.send_replace(state);
    }

    /// get the id of the managed order
    pub fn id(&self) -> OrderId {
        self.order_id
    }

    /// Wait for the order to be filled or out, return it's id and
    /// final state. If you have multiple orders that you want to wait
    /// for you can safely put this future in a
    /// `futures::stream::FuturesUnordered`
    pub fn wait_filled_or_out(&self) -> Outcome {
        // CR alee: will this get the last value even if rx was created after the send
        let mut rx = self.order_state.subscribe();
        let id = self.order_id;
        Box::pin(async move {
            let mut state = *rx.borrow();
            while state.is_empty() || state.contains(OrderState::Open) {
                rx.changed().await?;
                state = *rx.borrow();
            }
            Ok((id, state))
        })
    }
}