Skip to content

Commit 29fe45c

Browse files
committed
feat: Async retriever
Signed-off-by: Dmitry Dygalo <dmitry@dygalo.dev>
1 parent 6a529dd commit 29fe45c

File tree

19 files changed

+1059
-252
lines changed

19 files changed

+1059
-252
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151
cache-all-crates: "true"
5252
key: ${{ matrix.os }}
5353

54-
- run: cargo test --no-fail-fast
54+
- run: cargo test --no-fail-fast --all-features
5555

5656
test-wasm:
5757
name: Test on WASM

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,22 @@
22

33
## [Unreleased]
44

5+
### Breaking Changes
6+
7+
- The `Retrieve` trait's `retrieve` method now accepts URI references as `&Uri<String>` instead of `&Uri<&str>`.
8+
This aligns with the async version and simplifies internal URI handling. The behavior and available methods remain the same, this is purely a type-level change.
9+
10+
```rust
11+
// Before
12+
fn retrieve(&self, uri: &Uri<&str>) -> Result<Value, Box<dyn std::error::Error + Send + Sync>>
13+
14+
// After
15+
fn retrieve(&self, uri: &Uri<String>) -> Result<Value, Box<dyn std::error::Error + Send + Sync>>
16+
```
17+
518
### Added
619

20+
- Support non-blocking retrieval for external resources during schema resolution via the new `resolve-async` feature. [#385](https://github.com/Stranger6667/jsonschema/issues/385)
721
- Re-export `referencing::Registry` as `jsonschema::Registry`.
822
- `ValidationOptions::with_registry` that allows for providing a predefined `referencing::Registry`. [#682](https://github.com/Stranger6667/jsonschema/issues/682)
923

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ See more usage examples in the [documentation](https://docs.rs/jsonschema).
5252

5353
- 📚 Full support for popular JSON Schema drafts
5454
- 🔧 Custom keywords and format validators
55-
- 🌐 Remote reference fetching (network/file)
55+
- 🌐 Blocking & non-blocking remote reference fetching (network/file)
5656
- 🎨 `Basic` output style as per JSON Schema spec
5757
- ✨ Meta-schema validation for schema documents
5858
- 🔗 Bindings for [Python](https://github.com/Stranger6667/jsonschema/tree/master/crates/jsonschema-py)

crates/jsonschema-py/src/registry.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::sync::Arc;
2-
31
use jsonschema::Resource;
42
use pyo3::{exceptions::PyValueError, prelude::*};
53

@@ -29,7 +27,7 @@ impl Registry {
2927

3028
if let Some(retriever) = retriever {
3129
let func = into_retriever(retriever)?;
32-
options = options.retriever(Arc::new(Retriever { func }));
30+
options = options.retriever(Retriever { func });
3331
}
3432

3533
let pairs = resources.try_iter()?.map(|item| {
@@ -45,7 +43,7 @@ impl Registry {
4543
let pairs: Result<Vec<_>, PyErr> = pairs.collect();
4644

4745
let registry = options
48-
.try_from_resources(pairs?.into_iter())
46+
.build(pairs?)
4947
.map_err(|e| PyValueError::new_err(e.to_string()))?;
5048

5149
Ok(Registry { inner: registry })

crates/jsonschema-py/src/retriever.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ pub(crate) struct Retriever<T: Fn(&str) -> PyResult<Value>> {
1010
}
1111

1212
impl<T: Send + Sync + Fn(&str) -> PyResult<Value>> Retrieve for Retriever<T> {
13-
fn retrieve(&self, uri: &Uri<&str>) -> Result<Value, Box<dyn std::error::Error + Send + Sync>> {
13+
fn retrieve(
14+
&self,
15+
uri: &Uri<String>,
16+
) -> Result<Value, Box<dyn std::error::Error + Send + Sync>> {
1417
Ok((self.func)(uri.as_str())?)
1518
}
1619
}

crates/jsonschema-referencing/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ parking_lot = "0.12.3"
1717
percent-encoding = "2.3.1"
1818
serde_json.workspace = true
1919

20+
async-trait = { version = "0.1.86", optional = true }
21+
futures = { version = "0.3.31", optional = true }
22+
23+
[features]
24+
default = []
25+
retrieve-async = ["dep:async-trait", "dep:futures"]
26+
2027
[lints]
2128
workspace = true
2229

@@ -26,6 +33,7 @@ codspeed-criterion-compat = { version = "2.7", default-features = false }
2633
criterion = { version = "0.5", default-features = false }
2734
referencing_testsuite = { package = "jsonschema-referencing-testsuite", path = "../jsonschema-referencing-testsuite/" }
2835
test-case = "3.3.1"
36+
tokio = { version = "1", features = ["macros", "rt"] }
2937

3038
[[bench]]
3139
harness = false

crates/jsonschema-referencing/src/anchors/mod.rs

Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -243,14 +243,11 @@ mod tests {
243243
},
244244
}));
245245

246-
let registry = Registry::try_from_resources(
247-
[
248-
("http://example.com".to_string(), root.clone()),
249-
("http://example.com/foo/".to_string(), true_resource),
250-
("http://example.com/foo/bar".to_string(), root.clone()),
251-
]
252-
.into_iter(),
253-
)
246+
let registry = Registry::try_from_resources([
247+
("http://example.com".to_string(), root.clone()),
248+
("http://example.com/foo/".to_string(), true_resource),
249+
("http://example.com/foo/bar".to_string(), root.clone()),
250+
])
254251
.expect("Invalid resources");
255252
let resolver = registry
256253
.try_resolver("http://example.com")
@@ -287,14 +284,11 @@ mod tests {
287284
},
288285
}));
289286

290-
let registry = Registry::try_from_resources(
291-
[
292-
("http://example.com".to_string(), two.clone()),
293-
("http://example.com/foo/".to_string(), one),
294-
("http://example.com/foo/bar".to_string(), two.clone()),
295-
]
296-
.into_iter(),
297-
)
287+
let registry = Registry::try_from_resources([
288+
("http://example.com".to_string(), two.clone()),
289+
("http://example.com/foo/".to_string(), one),
290+
("http://example.com/foo/bar".to_string(), two.clone()),
291+
])
298292
.expect("Invalid resources");
299293
let resolver = registry
300294
.try_resolver("http://example.com")
@@ -397,14 +391,11 @@ mod tests {
397391
},
398392
}));
399393

