Skip to content

Commit 938a8eb

Browse files
authored
refactor(ext/cache): use concrete error type (denoland#26109)
1 parent 3df8f16 commit 938a8eb

File tree

5 files changed

+88
-38
lines changed

5 files changed

+88
-38
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/cache/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ deno_core.workspace = true
1919
rusqlite.workspace = true
2020
serde.workspace = true
2121
sha2.workspace = true
22+
thiserror.workspace = true
2223
tokio.workspace = true

ext/cache/lib.rs

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use std::sync::Arc;
77

88
use async_trait::async_trait;
99
use deno_core::error::type_error;
10-
use deno_core::error::AnyError;
1110
use deno_core::op2;
1211
use deno_core::serde::Deserialize;
1312
use deno_core::serde::Serialize;
@@ -19,6 +18,20 @@ use deno_core::ResourceId;
1918
mod sqlite;
2019
pub use sqlite::SqliteBackedCache;
2120

21+
#[derive(Debug, thiserror::Error)]
22+
pub enum CacheError {
23+
#[error(transparent)]
24+
Sqlite(#[from] rusqlite::Error),
25+
#[error(transparent)]
26+
JoinError(#[from] tokio::task::JoinError),
27+
#[error(transparent)]
28+
Resource(deno_core::error::AnyError),
29+
#[error(transparent)]
30+
Other(deno_core::error::AnyError),
31+
#[error(transparent)]
32+
Io(#[from] std::io::Error),
33+
}
34+
2235
#[derive(Clone)]
2336
pub struct CreateCache<C: Cache + 'static>(pub Arc<dyn Fn() -> C>);
2437

@@ -92,34 +105,39 @@ pub struct CacheDeleteRequest {
92105
pub trait Cache: Clone + 'static {
93106
type CacheMatchResourceType: Resource;
94107

95-
async fn storage_open(&self, cache_name: String) -> Result<i64, AnyError>;
96-
async fn storage_has(&self, cache_name: String) -> Result<bool, AnyError>;
97-
async fn storage_delete(&self, cache_name: String) -> Result<bool, AnyError>;
108+
async fn storage_open(&self, cache_name: String) -> Result<i64, CacheError>;
109+
async fn storage_has(&self, cache_name: String) -> Result<bool, CacheError>;
110+
async fn storage_delete(
111+
&self,
112+
cache_name: String,
113+
) -> Result<bool, CacheError>;
98114

99115
/// Put a resource into the cache.
100116
async fn put(
101117
&self,
102118
request_response: CachePutRequest,
103119
resource: Option<Rc<dyn Resource>>,
104-
) -> Result<(), AnyError>;
120+
) -> Result<(), CacheError>;
105121

106122
async fn r#match(
107123
&self,
108124
request: CacheMatchRequest,
109125
) -> Result<
110126
Option<(CacheMatchResponseMeta, Option<Self::CacheMatchResourceType>)>,
111-
AnyError,
127+
CacheError,
112128
>;
113-
async fn delete(&self, request: CacheDeleteRequest)
114-
-> Result<bool, AnyError>;
129+
async fn delete(
130+
&self,
131+
request: CacheDeleteRequest,
132+
) -> Result<bool, CacheError>;
115133
}
116134

117135
#[op2(async)]
118136
#[number]
119137
pub async fn op_cache_storage_open<CA>(
120138
state: Rc<RefCell<OpState>>,
121139
#[string] cache_name: String,
122-
) -> Result<i64, AnyError>
140+
) -> Result<i64, CacheError>
123141
where
124142
CA: Cache,
125143
{
@@ -131,7 +149,7 @@ where
131149
pub async fn op_cache_storage_has<CA>(
132150
state: Rc<RefCell<OpState>>,
133151
#[string] cache_name: String,
134-
) -> Result<bool, AnyError>
152+
) -> Result<bool, CacheError>
135153
where
136154
CA: Cache,
137155
{
@@ -143,7 +161,7 @@ where
143161
pub async fn op_cache_storage_delete<CA>(
144162
state: Rc<RefCell<OpState>>,
145163
#[string] cache_name: String,
146-
) -> Result<bool, AnyError>
164+
) -> Result<bool, CacheError>
147165
where
148166
CA: Cache,
149167
{
@@ -155,13 +173,19 @@ where
155173
pub async fn op_cache_put<CA>(
156174
state: Rc<RefCell<OpState>>,
157175
#[serde] request_response: CachePutRequest,
158-
) -> Result<(), AnyError>
176+
) -> Result<(), CacheError>
159177
where
160178
CA: Cache,
161179
{
162180
let cache = get_cache::<CA>(&state)?;
163181
let resource = match request_response.response_rid {
164-
Some(rid) => Some(state.borrow_mut().resource_table.take_any(rid)?),
182+
Some(rid) => Some(
183+
state
184+
.borrow_mut()
185+
.resource_table
186+
.take_any(rid)
187+
.map_err(CacheError::Resource)?,
188+
),
165189
None => None,
166190
};
167191
cache.put(request_response, resource).await
@@ -172,7 +196,7 @@ where
172196
pub async fn op_cache_match<CA>(
173197
state: Rc<RefCell<OpState>>,
174198
#[serde] request: CacheMatchRequest,
175-
) -> Result<Option<CacheMatchResponse>, AnyError>
199+
) -> Result<Option<CacheMatchResponse>, CacheError>
176200
where
177201
CA: Cache,
178202
{
@@ -191,15 +215,15 @@ where
191215
pub async fn op_cache_delete<CA>(
192216
state: Rc<RefCell<OpState>>,
193217
#[serde] request: CacheDeleteRequest,
194-
) -> Result<bool, AnyError>
218+
) -> Result<bool, CacheError>
195219
where
196220
CA: Cache,
197221
{
198222
let cache = get_cache::<CA>(&state)?;
199223
cache.delete(request).await
200224
}
201225

202-
pub fn get_cache<CA>(state: &Rc<RefCell<OpState>>) -> Result<CA, AnyError>
226+
pub fn get_cache<CA>(state: &Rc<RefCell<OpState>>) -> Result<CA, CacheError>
203227
where
204228
CA: Cache,
205229
{
@@ -211,7 +235,9 @@ where
211235
state.put(cache);
212236
Ok(state.borrow::<CA>().clone())
213237
} else {
214-
Err(type_error("CacheStorage is not available in this context"))
238+
Err(CacheError::Other(type_error(
239+
"CacheStorage is not available in this context",
240+
)))
215241
}
216242
}
217243

