1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
//! Workers for asset data collection and information updates.
//!
//! This module defines traits and implementations for workers that monitor and update asset information.
//! Workers are responsible for collecting data from various sources and updating asset information in the store.
//!
//! The module provides:
//!
//! - The [`AssetWorker`] trait which defines the common interface for all asset workers
//! - Specialized worker implementations for different protocols and data sources
//! - Error handling specific to asset workers
//!
//! # Worker Types
//!
//! The module includes various worker implementations:
//!
//! - REST-based workers in the [`rest`] module for HTTP/HTTPS API polling
//! - WebSocket-based workers in the [`websocket`] module for real-time data streaming
//!
//! # Worker Lifecycle
//!
//! Workers follow a typical lifecycle pattern:
//!
//! 1. **Initialization**: Workers are built using their `build` method and configured with options
//! 3. **Running**: Workers run continuously, collecting data from sources and updating the store
//! 4. **Error Handling**: Workers should handle temporary failures gracefully with retries
//! 5. **Shutdown**: Workers should support graceful shutdown when requested
//!
//! # Worker Storage
//!
//! Workers should use the [`WorkerStore`](crate::store::WorkerStore) wrapper to interact with the main store.
//! This wrapper provides namespace isolation for each worker, ensuring that different workers
//! can operate without conflicts. Each worker should use the WorkerStore to update asset
//! information through the `set_asset_info` and `set_batch_asset_info` methods.
//!
//! # Extensibility
//!
//! While this module provides general-purpose implementations that cover common use cases,
//! the [`AssetWorker`] trait is designed for extensibility. Users can create custom worker
//! implementations by implementing this trait to support specialized data sources, protocols,
//! or business logic beyond what's provided in the standard implementations.
//!
//! # Implementation
//!
//! When implementing a new worker type:
//!
//! 1. Implement the [`AssetWorker`] trait
//! 2. Define appropriate configuration options via the associated `Opts` type
//! 3. Implement the `build` method to create worker instances from configuration
//! 4. Implement any protocol-specific functionality in the worker
//! 5. Use [`WorkerStore`](crate::store::WorkerStore) to store asset information
//!
//! Workers are typically registered with a worker registry and managed by the system
//! to handle data collection and updates in a coordinated way.
use AssetWorkerError;
use crateStore;
/// The universal trait for all workers that collect and update asset info.
///
/// This trait defines the common interface that all asset workers must implement,
/// allowing the system to interact with different types of workers in a uniform way.
/// Each worker is responsible for monitoring specific assets and updating their information
/// in the store.
///
/// Worker implementations should:
/// - Collect data from sources using appropriate methods
/// - Parse and validate the received data
/// - Update asset information using the [`WorkerStore`](crate::store::WorkerStore)
/// - Handle errors and implement retry mechanisms
/// - Support graceful shutdown
///
/// # Required Methods
///
/// Implementors must define:
/// * `name()` - Returns a unique identifier for the worker type
/// * `build()` - Creates a new worker instance with the specified options and query IDs
///
/// # Worker Store Usage
///
/// Workers should use the [`WorkerStore`](crate::store::WorkerStore) to interact with
/// the main store. This provides namespace isolation and ensures that different workers
/// can operate without conflicts. Typically, a worker implementation will:
///
/// 1. Receive a reference to the main store in its `build` method
/// 2. Create a `WorkerStore` instance with the worker's name as prefix
/// 3. Use the `WorkerStore` to update asset information
///
/// # Examples
///
/// Implementing a simple HTTP polling worker:
///
/// ```rust
/// use std::time::Duration;
/// use async_trait::async_trait;
/// use bothan_lib::worker::{AssetWorker, error::AssetWorkerError};
/// use bothan_lib::store::{Store, WorkerStore};
/// use bothan_lib::types::AssetInfo;
/// use rust_decimal::Decimal;
///
/// // Worker configuration
/// #[derive(Clone)]
/// struct HttpPollerOpts {
/// poll_interval: Duration,
/// endpoint: String,
/// }
///
/// // Worker implementation
/// struct HttpPoller {
/// opts: HttpPollerOpts,
/// ids: Vec<String>,
/// }
///
/// #[async_trait]
/// impl AssetWorker for HttpPoller {
/// type Opts = HttpPollerOpts;
///
/// fn name(&self) -> &'static str {
/// "http_poller"
/// }
///
/// async fn build<S: Store + 'static>(
/// opts: Self::Opts,
/// store: &S,
/// ids: Vec<String>,
/// ) -> Result<Self, AssetWorkerError> {
/// // Create a worker-specific store with the worker's name as prefix
/// let worker_store = WorkerStore::new(store, "http_poller");
///
/// // In a real implementation, you would also have methods for:
/// // - Starting the worker (data collection loop)
/// // - Handling errors and retries
/// // - Shutting down gracefully
///
/// Ok(HttpPoller {
/// opts,
/// ids,
/// })
/// }
/// }
/// ```