opcua_server/util/
mod.rs

1// OPCUA for Rust
2// SPDX-License-Identifier: MPL-2.0
3// Copyright (C) 2017-2022 Adam Lock
4
5//! Provides utility routines for things that might be used in a number of places elsewhere.
6
7use std::sync::{Arc, RwLock};
8
9use tokio::time::{interval_at, Duration, Instant};
10
11use opcua_types::service_types::ServerState as ServerStateType;
12
13use crate::state::ServerState;
14
15/// This is a convenience for a polling action. This struct starts a repeating timer that calls
16/// an action repeatedly.
17pub struct PollingAction {}
18
19impl PollingAction {
20    pub fn spawn<F>(
21        server_state: Arc<RwLock<ServerState>>,
22        interval_ms: u64,
23        action: F,
24    ) -> PollingAction
25    where
26        F: 'static + Fn() + Send,
27    {
28        tokio::spawn(async move {
29            let mut timer = interval_at(Instant::now(), Duration::from_millis(interval_ms));
30            loop {
31                {
32                    // trace!("polling action.take_while");
33                    let server_state = trace_read_lock!(server_state);
34                    // If the server aborts or is in a failed state, this polling timer will stop
35                    let abort = match server_state.state() {
36                        ServerStateType::Failed
37                        | ServerStateType::NoConfiguration
38                        | ServerStateType::Shutdown => true,
39                        _ => server_state.is_abort(),
40                    };
41                    if abort {
42                        debug!("Polling action is stopping due to server state / abort");
43                        break;
44                    }
45                }
46
47                // Timer
48                timer.tick().await;
49
50                // Polling timer will only call the action if the server is in a running state
51                let process_action = {
52                    let server_state = trace_read_lock!(server_state);
53                    server_state.is_running()
54                };
55                if process_action {
56                    action();
57                }
58            }
59        });
60        PollingAction {}
61    }
62}