Skip to main content

nautilus_common/cache/
error.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16use nautilus_model::identifiers::{
17    AccountId, ClientOrderId, InstrumentId, OrderListId, PositionId, VenueOrderId,
18};
19use thiserror::Error;
20use ustr::Ustr;
21
22use crate::component::ComponentAccessError;
23
24/// Message used for a missing account lookup.
25pub const ACCOUNT_NOT_FOUND: &str = "account not found in cache";
26
27/// Message used for a missing currency lookup.
28pub const CURRENCY_NOT_FOUND: &str = "currency not found in cache";
29
30/// Message used for a missing instrument lookup.
31pub const INSTRUMENT_NOT_FOUND: &str = "instrument not found in cache";
32
33/// Message used for a missing order book lookup.
34pub const ORDER_BOOK_NOT_FOUND: &str = "order book not found in cache";
35
36/// Message used for a missing own order book lookup.
37pub const OWN_ORDER_BOOK_NOT_FOUND: &str = "own order book not found in cache";
38
39/// Message used for a missing synthetic instrument lookup.
40pub const SYNTHETIC_INSTRUMENT_NOT_FOUND: &str = "synthetic instrument not found in cache";
41
42/// Message used for a missing order lookup.
43pub const ORDER_NOT_FOUND: &str = "order not found in cache";
44
45/// Message used for a missing order list lookup.
46pub const ORDER_LIST_NOT_FOUND: &str = "order list not found in cache";
47
48/// Message used for a missing position lookup.
49pub const POSITION_NOT_FOUND: &str = "position not found in cache";
50
51/// Error returned when a venue order ID is already owned by another client order.
52#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
53#[error(
54    "Venue order ID {venue_order_id} is already owned by client order \
55     {existing_client_order_id} and cannot be claimed by {claimant_client_order_id}"
56)]
57pub struct VenueOrderIdOwnershipError {
58    /// The venue order ID whose ownership conflicts.
59    pub venue_order_id: VenueOrderId,
60    /// The client order which already owns the venue order ID.
61    pub existing_client_order_id: ClientOrderId,
62    /// The client order attempting to claim the venue order ID.
63    pub claimant_client_order_id: ClientOrderId,
64}
65
66/// Error returned when an account cannot be resolved from a cache or store.
67#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
68pub enum AccountLookupError {
69    /// The cache cannot be borrowed for this lookup.
70    #[error(transparent)]
71    Access(#[from] ComponentAccessError),
72    /// The requested account is not present.
73    #[error("{message}: {account_id}", message = ACCOUNT_NOT_FOUND)]
74    NotFound {
75        /// The account identifier that was requested.
76        account_id: AccountId,
77    },
78}
79
80impl AccountLookupError {
81    /// Returns a not-found error for `account_id`.
82    #[must_use]
83    pub const fn not_found(account_id: AccountId) -> Self {
84        Self::NotFound { account_id }
85    }
86}
87
88/// Error returned when a currency cannot be resolved from a cache or store.
89#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
90pub enum CurrencyLookupError {
91    /// The cache cannot be borrowed for this lookup.
92    #[error(transparent)]
93    Access(#[from] ComponentAccessError),
94    /// The requested currency is not present.
95    #[error("{message}: {code}", message = CURRENCY_NOT_FOUND)]
96    NotFound {
97        /// The currency code that was requested.
98        code: Ustr,
99    },
100}
101
102impl CurrencyLookupError {
103    /// Returns a not-found error for `code`.
104    #[must_use]
105    pub const fn not_found(code: Ustr) -> Self {
106        Self::NotFound { code }
107    }
108}
109
110/// Error returned when an instrument cannot be resolved from a cache or store.
111#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
112pub enum InstrumentLookupError {
113    /// The cache cannot be borrowed for this lookup.
114    #[error(transparent)]
115    Access(#[from] ComponentAccessError),
116    /// The requested instrument is not present.
117    #[error("{message}: {instrument_id}", message = INSTRUMENT_NOT_FOUND)]
118    NotFound {
119        /// The instrument identifier that was requested.
120        instrument_id: InstrumentId,
121    },
122}
123
124impl InstrumentLookupError {
125    /// Returns a not-found error for `instrument_id`.
126    #[must_use]
127    pub const fn not_found(instrument_id: InstrumentId) -> Self {
128        Self::NotFound { instrument_id }
129    }
130}
131
132/// Error returned when a synthetic instrument cannot be resolved from a cache or store.
133#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
134pub enum SyntheticInstrumentLookupError {
135    /// The cache cannot be borrowed for this lookup.
136    #[error(transparent)]
137    Access(#[from] ComponentAccessError),
138    /// The requested synthetic instrument is not present.
139    #[error("{message}: {instrument_id}", message = SYNTHETIC_INSTRUMENT_NOT_FOUND)]
140    NotFound {
141        /// The instrument identifier that was requested.
142        instrument_id: InstrumentId,
143    },
144}
145
146impl SyntheticInstrumentLookupError {
147    /// Returns a not-found error for `instrument_id`.
148    #[must_use]
149    pub const fn not_found(instrument_id: InstrumentId) -> Self {
150        Self::NotFound { instrument_id }
151    }
152}
153
154/// Error returned when an order book cannot be resolved from a cache or store.
155#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
156pub enum OrderBookLookupError {
157    /// The cache cannot be borrowed for this lookup.
158    #[error(transparent)]
159    Access(#[from] ComponentAccessError),
160    /// The requested order book is not present.
161    #[error("{message}: {instrument_id}", message = ORDER_BOOK_NOT_FOUND)]
162    NotFound {
163        /// The instrument identifier that was requested.
164        instrument_id: InstrumentId,
165    },
166}
167
168impl OrderBookLookupError {
169    /// Returns a not-found error for `instrument_id`.
170    #[must_use]
171    pub const fn not_found(instrument_id: InstrumentId) -> Self {
172        Self::NotFound { instrument_id }
173    }
174}
175
176/// Error returned when an own order book cannot be resolved from a cache or store.
177#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
178pub enum OwnOrderBookLookupError {
179    /// The cache cannot be borrowed for this lookup.
180    #[error(transparent)]
181    Access(#[from] ComponentAccessError),
182    /// The requested own order book is not present.
183    #[error("{message}: {instrument_id}", message = OWN_ORDER_BOOK_NOT_FOUND)]
184    NotFound {
185        /// The instrument identifier that was requested.
186        instrument_id: InstrumentId,
187    },
188}
189
190impl OwnOrderBookLookupError {
191    /// Returns a not-found error for `instrument_id`.
192    #[must_use]
193    pub const fn not_found(instrument_id: InstrumentId) -> Self {
194        Self::NotFound { instrument_id }
195    }
196}
197
198/// Error returned when an order cannot be resolved from a cache or store.
199#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
200pub enum OrderLookupError {
201    /// The cache cannot be borrowed for this lookup.
202    #[error(transparent)]
203    Access(#[from] ComponentAccessError),
204    /// The requested order is not present.
205    #[error("{message}: {client_order_id}", message = ORDER_NOT_FOUND)]
206    NotFound {
207        /// The client order identifier that was requested.
208        client_order_id: ClientOrderId,
209    },
210}
211
212impl OrderLookupError {
213    /// Returns a not-found error for `client_order_id`.
214    #[must_use]
215    pub const fn not_found(client_order_id: ClientOrderId) -> Self {
216        Self::NotFound { client_order_id }
217    }
218}
219
220/// Error returned when an order list cannot be resolved from a cache or store.
221#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
222pub enum OrderListLookupError {
223    /// The cache cannot be borrowed for this lookup.
224    #[error(transparent)]
225    Access(#[from] ComponentAccessError),
226    /// The requested order list is not present.
227    #[error("{message}: {order_list_id}", message = ORDER_LIST_NOT_FOUND)]
228    NotFound {
229        /// The order list identifier that was requested.
230        order_list_id: OrderListId,
231    },
232}
233
234impl OrderListLookupError {
235    /// Returns a not-found error for `order_list_id`.
236    #[must_use]
237    pub const fn not_found(order_list_id: OrderListId) -> Self {
238        Self::NotFound { order_list_id }
239    }
240}
241
242/// Error returned when a position cannot be resolved from a cache or store.
243#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
244pub enum PositionLookupError {
245    /// The cache cannot be borrowed for this lookup.
246    #[error(transparent)]
247    Access(#[from] ComponentAccessError),
248    /// The requested position is not present.
249    #[error("{message}: {position_id}", message = POSITION_NOT_FOUND)]
250    NotFound {
251        /// The position identifier that was requested.
252        position_id: PositionId,
253    },
254}
255
256impl PositionLookupError {
257    /// Returns a not-found error for `position_id`.
258    #[must_use]
259    pub const fn not_found(position_id: PositionId) -> Self {
260        Self::NotFound { position_id }
261    }
262}