aquarium_control/food/
food_injection_error.rs

1/* Copyright 2025 Uwe Martin
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
5The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
7THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8*/
9
10//! Defines the custom error type for the food injection process.
11//!
12//! This module contains the `FoodInjectionError` enum, which consolidates all potential
13//! failures that can occur when the `FoodInjection` controller executes a feed pattern.
14//! By using a dedicated, descriptive error type, the system can provide clear diagnostics
15//! when a feeding action fails.
16//!
17//! ## Design and Purpose
18//!
19//! The `FoodInjectionError` enum is designed using the `thiserror` crate to provide
20//! structured and informative error messages.
21//!
22//! - **Source Chaining**: For errors originating from channel communication (e.g.,
23//!   `RelayManagerSend`), the `#[source]` attribute preserves the underlying
24//!   `AquaChannelError`. This creates a full error chain, which is invaluable for
25//!   debugging the root cause of a communication failure.
26//!
27//! - **Contextual Information**: Each error variant includes important context, such as
28//!   the code `location` and the specific `AquariumDevice` that was being controlled
29//!   when the error occurred.
30//!
31//! - **Error Collection**: The `FoodInjection` process is designed to collect multiple
32//!   errors into a `Vec<FoodInjectionError>` rather than failing on the first one.
33//!   This allows it to report a complete set of failures from a single injection
34//!   attempt (e.g., if communication with multiple devices fails).
35//!
36//! ### Error Categories
37//!
38//! The errors fall into two main categories:
39//!
40//! 1.  **Channel Communication Failures**: These occur when sending a command to, or
41//!     receiving a confirmation from, the `RelayManager` thread fails.
42//!
43//! 2.  **Invalid State Errors**: These occur if the logic attempts to set a device to an
44//!     undefined state (i.e., something other than `On` or `Off`).
45
46use crate::launch::channels::AquaChannelError;
47use crate::utilities::channel_content::AquariumDevice;
48use thiserror::Error;
49
50/// Contains error definition for FoodInjection
51#[derive(Error, Debug, Clone)]
52pub enum FoodInjectionError {
53    /// Occurs when sending a command to the relay manager via an MPSC channel fails.
54    /// This typically happens if the receiving end (the relay manager) has been dropped.
55    #[error("[{location}] Failed to send command to relay manager for device: {device}")]
56    RelayManagerSend {
57        location: String,
58        device: AquariumDevice,
59
60        #[source]
61        source: AquaChannelError,
62    },
63
64    /// Occurs when waiting for a confirmation message from the relay manager fails.
65    /// This usually indicates that the relay manager's sending channel was dropped,
66    /// preventing a response from ever being sent.
67    #[error("[{location}] Failed to receive confirmation from relay manager for device: {device}")]
68    RelayManagerReceive {
69        location: String,
70        device: AquariumDevice,
71
72        #[source]
73        source: AquaChannelError,
74    },
75
76    /// An invalid or unexpected target state was requested for a device.
77    /// The device should only be turned ON or OFF.
78    #[error("[{0}] Received undefined state as target state for {1}.")]
79    UndefinedTargetState(String, AquariumDevice),
80}