Skip to content

Commit 6062226

Browse files
authored
feat(sync-only): add support for removing async runtime dependency altogether (#56)
1 parent 2c98f08 commit 6062226

File tree

14 files changed

+190
-33
lines changed

14 files changed

+190
-33
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ tokio = { version = "1.12.0", features = [
3131
"fs",
3232
"io-util",
3333
"macros",
34-
"rt"
34+
"rt",
3535
], optional = true }
3636
tokio-stream = { version = "0.1.7", features = ["io-util"], optional = true }
3737
walkdir = "2.3.2"
@@ -49,7 +49,7 @@ tokio = { version = "1.12.0", features = [
4949
"macros",
5050
"rt",
5151
"rt-multi-thread",
52-
]}
52+
] }
5353

5454
[[bench]]
5555
name = "benchmarks"

README.md

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@ Minimum supported Rust version is `1.43.0`.
3838

3939
## Features
4040

41-
- First-class async support, using either [`async-std`](https://crates.io/crates/async-std) or [`tokio`](https://crates.io/crates/tokio) as its runtime. Sync APIs are available but secondary
41+
- First-class async support, using either
42+
[`async-std`](https://crates.io/crates/async-std) or
43+
[`tokio`](https://crates.io/crates/tokio) as its runtime. Sync APIs are
44+
available but secondary. You can also use sync APIs only and remove the
45+
async runtime dependency.
4246
- `std::fs`-style API
4347
- Extraction by key or by content address (shasum, etc)
4448
- [Subresource Integrity](#integrity) web standard support
@@ -56,21 +60,37 @@ Minimum supported Rust version is `1.43.0`.
5660
- [`miette`](https://crates.io/crates/miette) integration for detailed, helpful error reporting.
5761
- Punches nazis
5862

59-
`async-std` is the default async runtime. To use `tokio` instead, turn off default features and enable the `tokio-runtime` feature, like this:
63+
`async-std` is the default async runtime. To use `tokio` instead, turn off
64+
default features and enable the `tokio-runtime` feature, like this:
6065

6166
```toml
6267
[dependencies]
63-
cacache = { version = "*", default-features = false, features = ["tokio-runtime"] }
68+
cacache = { version = "*", default-features = false, features = ["tokio-runtime", "mmap"] }
69+
```
70+
71+
You can also remove async APIs altogether, including removing async runtime
72+
dependency:
73+
74+
```toml
75+
[dependencies]
76+
cacache = { version = "*", default-features = false, features = ["mmap"] }
6477
```
6578

6679
Experimental support for symlinking to existing files is provided via the
6780
"link_to" feature.
6881

6982
## Contributing
7083

71-
The cacache team enthusiastically welcomes contributions and project participation! There's a bunch of things you can do if you want to contribute! The [Contributor Guide](CONTRIBUTING.md) has all the information you need for everything from reporting bugs to contributing entire new features. Please don't hesitate to jump in if you'd like to, or even ask us questions if something isn't clear.
84+
The cacache team enthusiastically welcomes contributions and project
85+
participation! There's a bunch of things you can do if you want to contribute!
86+
The [Contributor Guide](CONTRIBUTING.md) has all the information you need for
87+
everything from reporting bugs to contributing entire new features. Please
88+
don't hesitate to jump in if you'd like to, or even ask us questions if
89+
something isn't clear.
7290

73-
All participants and maintainers in this project are expected to follow [Code of Conduct](CODE_OF_CONDUCT.md), and just generally be excellent to each other.
91+
All participants and maintainers in this project are expected to follow [Code
92+
of Conduct](CODE_OF_CONDUCT.md), and just generally be excellent to each
93+
other.
7494

7595
Happy hacking!
7696

benches/benchmarks.rs

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ fn baseline_read_many_sync(c: &mut Criterion) {
6262
});
6363
}
6464

65+
#[cfg(any(feature = "async-std", feature = "tokio"))]
6566
fn baseline_read_async(c: &mut Criterion) {
6667
let tmp = tempfile::tempdir().unwrap();
6768
let path = tmp.path().join("test_file");
@@ -74,6 +75,7 @@ fn baseline_read_async(c: &mut Criterion) {
7475
});
7576
}
7677

78+
#[cfg(any(feature = "async-std", feature = "tokio"))]
7779
fn baseline_read_many_async(c: &mut Criterion) {
7880
let tmp = tempfile::tempdir().unwrap();
7981
let paths: Vec<_> = (0..)
@@ -188,6 +190,7 @@ fn read_hash_sync_big_data_xxh3(c: &mut Criterion) {
188190
});
189191
}
190192

193+
#[cfg(any(feature = "async-std", feature = "tokio"))]
191194
fn read_hash_many_async(c: &mut Criterion) {
192195
let tmp = tempfile::tempdir().unwrap();
193196
let cache = tmp.path().to_owned();
@@ -209,6 +212,7 @@ fn read_hash_many_async(c: &mut Criterion) {
209212
});
210213
}
211214

