Skip to content

Commit 63d2143

Browse files
author
Michael-F-Bryan
committed
Split Summary into two types
1 parent 0904a42 commit 63d2143

File tree

8 files changed

+200
-157
lines changed

8 files changed

+200
-157
lines changed

lib/wasi/src/runtime/package_loader/builtin_loader.rs

+39-35
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::{
1818
http::{HttpClient, HttpRequest, HttpResponse, USER_AGENT},
1919
runtime::{
2020
package_loader::PackageLoader,
21-
resolver::{Summary, WebcHash},
21+
resolver::{DistributionInfo, Summary, WebcHash},
2222
},
2323
};
2424

@@ -76,9 +76,9 @@ impl BuiltinLoader {
7676
Ok(None)
7777
}
7878

79-
async fn download(&self, summary: &Summary) -> Result<Bytes, Error> {
80-
if summary.webc.scheme() == "file" {
81-
if let Ok(path) = summary.webc.to_file_path() {
79+
async fn download(&self, dist: &DistributionInfo) -> Result<Bytes, Error> {
80+
if dist.webc.scheme() == "file" {
81+
if let Ok(path) = dist.webc.to_file_path() {
8282
// FIXME: This will block the thread
8383
let bytes = std::fs::read(&path)
8484
.with_context(|| format!("Unable to read \"{}\"", path.display()))?;
@@ -87,7 +87,7 @@ impl BuiltinLoader {
8787
}
8888

8989
let request = HttpRequest {
90-
url: summary.webc.to_string(),
90+
url: dist.webc.to_string(),
9191
method: "GET".to_string(),
9292
headers: vec![
9393
("Accept".to_string(), "application/webc".to_string()),
@@ -117,17 +117,17 @@ impl BuiltinLoader {
117117
async fn save_and_load_as_mmapped(
118118
&self,
119119
webc: &[u8],
120-
summary: &Summary,
120+
dist: &DistributionInfo,
121121
) -> Result<Container, Error> {
122122
// First, save it to disk
123-
self.fs.save(webc, summary).await?;
123+
self.fs.save(webc, dist).await?;
124124

125125
// Now try to load it again. The resulting container should use
126126
// a memory-mapped file rather than an in-memory buffer.
127-
match self.fs.lookup(&summary.webc_sha256).await? {
127+
match self.fs.lookup(&dist.webc_sha256).await? {
128128
Some(container) => {
129129
// we also want to make sure it's in the in-memory cache
130-
self.in_memory.save(&container, summary.webc_sha256);
130+
self.in_memory.save(&container, dist.webc_sha256);
131131

132132
Ok(container)
133133
}
@@ -144,20 +144,20 @@ impl BuiltinLoader {
144144
#[async_trait::async_trait]
145145
impl PackageLoader for BuiltinLoader {
146146
async fn load(&self, summary: &Summary) -> Result<Container, Error> {
147-
if let Some(container) = self.get_cached(&summary.webc_sha256).await? {
147+
if let Some(container) = self.get_cached(&summary.dist.webc_sha256).await? {
148148
return Ok(container);
149149
}
150150

151151
// looks like we had a cache miss and need to download it manually
152152
let bytes = self
153-
.download(summary)
153+
.download(&summary.dist)
154154
.await
155-
.with_context(|| format!("Unable to download \"{}\"", summary.webc))?;
155+
.with_context(|| format!("Unable to download \"{}\"", summary.dist.webc))?;
156156

157157
// We want to cache the container we downloaded, but we want to do it
158158
// in a smart way to keep memory usage down.
159159

160-
match self.save_and_load_as_mmapped(&bytes, summary).await {
160+
match self.save_and_load_as_mmapped(&bytes, &summary.dist).await {
161161
Ok(container) => {
162162
// The happy path - we've saved to both caches and loaded the
163163
// container from disk (hopefully using mmap) so we're done.
@@ -166,17 +166,17 @@ impl PackageLoader for BuiltinLoader {
166166
Err(e) => {
167167
tracing::warn!(
168168
error=&*e,
169-
pkg.name=%summary.package_name,
170-
pkg.version=%summary.version,
171-
pkg.hash=?summary.webc_sha256,
172-
pkg.url=%summary.webc,
169+
pkg.name=%summary.pkg.name,
170+
pkg.version=%summary.pkg.version,
171+
pkg.hash=?summary.dist.webc_sha256,
172+
pkg.url=%summary.dist.webc,
173173
"Unable to save the downloaded package to disk",
174174
);
175175
// The sad path - looks like we'll need to keep the whole thing
176176
// in memory.
177177
let container = Container::from_bytes(bytes)?;
178178
// We still want to cache it, of course
179-
self.in_memory.save(&container, summary.webc_sha256);
179+
self.in_memory.save(&container, summary.dist.webc_sha256);
180180
Ok(container)
181181
}
182182
}
@@ -221,8 +221,8 @@ impl FileSystemCache {
221221
}
222222
}
223223

224-
async fn save(&self, webc: &[u8], summary: &Summary) -> Result<(), Error> {
225-
let path = self.path(&summary.webc_sha256);
224+
async fn save(&self, webc: &[u8], dist: &DistributionInfo) -> Result<(), Error> {
225+
let path = self.path(&dist.webc_sha256);
226226

227227
let parent = path.parent().expect("Always within cache_dir");
228228

@@ -273,7 +273,7 @@ mod tests {
273273

274274
use crate::{
275275
http::{HttpRequest, HttpResponse},
276-
runtime::resolver::{SourceId, SourceKind},
276+
runtime::resolver::{PackageInfo, SourceId, SourceKind},
277277
};
278278

279279
use super::*;
@@ -320,25 +320,29 @@ mod tests {
320320
}]));
321321
let loader = BuiltinLoader::new_with_client(temp.path(), client.clone());
322322
let summary = Summary {
323-
package_name: "python/python".to_string(),
324-
version: "0.1.0".parse().unwrap(),
325-
webc: "https://wapm.io/python/python".parse().unwrap(),
326-
webc_sha256: [0xaa; 32].into(),
327-
dependencies: Vec::new(),
328-
commands: Vec::new(),
329-
source: SourceId::new(
330-
SourceKind::Url,
331-
"https://registry.wapm.io/graphql".parse().unwrap(),
332-
),
333-
entrypoint: Some("asdf".to_string()),
323+
pkg: PackageInfo {
324+
name: "python/python".to_string(),
325+
version: "0.1.0".parse().unwrap(),
326+
dependencies: Vec::new(),
327+
commands: Vec::new(),
328+
entrypoint: Some("asdf".to_string()),
329+
},
330+
dist: DistributionInfo {
331+
webc: "https://wapm.io/python/python".parse().unwrap(),
332+
webc_sha256: [0xaa; 32].into(),
333+
source: SourceId::new(
334+
SourceKind::Url,
335+
"https://registry.wapm.io/graphql".parse().unwrap(),
336+
),
337+
},
334338
};
335339

336340
let container = loader.load(&summary).await.unwrap();
337341

338342
// A HTTP request was sent
339343
let requests = client.requests.lock().unwrap();
340344
let request = &requests[0];
341-
assert_eq!(request.url, summary.webc.to_string());
345+
assert_eq!(request.url, summary.dist.webc.to_string());
342346
assert_eq!(request.method, "GET");
343347
assert_eq!(
344348
request.headers,
@@ -351,11 +355,11 @@ mod tests {
351355
let manifest = container.manifest();
352356
assert_eq!(manifest.entrypoint.as_deref(), Some("python"));
353357
// it should have been automatically saved to disk
354-
let path = loader.fs.path(&summary.webc_sha256);
358+
let path = loader.fs.path(&summary.dist.webc_sha256);
355359
assert!(path.exists());
356360
assert_eq!(std::fs::read(&path).unwrap(), PYTHON);
357361
// and cached in memory for next time
358362
let in_memory = loader.in_memory.0.read().unwrap();
359-
assert!(in_memory.contains_key(&summary.webc_sha256));
363+
assert!(in_memory.contains_key(&summary.dist.webc_sha256));
360364
}
361365
}

lib/wasi/src/runtime/resolver/in_memory_source.rs

+34-32
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,14 @@ impl InMemorySource {
6363

6464
/// Add a new [`Summary`] to the [`InMemorySource`].
6565
pub fn add(&mut self, summary: Summary) {
66-
let summaries = self
67-
.packages
68-
.entry(summary.package_name.clone())
69-
.or_default();
66+
let summaries = self.packages.entry(summary.pkg.name.clone()).or_default();
7067
summaries.push(summary);
71-
summaries.sort_by(|left, right| left.version.cmp(&right.version));
72-
summaries.dedup_by(|left, right| left.version == right.version);
68+
summaries.sort_by(|left, right| left.pkg.version.cmp(&right.pkg.version));
69+
summaries.dedup_by(|left, right| left.pkg.version == right.pkg.version);
7370
}
7471

7572
pub fn add_webc(&mut self, path: impl AsRef<Path>) -> Result<(), Error> {
76-
let path = path.as_ref();
77-
78-
let summary = super::extract_summary_from_webc(path, self.id())?;
73+
let summary = Summary::from_webc_file(path, self.id())?;
7974
self.add(summary);
8075

8176
Ok(())
@@ -87,7 +82,7 @@ impl InMemorySource {
8782

8883
pub fn get(&self, package_name: &str, version: &Version) -> Option<&Summary> {
8984
let summaries = self.packages.get(package_name)?;
90-
summaries.iter().find(|s| s.version == *version)
85+
summaries.iter().find(|s| s.pkg.version == *version)
9186
}
9287
}
9388

@@ -105,7 +100,7 @@ impl Source for InMemorySource {
105100
match self.packages.get(full_name) {
106101
Some(summaries) => Ok(summaries
107102
.iter()
108-
.filter(|summary| version.matches(&summary.version))
103+
.filter(|summary| version.matches(&summary.pkg.version))
109104
.cloned()
110105
.collect()),
111106
None => Ok(Vec::new()),
@@ -120,7 +115,10 @@ impl Source for InMemorySource {
120115
mod tests {
121116
use tempfile::TempDir;
122117

123-
use crate::runtime::resolver::Dependency;
118+
use crate::runtime::resolver::{
119+
inputs::{DistributionInfo, PackageInfo},
120+
Dependency,
121+
};
124122

125123
use super::*;
126124

@@ -154,26 +152,30 @@ mod tests {
154152
assert_eq!(
155153
source.packages["sharrattj/bash"][0],
156154
Summary {
157-
package_name: "sharrattj/bash".to_string(),
158-
version: "1.0.12".parse().unwrap(),
159-
webc: Url::from_file_path(bash.canonicalize().unwrap()).unwrap(),
160-
webc_sha256: [
161-
7, 226, 190, 131, 173, 231, 130, 245, 207, 185, 51, 189, 86, 85, 222, 37, 27,
162-
163, 170, 27, 25, 24, 211, 136, 186, 233, 174, 119, 66, 15, 134, 9
163-
]
164-
.into(),
165-
dependencies: vec![Dependency {
166-
alias: "coreutils".to_string(),
167-
pkg: "sharrattj/coreutils@^1.0.11".parse().unwrap()
168-
}],
169-
commands: ["bash", "sh"]
170-
.iter()
171-
.map(|name| crate::runtime::resolver::Command {
172-
name: name.to_string()
173-
})
174-
.collect(),
175-
entrypoint: None,
176-
source: source.id()
155+
pkg: PackageInfo {
156+
name: "sharrattj/bash".to_string(),
157+
version: "1.0.12".parse().unwrap(),
158+
dependencies: vec![Dependency {
159+
alias: "coreutils".to_string(),
160+
pkg: "sharrattj/coreutils@^1.0.11".parse().unwrap()
161+
}],
162+
commands: ["bash", "sh"]
163+
.iter()
164+
.map(|name| crate::runtime::resolver::Command {
165+
name: name.to_string()
166+
})
167+
.collect(),
168+
entrypoint: None,
169+
},
170+
dist: DistributionInfo {
171+
webc: Url::from_file_path(bash.canonicalize().unwrap()).unwrap(),
172+
webc_sha256: [
173+
7, 226, 190, 131, 173, 231, 130, 245, 207, 185, 51, 189, 86, 85, 222, 37,
174+
27, 163, 170, 27, 25, 24, 211, 136, 186, 233, 174, 119, 66, 15, 134, 9
175+
]
176+
.into(),
177+
source: source.id()
178+
},
177179
}
178180
);
179181
}

lib/wasi/src/runtime/resolver/inputs.rs

+30-18
Original file line numberDiff line numberDiff line change
@@ -105,39 +105,51 @@ impl Dependency {
105105
/// [source]: crate::runtime::resolver::Source
106106
#[derive(Debug, Clone, PartialEq, Eq)]
107107
pub struct Summary {
108+
pub pkg: PackageInfo,
109+
pub dist: DistributionInfo,
110+
}
111+
112+
impl Summary {
113+
pub fn package_id(&self) -> PackageId {
114+
PackageId {
115+
package_name: self.pkg.name.clone(),
116+
version: self.pkg.version.clone(),
117+
source: self.dist.source.clone(),
118+
}
119+
}
120+
}
121+
122+
/// Information about a package's contents.
123+
#[derive(Debug, Clone, PartialEq, Eq)]
124+
pub struct PackageInfo {
108125
/// The package's full name (i.e. `wasmer/wapm2pirita`).
109-
pub package_name: String,
126+
pub name: String,
110127
/// The package version.
111128
pub version: Version,
112-
/// A URL that can be used to download the `*.webc` file.
113-
pub webc: Url,
114-
/// A SHA-256 checksum for the `*.webc` file.
115-
pub webc_sha256: WebcHash,
116-
/// Any dependencies this package may have.
117-
pub dependencies: Vec<Dependency>,
118129
/// Commands this package exposes to the outside world.
119130
pub commands: Vec<Command>,
120131
/// The name of a [`Command`] that should be used as this package's
121132
/// entrypoint.
122133
pub entrypoint: Option<String>,
134+
/// Any dependencies this package may have.
135+
pub dependencies: Vec<Dependency>,
136+
}
137+
138+
/// Information used when retrieving a package.
139+
#[derive(Debug, Clone, PartialEq, Eq)]
140+
pub struct DistributionInfo {
141+
/// A URL that can be used to download the `*.webc` file.
142+
pub webc: Url,
143+
/// A SHA-256 checksum for the `*.webc` file.
144+
pub webc_sha256: WebcHash,
123145
/// The [`Source`][source] this [`Summary`] came from.
124146
///
125147
/// [source]: crate::runtime::resolver::Source
126148
pub source: SourceId,
127149
}
128150

129-
impl Summary {
130-
pub fn package_id(&self) -> PackageId {
131-
PackageId {
132-
package_name: self.package_name.clone(),
133-
version: self.version.clone(),
134-
source: self.source.clone(),
135-
}
136-
}
137-
}
138-
139151
/// The SHA-256 hash of a `*.webc` file.
140-
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
152+
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
141153
pub struct WebcHash([u8; 32]);
142154

143155
impl WebcHash {

lib/wasi/src/runtime/resolver/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ mod wapm_source;
1010

1111
pub use self::{
1212
in_memory_source::InMemorySource,
13-
inputs::{Command, Dependency, PackageSpecifier, Summary, WebcHash},
13+
inputs::{
14+
Command, Dependency, DistributionInfo, PackageInfo, PackageSpecifier, Summary, WebcHash,
15+
},
1416
multi_source_registry::MultiSourceRegistry,
1517
outputs::{
1618
DependencyGraph, FileSystemMapping, ItemLocation, PackageId, Resolution, ResolvedPackage,
@@ -20,5 +22,3 @@ pub use self::{
2022
source::{Source, SourceId, SourceKind},
2123
wapm_source::WapmSource,
2224
};
23-
24-
pub(crate) use self::utils::{extract_summary_from_manifest, extract_summary_from_webc};

lib/wasi/src/runtime/resolver/registry.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub trait Registry: Send + Sync + Debug {
1717
let candidates = self.query(pkg).await?;
1818
candidates
1919
.into_iter()
20-
.max_by(|left, right| left.version.cmp(&right.version))
20+
.max_by(|left, right| left.pkg.version.cmp(&right.pkg.version))
2121
.ok_or_else(|| Error::msg("Couldn't find a package version satisfying that constraint"))
2222
}
2323
}

0 commit comments

Comments
 (0)