1use std::{path::Path, sync::Arc, time::Duration};
4
5use futures_util::{StreamExt, stream::BoxStream};
6
7use super::{
8 AddOptions, BatchAddHandle, Dataset, DatasetInfo, KeyList, KeyValueStore, KvEntry, Lease,
9 LeaseId, ListKeysOptions, ListOptions, Page, QueueOpInfo, ReclaimOptions, RequestQueue,
10 RequestSource, StorageClient, StorageResult,
11};
12use crate::{autoscale::ClientLoadSignalHandle, request::Request};
13
14fn observe<T>(handle: &ClientLoadSignalHandle, result: StorageResult<T>) -> StorageResult<T> {
15 match &result {
16 Ok(_) => handle.record_healthy(),
17 Err(error) if error.is_rate_limited() => handle.record_rate_limited(),
18 Err(_) => {}
19 }
20 result
21}
22
23pub struct RateLimitReportingClient {
25 inner: Arc<dyn StorageClient>,
26 handle: ClientLoadSignalHandle,
27}
28
29impl RateLimitReportingClient {
30 #[allow(clippy::new_ret_no_self)]
32 pub fn new(
33 inner: Arc<dyn StorageClient>,
34 handle: ClientLoadSignalHandle,
35 ) -> Arc<dyn StorageClient> {
36 Arc::new(Self { inner, handle })
37 }
38}
39
40#[async_trait::async_trait]
41impl StorageClient for RateLimitReportingClient {
42 async fn open_dataset(&self, name: Option<&str>) -> StorageResult<Arc<dyn Dataset>> {
43 let result = self.inner.open_dataset(name).await;
44 observe(&self.handle, result).map(|inner| {
45 Arc::new(ReportingDataset {
46 inner,
47 handle: self.handle.clone(),
48 }) as Arc<dyn Dataset>
49 })
50 }
51
52 async fn open_key_value_store(
53 &self,
54 name: Option<&str>,
55 ) -> StorageResult<Arc<dyn KeyValueStore>> {
56 let result = self.inner.open_key_value_store(name).await;
57 observe(&self.handle, result).map(|inner| {
58 Arc::new(ReportingKvs {
59 inner,
60 handle: self.handle.clone(),
61 }) as Arc<dyn KeyValueStore>
62 })
63 }
64
65 async fn open_request_queue(&self, name: Option<&str>) -> StorageResult<Arc<dyn RequestQueue>> {
66 let result = self.inner.open_request_queue(name).await;
67 observe(&self.handle, result).map(|inner| {
68 Arc::new(ReportingQueue {
69 inner,
70 handle: self.handle.clone(),
71 }) as Arc<dyn RequestQueue>
72 })
73 }
74
75 async fn purge(&self) -> StorageResult<()> {
76 let result = self.inner.purge().await;
77 observe(&self.handle, result)
78 }
79}
80
81struct ReportingDataset {
82 inner: Arc<dyn Dataset>,
83 handle: ClientLoadSignalHandle,
84}
85
86#[async_trait::async_trait]
87impl Dataset for ReportingDataset {
88 async fn push_json(&self, item: serde_json::Value) -> StorageResult<()> {
89 let result = self.inner.push_json(item).await;
90 observe(&self.handle, result)
91 }
92
93 async fn push_json_batch(&self, items: Vec<serde_json::Value>) -> StorageResult<()> {
94 let result = self.inner.push_json_batch(items).await;
95 observe(&self.handle, result)
96 }
97
98 async fn list_raw(&self, opts: ListOptions) -> StorageResult<Page<serde_json::Value>> {
99 let result = self.inner.list_raw(opts).await;
100 observe(&self.handle, result)
101 }
102
103 fn stream_raw(&self, opts: ListOptions) -> BoxStream<'_, StorageResult<serde_json::Value>> {
104 let handle = self.handle.clone();
105 Box::pin(
106 self.inner
107 .stream_raw(opts)
108 .map(move |result| observe(&handle, result)),
109 )
110 }
111
112 async fn export_json(&self, path: &Path) -> StorageResult<()> {
113 let result = self.inner.export_json(path).await;
114 observe(&self.handle, result)
115 }
116
117 async fn export_csv(&self, path: &Path) -> StorageResult<()> {
118 let result = self.inner.export_csv(path).await;
119 observe(&self.handle, result)
120 }
121
122 async fn info(&self) -> StorageResult<DatasetInfo> {
123 let result = self.inner.info().await;
124 observe(&self.handle, result)
125 }
126}
127
128struct ReportingKvs {
129 inner: Arc<dyn KeyValueStore>,
130 handle: ClientLoadSignalHandle,
131}
132
133#[async_trait::async_trait]
134impl KeyValueStore for ReportingKvs {
135 async fn get_bytes(&self, key: &str) -> StorageResult<Option<KvEntry>> {
136 let result = self.inner.get_bytes(key).await;
137 observe(&self.handle, result)
138 }
139
140 async fn set_bytes(
141 &self,
142 key: &str,
143 bytes: bytes::Bytes,
144 content_type: &str,
145 ) -> StorageResult<()> {
146 let result = self.inner.set_bytes(key, bytes, content_type).await;
147 observe(&self.handle, result)
148 }
149
150 async fn delete(&self, key: &str) -> StorageResult<()> {
151 let result = self.inner.delete(key).await;
152 observe(&self.handle, result)
153 }
154
155 async fn list_keys(&self, opts: ListKeysOptions) -> StorageResult<KeyList> {
156 let result = self.inner.list_keys(opts).await;
157 observe(&self.handle, result)
158 }
159}
160
161struct ReportingQueue {
162 inner: Arc<dyn RequestQueue>,
163 handle: ClientLoadSignalHandle,
164}
165
166#[async_trait::async_trait]
167impl RequestQueue for ReportingQueue {
168 async fn add(&self, req: Request, opts: AddOptions) -> StorageResult<QueueOpInfo> {
169 let result = self.inner.add(req, opts).await;
170 observe(&self.handle, result)
171 }
172
173 async fn add_batch(
174 &self,
175 reqs: Vec<RequestSource>,
176 opts: AddOptions,
177 ) -> StorageResult<BatchAddHandle> {
178 let result = self.inner.add_batch(reqs, opts).await;
179 observe(&self.handle, result)
180 }
181
182 async fn fetch_next(&self) -> StorageResult<Option<Lease>> {
183 let result = self.inner.fetch_next().await;
184 observe(&self.handle, result)
185 }
186
187 async fn mark_handled(&self, lease: Lease) -> StorageResult<()> {
188 let result = self.inner.mark_handled(lease).await;
189 observe(&self.handle, result)
190 }
191
192 async fn reclaim(&self, lease: Lease, opts: ReclaimOptions) -> StorageResult<()> {
193 let result = self.inner.reclaim(lease, opts).await;
194 observe(&self.handle, result)
195 }
196
197 async fn renew(&self, lease_id: &LeaseId, extend_by: Duration) -> StorageResult<()> {
198 let result = self.inner.renew(lease_id, extend_by).await;
199 observe(&self.handle, result)
200 }
201
202 async fn abandon(&self, lease: Lease) -> StorageResult<()> {
203 let result = self.inner.abandon(lease).await;
204 observe(&self.handle, result)
205 }
206
207 async fn is_empty(&self) -> StorageResult<bool> {
208 let result = self.inner.is_empty().await;
209 observe(&self.handle, result)
210 }
211
212 async fn is_finished(&self) -> StorageResult<bool> {
213 let result = self.inner.is_finished().await;
214 observe(&self.handle, result)
215 }
216
217 async fn handled_count(&self) -> StorageResult<u64> {
218 let result = self.inner.handled_count().await;
219 observe(&self.handle, result)
220 }
221
222 async fn pending_count(&self) -> StorageResult<u64> {
223 let result = self.inner.pending_count().await;
224 observe(&self.handle, result)
225 }
226}