215+
#[cfg(any(feature = "async-std", feature = "tokio"))]
212216
fn read_hash_async(c: &mut Criterion) {
213217
let tmp = tempfile::tempdir().unwrap();
214218
let cache = tmp.path().to_owned();
@@ -219,6 +223,7 @@ fn read_hash_async(c: &mut Criterion) {
219223
});
220224
}
221225

226+
#[cfg(any(feature = "async-std", feature = "tokio"))]
222227
fn read_async(c: &mut Criterion) {
223228
let tmp = tempfile::tempdir().unwrap();
224229
let cache = tmp.path().to_owned();
@@ -229,6 +234,7 @@ fn read_async(c: &mut Criterion) {
229234
});
230235
}
231236

237+
#[cfg(any(feature = "async-std", feature = "tokio"))]
232238
fn read_hash_async_big_data(c: &mut Criterion) {
233239
let tmp = tempfile::tempdir().unwrap();
234240
let cache = tmp.path().to_owned();
@@ -271,6 +277,8 @@ fn write_hash_xxh3(c: &mut Criterion) {
271277
})
272278
});
273279
}
280+
281+
#[cfg(any(feature = "async-std", feature = "tokio"))]
274282
fn write_hash_async(c: &mut Criterion) {
275283
let tmp = tempfile::tempdir().unwrap();
276284
let cache = tmp.path().to_owned();
@@ -285,6 +293,7 @@ fn write_hash_async(c: &mut Criterion) {
285293
});
286294
}
287295

296+
#[cfg(any(feature = "async-std", feature = "tokio"))]
288297
fn write_hash_async_xxh3(c: &mut Criterion) {
289298
let tmp = tempfile::tempdir().unwrap();
290299
let cache = tmp.path().to_owned();
@@ -316,6 +325,7 @@ fn create_tmpfile(tmp: &tempfile::TempDir, buf: &[u8]) -> PathBuf {
316325
}
317326

318327
#[cfg(feature = "link_to")]
328+
#[cfg(any(feature = "async-std", feature = "tokio"))]
319329
fn link_to_async(c: &mut Criterion) {
320330
let tmp = tempfile::tempdir().unwrap();
321331
let target = create_tmpfile(&tmp, b"hello world");
@@ -338,7 +348,7 @@ fn link_to_async(c: &mut Criterion) {
338348
});
339349
}
340350

341-
#[cfg(feature = "link_to")]
351+
#[cfg(all(feature = "link_to", any(feature = "async-std", feature = "tokio")))]
342352
fn link_to_hash_async(c: &mut Criterion) {
343353
let tmp = tempfile::tempdir().unwrap();
344354
let target = create_tmpfile(&tmp, b"hello world");
@@ -384,35 +394,55 @@ criterion_group!(
384394
benches,
385395
baseline_read_sync,
386396
baseline_read_many_sync,
387-
baseline_read_async,
388-
baseline_read_many_async,
389-
read_hash_async,
390-
read_hash_many_async,
391-
read_async,
392397
write_hash,
393398
write_hash_xxh3,
394-
write_hash_async,
395-
write_hash_async_xxh3,
396399
read_hash_sync,
397400
read_hash_sync_xxh3,
398401
read_hash_many_sync,
399402
read_hash_many_sync_xxh3,
400403
read_sync,
401-
read_hash_async_big_data,
402404
read_hash_sync_big_data,
403405
read_hash_sync_big_data_xxh3,
404406
);
405407

406-
#[cfg(feature = "link_to")]
408+
#[cfg(any(feature = "async-std", feature = "tokio"))]
407409
criterion_group!(
408-
link_to_benches,
409-
link_to_async,
410-
link_to_hash_async,
411-
link_to_sync,
412-
link_to_hash_sync
410+
benches_async,
411+
baseline_read_async,
412+
baseline_read_many_async,
413+
read_hash_async,
414+
read_hash_many_async,
415+
read_async,
416+
write_hash_async,
417+
write_hash_async_xxh3,
418+
read_hash_async_big_data,
413419
);
414420

421+
#[cfg(all(feature = "link_to", any(feature = "async-std", feature = "tokio")))]
422+
criterion_group!(link_to_benches_async, link_to_async, link_to_hash_async,);
423+
415424
#[cfg(feature = "link_to")]
425+
criterion_group!(link_to_benches, link_to_sync, link_to_hash_sync);
426+
427+
#[cfg(all(
428+
feature = "link_to",
429+
not(any(feature = "async-std", feature = "tokio"))
430+
))]
416431
criterion_main!(benches, link_to_benches);
417-
#[cfg(not(feature = "link_to"))]
432+
#[cfg(all(
433+
not(feature = "link_to"),
434+
any(feature = "async-std", feature = "tokio")
435+
))]
436+
criterion_main!(benches, benches_async);
437+
#[cfg(all(feature = "link_to", any(feature = "async-std", feature = "tokio")))]
438+
criterion_main!(
439+
benches,
440+
benches_async,
441+
link_to_benches,
442+
link_to_benches_async
443+
);
444+
#[cfg(all(
445+
not(feature = "link_to"),
446+
not(any(feature = "async-std", feature = "tokio"))
447+
))]
418448
criterion_main!(benches);