ext/cache/sqlite.rs

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use crate::serialize_headers;
3030
use crate::vary_header_matches;
3131
use crate::Cache;
3232
use crate::CacheDeleteRequest;
33+
use crate::CacheError;
3334
use crate::CacheMatchRequest;
3435
use crate::CacheMatchResponseMeta;
3536
use crate::CachePutRequest;
@@ -102,7 +103,7 @@ impl Cache for SqliteBackedCache {
102103
/// Open a cache storage. Internally, this creates a row in the
103104
/// sqlite db if the cache doesn't exist and returns the internal id
104105
/// of the cache.
105-
async fn storage_open(&self, cache_name: String) -> Result<i64, AnyError> {
106+
async fn storage_open(&self, cache_name: String) -> Result<i64, CacheError> {
106107
let db = self.connection.clone();
107108
let cache_storage_dir = self.cache_storage_dir.clone();
108109
spawn_blocking(move || {
@@ -121,14 +122,14 @@ impl Cache for SqliteBackedCache {
121122
)?;
122123
let responses_dir = get_responses_dir(cache_storage_dir, cache_id);
123124
std::fs::create_dir_all(responses_dir)?;
124-
Ok::<i64, AnyError>(cache_id)
125+
Ok::<i64, CacheError>(cache_id)
125126
})
126127
.await?
127128
}
128129

129130
/// Check if a cache with the provided name exists.
130131
/// Note: this doesn't check the disk, it only checks the sqlite db.
131-
async fn storage_has(&self, cache_name: String) -> Result<bool, AnyError> {
132+
async fn storage_has(&self, cache_name: String) -> Result<bool, CacheError> {
132133
let db = self.connection.clone();
133134
spawn_blocking(move || {
134135
let db = db.lock();
@@ -140,13 +141,16 @@ impl Cache for SqliteBackedCache {
140141
Ok(count > 0)
141142
},
142143
)?;
143-
Ok::<bool, AnyError>(cache_exists)
144+
Ok::<bool, CacheError>(cache_exists)
144145
})
145146
.await?
146147
}
147148

148149
/// Delete a cache storage. Internally, this deletes the row in the sqlite db.
149-
async fn storage_delete(&self, cache_name: String) -> Result<bool, AnyError> {
150+
async fn storage_delete(
151+
&self,
152+
cache_name: String,
153+
) -> Result<bool, CacheError> {
150154
let db = self.connection.clone();
151155
let cache_storage_dir = self.cache_storage_dir.clone();
152156
spawn_blocking(move || {
@@ -167,7 +171,7 @@ impl Cache for SqliteBackedCache {
167171
std::fs::remove_dir_all(cache_dir)?;
168172
}
169173
}
170-
Ok::<bool, AnyError>(maybe_cache_id.is_some())
174+
Ok::<bool, CacheError>(maybe_cache_id.is_some())
171175
})
172176
.await?
173177
}
@@ -176,10 +180,12 @@ impl Cache for SqliteBackedCache {
176180
&self,
177181
request_response: CachePutRequest,
178182
resource: Option<Rc<dyn Resource>>,
179-
) -> Result<(), AnyError> {
183+
) -> Result<(), CacheError> {
180184
let db = self.connection.clone();
181185
let cache_storage_dir = self.cache_storage_dir.clone();
182-
let now = SystemTime::now().duration_since(UNIX_EPOCH)?;
186+
let now = SystemTime::now()
187+
.duration_since(UNIX_EPOCH)
188+
.expect("SystemTime is before unix epoch");
183189

184190
if let Some(resource) = resource {
185191
let body_key = hash(&format!(
@@ -193,7 +199,11 @@ impl Cache for SqliteBackedCache {
193199
let mut file = tokio::fs::File::create(response_path).await?;
194200
let mut buf = BufMutView::new(64 * 1024);
195201
loop {
196-
let (size, buf2) = resource.clone().read_byob(buf).await?;
202+
let (size, buf2) = resource
203+
.clone()
204+
.read_byob(buf)
205+
.await
206+
.map_err(CacheError::Other)?;
197207
if size == 0 {
198208
break;
199209
}
@@ -224,7 +234,7 @@ impl Cache for SqliteBackedCache {
224234
request: CacheMatchRequest,
225235
) -> Result<
226236
Option<(CacheMatchResponseMeta, Option<CacheResponseResource>)>,
227-
AnyError,
237+
CacheError,
228238
> {
229239
let db = self.connection.clone();
230240
let cache_storage_dir = self.cache_storage_dir.clone();
@@ -290,19 +300,17 @@ impl Cache for SqliteBackedCache {
290300
}
291301
Err(err) => return Err(err.into()),
292302
};
293-
return Ok(Some((cache_meta, Some(CacheResponseResource::new(file)))));
294-
}
295-
Some((cache_meta, None)) => {
296-
return Ok(Some((cache_meta, None)));
303+
Ok(Some((cache_meta, Some(CacheResponseResource::new(file)))))
297304
}
298-
None => return Ok(None),
305+
Some((cache_meta, None)) => Ok(Some((cache_meta, None))),
306+
None => Ok(None),
299307
}
300308
}
301309

302310
async fn delete(
303311
&self,
304312
request: CacheDeleteRequest,
305-
) -> Result<bool, AnyError> {
313+
) -> Result<bool, CacheError> {
306314
let db = self.connection.clone();
307315
spawn_blocking(move || {
308316
// TODO(@satyarohith): remove the response body from disk if one exists
@@ -311,17 +319,17 @@ impl Cache for SqliteBackedCache {
311319
"DELETE FROM request_response_list WHERE cache_id = ?1 AND request_url = ?2",
312320
(request.cache_id, &request.request_url),
313321
)?;
314-
Ok::<bool, AnyError>(rows_effected > 0)
322+
Ok::<bool, CacheError>(rows_effected > 0)
315323
})
316324
.await?
317325
}
318326
}
319327

320328
async fn insert_cache_asset(
321-
db: Arc<Mutex<rusqlite::Connection>>,
329+
db: Arc<Mutex<Connection>>,
322330
put: CachePutRequest,
323331
response_body_key: Option<String>,
324-
) -> Result<Option<String>, deno_core::anyhow::Error> {
332+
) -> Result<Option<String>, CacheError> {
325333
spawn_blocking(move || {
326334
let maybe_response_body = {
327335
let db = db.lock();
@@ -339,15 +347,15 @@ async fn insert_cache_asset(
339347
response_body_key,
340348
put.response_status,
341349
put.response_status_text,
342-
SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs(),
350+
SystemTime::now().duration_since(UNIX_EPOCH).expect("SystemTime is before unix epoch").as_secs(),
343351
),
344352
|row| {
345353
let response_body_key: Option<String> = row.get(0)?;
346354
Ok(response_body_key)
347355
},
348356
)?
349357
};
350-
Ok::<Option<String>, AnyError>(maybe_response_body)
358+
Ok::<Option<String>, CacheError>(maybe_response_body)
351359
}).await?
352360
}
353361

runtime/errors.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//! exceptions.
1111
1212
use deno_broadcast_channel::BroadcastChannelError;
13+
use deno_cache::CacheError;
1314
use deno_core::error::AnyError;
1415
use deno_core::serde_json;
1516
use deno_core::url;
@@ -154,6 +155,18 @@ pub fn get_nix_error_class(error: &nix::Error) -> &'static str {
154155
}
155156
}
156157

158+
pub fn get_cache_error(error: &CacheError) -> &'static str {
159+
match error {
160+
CacheError::Sqlite(_) => "Error",
161+
CacheError::JoinError(_) => "Error",
162+
CacheError::Resource(err) => {
163+
deno_core::error::get_custom_error_class(err).unwrap_or("Error")
164+
}
165+
CacheError::Other(e) => get_error_class_name(e).unwrap_or("Error"),
166+
CacheError::Io(err) => get_io_error_class(err),
167+
}
168+
}
169+
157170
fn get_broadcast_channel_error(error: &BroadcastChannelError) -> &'static str {
158171
match error {
159172
BroadcastChannelError::Resource(err) => {
@@ -173,6 +186,7 @@ pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> {
173186
.or_else(|| deno_web::get_error_class_name(e))
174187
.or_else(|| deno_webstorage::get_not_supported_error_class_name(e))
175188
.or_else(|| deno_websocket::get_network_error_class_name(e))
189+
.or_else(|| e.downcast_ref::<CacheError>().map(get_cache_error))
176190
.or_else(|| {
177191
e.downcast_ref::<BroadcastChannelError>()
178192
.map(get_broadcast_channel_error)

0 commit comments

Comments
 (0)