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}