I am trying to implement a simple health check using tokio for async that does a simple loop and runs an update function based on the result however I am running into an error with my RwLock.
struct HealthCheck {
state: Arc<RwLock<ServerStatus>>,
}
enum ServerStatus {
Ready {
errors: Vec<i64>,
},
NotReady {
ping_attempts: u8,
ping_success: u8,
ping_failure: u8,
},
Maintenance,
Unhealthy,
}
...
...
// Init the state
let state = Arc::new(RwLock::new(ServerStatus::NotReady {
ping_attempts: 0,
ping_success: 0,
ping_failure: 0,
}));
let state_clone = state.clone();
// Spawn a task that loops taking the client
tokio::spawn(async move {
let mut interval = time::interval(time::Duration::from_secs(5));
loop {
match client.ping().await {
Ok(Ping) => {
{
// Get a lock on the state
let current_state = &state_clone.write().await;
// Update state
¤t_state.update(Event::PingSuccess)
}
},
Err(e) => {
{
// Get a lock on the state
let mut current_state = &state_clone.write().await;
// Update state
¤t_state.update(Event::PingFailure)
}
}
};
interval.tick().await;
}
});
impl ServerStatus {
// This function handles the state machine for the health check of a server
fn update(self, event: Event) -> ServerStatus
}
The error is below
cannot move out of dereference of `tokio::sync::rwlock::RwLockWriteGuard<'_, health_check::ServerStatus>`
move occurs because value has type `health_check::ServerStatus`, which does not implement the `Copy` trait
error[E0507]: cannot move out of dereference of `tokio::sync::rwlock::RwLockWriteGuard<'_, health_check::ServerStatus>`
--> src/health_check.rs:60:29
|
60 | ... current_state.update(Event::PingSuccess)
| ^^^^^^^^^^^^^ move occurs because value has type `health_check::ServerStatus`, which does not implement the `Copy` trait
Now I can make the error go away if I box the vector in the ready variant of ServerStatus but I don't understand why I need Copy to run the function of the write locked object? Is this the correct way to go about it or should I attempt a different approach ?