src/async_lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,8 @@ pub async fn create_named_tempfile(tmp_path: std::path::PathBuf) -> crate::Resul
121121
#[inline]
122122
pub async fn create_named_tempfile(tmp_path: std::path::PathBuf) -> crate::Result<NamedTempFile> {
123123
let cloned = tmp_path.clone();
124-
Ok(spawn_blocking(|| NamedTempFile::new_in(tmp_path))
124+
spawn_blocking(|| NamedTempFile::new_in(tmp_path))
125125
.await
126126
.unwrap()
127-
.with_context(|| format!("Failed to create a temp file at {}", cloned.display()))?)
127+
.with_context(|| format!("Failed to create a temp file at {}", cloned.display()))
128128
}

src/content/linkto.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ use ssri::{Algorithm, Integrity, IntegrityOpts};
22
use std::fs::DirBuilder;
33
use std::fs::File;
44
use std::path::{Path, PathBuf};
5+
#[cfg(any(feature = "async-std", feature = "tokio"))]
56
use std::pin::Pin;
7+
#[cfg(any(feature = "async-std", feature = "tokio"))]
68
use std::task::{Context, Poll};
79

10+
#[cfg(any(feature = "async-std", feature = "tokio"))]
811
use crate::async_lib::AsyncRead;
912
use crate::content::path;
1013
use crate::errors::{IoErrorExt, Result};
@@ -103,6 +106,7 @@ impl std::io::Read for ToLinker {
103106
/// An `AsyncRead`-like type that calculates the integrity of a file as it is
104107
/// read. When the linker is committed, a symlink is created from the cache to
105108
/// the target file using the integrity computed from the file's contents.
109+
#[cfg(any(feature = "async-std", feature = "tokio"))]
106110
pub struct AsyncToLinker {
107111
/// The path to the target file that will be symlinked from the cache.
108112
target: PathBuf,
@@ -114,6 +118,7 @@ pub struct AsyncToLinker {
114118
builder: IntegrityOpts,
115119
}
116120

121+
#[cfg(any(feature = "async-std", feature = "tokio"))]
117122
impl AsyncRead for AsyncToLinker {
118123
#[cfg(feature = "async-std")]
119124
fn poll_read(
@@ -143,6 +148,7 @@ impl AsyncRead for AsyncToLinker {
143148
}
144149
}
145150

151+
#[cfg(any(feature = "async-std", feature = "tokio"))]
146152
impl AsyncToLinker {
147153
pub async fn new(cache: &Path, algo: Algorithm, target: &Path) -> Result<Self> {
148154
let file = crate::async_lib::File::open(target)
@@ -216,6 +222,7 @@ mod tests {
216222
assert_eq!(std::fs::read(cpath).unwrap(), b"hello world");
217223
}
218224

225+
#[cfg(any(feature = "async-std", feature = "tokio"))]
219226
#[async_test]
220227
async fn basic_async_link() {
221228
let tmp = tempfile::tempdir().unwrap();

src/content/read.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use std::fs::{self, File};
22
use std::io::Read;
33
use std::path::Path;
4+
#[cfg(any(feature = "async-std", feature = "tokio"))]
45
use std::pin::Pin;
6+
#[cfg(any(feature = "async-std", feature = "tokio"))]
57
use std::task::{Context, Poll};
68

79
#[cfg(feature = "async-std")]
@@ -11,6 +13,7 @@ use tokio::io::AsyncReadExt;
1113

1214
use ssri::{Algorithm, Integrity, IntegrityChecker};
1315

16+
#[cfg(any(feature = "async-std", feature = "tokio"))]
1417
use crate::async_lib::AsyncRead;
1518
use crate::content::path;
1619
use crate::errors::{IoErrorExt, Result};
@@ -34,11 +37,13 @@ impl Reader {
3437
}
3538
}
3639

40+
#[cfg(any(feature = "async-std", feature = "tokio"))]
3741
pub struct AsyncReader {
3842
fd: crate::async_lib::File,
3943
checker: IntegrityChecker,
4044
}
4145

46+
#[cfg(any(feature = "async-std", feature = "tokio"))]
4247
impl AsyncRead for AsyncReader {
4348
#[cfg(feature = "async-std")]
4449
fn poll_read(
@@ -68,6 +73,7 @@ impl AsyncRead for AsyncReader {
6873
}
6974
}
7075

76+
#[cfg(any(feature = "async-std", feature = "tokio"))]
7177
impl AsyncReader {
7278
pub fn check(self) -> Result<Algorithm> {
7379
Ok(self.checker.result()?)
@@ -87,6 +93,7 @@ pub fn open(cache: &Path, sri: Integrity) -> Result<Reader> {
8793
})
8894
}
8995

96+
#[cfg(any(feature = "async-std", feature = "tokio"))]
9097
pub async fn open_async(cache: &Path, sri: Integrity) -> Result<AsyncReader> {
9198
let cpath = path::content_path(cache, &sri);
9299
Ok(AsyncReader {
@@ -112,6 +119,7 @@ pub fn read(cache: &Path, sri: &Integrity) -> Result<Vec<u8>> {
112119
Ok(ret)
113120
}
114121

122+
#[cfg(any(feature = "async-std", feature = "tokio"))]
115123
pub async fn read_async<'a>(cache: &'a Path, sri: &'a Integrity) -> Result<Vec<u8>> {
116124
let cpath = path::content_path(cache, sri);
117125
let ret = crate::async_lib::read(&cpath).await.with_context(|| {
@@ -158,6 +166,7 @@ pub fn copy(cache: &Path, sri: &Integrity, to: &Path) -> Result<u64> {
158166
Ok(size as u64)
159167
}
160168

169+
#[cfg(any(feature = "async-std", feature = "tokio"))]
161170
pub async fn copy_unchecked_async<'a>(
162171
cache: &'a Path,
163172
sri: &'a Integrity,
@@ -176,6 +185,7 @@ pub async fn copy_unchecked_async<'a>(
176185
Ok(())
177186
}
178187

188+
#[cfg(any(feature = "async-std", feature = "tokio"))]
179189
pub async fn copy_async<'a>(cache: &'a Path, sri: &'a Integrity, to: &'a Path) -> Result<u64> {
180190
copy_unchecked_async(cache, sri, to).await?;
181191
let mut reader = open_async(cache, sri.clone()).await?;
@@ -230,6 +240,7 @@ pub fn hard_link(cache: &Path, sri: &Integrity, to: &Path) -> Result<()> {
230240
Ok(())
231241
}
232242

243+
#[cfg(any(feature = "async-std", feature = "tokio"))]
233244
pub async fn hard_link_async(cache: &Path, sri: &Integrity, to: &Path) -> Result<()> {
234245
hard_link_unchecked(cache, sri, to)?;
235246
let mut reader = open_async(cache, sri.clone()).await?;
@@ -259,6 +270,7 @@ pub fn has_content(cache: &Path, sri: &Integrity) -> Option<Integrity> {
259270
}
260271
}
261272

273+
#[cfg(any(feature = "async-std", feature = "tokio"))]
262274
pub async fn has_content_async(cache: &Path, sri: &Integrity) -> Option<Integrity> {
263275
if crate::async_lib::metadata(path::content_path(cache, sri))
264276
.await

src/content/rm.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ pub fn rm(cache: &Path, sri: &Integrity) -> Result<()> {
1616
Ok(())
1717
}
1818

19+
#[cfg(any(feature = "async-std", feature = "tokio"))]
1920
pub async fn rm_async(cache: &Path, sri: &Integrity) -> Result<()> {
2021
crate::async_lib::remove_file(path::content_path(cache, sri))
2122
.await

0 commit comments

Comments
 (0)