400-
let registry = Registry::try_from_resources(
401-
vec![
402-
("http://example.com".to_string(), root.clone()),
403-
("http://example.com/foo/".to_string(), true_resource),
404-
("http://example.com/foo/bar".to_string(), root.clone()),
405-
]
406-
.into_iter(),
407-
)
394+
let registry = Registry::try_from_resources(vec![
395+
("http://example.com".to_string(), root.clone()),
396+
("http://example.com/foo/".to_string(), true_resource),
397+
("http://example.com/foo/bar".to_string(), root.clone()),
398+
])
408399
.expect("Invalid resources");
409400

410401
let resolver = registry
@@ -442,14 +433,11 @@ mod tests {
442433
}));
443434
let three = Draft::Draft201909.create_resource(json!({"$recursiveAnchor": false}));
444435

445-
let registry = Registry::try_from_resources(
446-
vec![
447-
("http://example.com".to_string(), three),
448-
("http://example.com/foo/".to_string(), two.clone()),
449-
("http://example.com/foo/bar".to_string(), one),
450-
]
451-
.into_iter(),
452-
)
436+
let registry = Registry::try_from_resources(vec![
437+
("http://example.com".to_string(), three),
438+
("http://example.com/foo/".to_string(), two.clone()),
439+
("http://example.com/foo/bar".to_string(), one),
440+
])
453441
.expect("Invalid resources");
454442

455443
let resolver = registry

crates/jsonschema-referencing/src/error.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ impl std::error::Error for Error {
153153
}
154154
}
155155

156+
/// Errors that can occur during URI handling.
156157
#[derive(Debug)]
157158
pub enum UriError {
158159
Parse {

crates/jsonschema-referencing/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,6 @@ pub use retriever::{DefaultRetriever, Retrieve};
2727
pub(crate) use segments::Segments;
2828
pub use specification::Draft;
2929
pub use vocabularies::{Vocabulary, VocabularySet};
30+
31+
#[cfg(feature = "retrieve-async")]
32+
pub use retriever::AsyncRetrieve;

crates/jsonschema-referencing/src/meta.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
//! Built-in JSON Schema meta-schemas.
2+
//!
3+
//! This module provides access to the official JSON Schema meta-schemas for different draft versions.
14
use std::sync::Arc;
25

36
use once_cell::sync::Lazy;

0 commit comments

Comments
 (0)