Skip to content

Commit 2eacc64

Browse files
committed
Define Registry trait
1 parent ffdb0a8 commit 2eacc64

File tree

5 files changed

+98
-71
lines changed

5 files changed

+98
-71
lines changed

murek/src/core/registry/cache.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
11
use anyhow::Result;
2+
use async_trait::async_trait;
23

4+
use crate::core::registry::source_map::SourceMap;
35
use crate::core::registry::Registry;
46
use crate::core::{ManifestDependency, Package, PackageId, Summary};
57

68
// TODO(mkaput): Really implement what is promised here.
7-
/// A caching wrapper over [`Registry`] which memorizes all queries and downloads.
9+
/// A caching wrapper over another [`Registry`] which memorizes all queries and downloads.
810
pub struct RegistryCache<'c> {
9-
registry: Registry<'c>,
11+
registry: SourceMap<'c>,
1012
}
1113

1214
impl<'c> RegistryCache<'c> {
13-
pub fn new(registry: Registry<'c>) -> Self {
15+
pub fn new(registry: SourceMap<'c>) -> Self {
1416
Self { registry }
1517
}
18+
}
1619

20+
#[async_trait(?Send)]
21+
impl<'c> Registry for RegistryCache<'c> {
1722
/// Attempt to find the packages that match dependency request.
18-
pub async fn query(&mut self, dependency: &ManifestDependency) -> Result<Vec<Summary>> {
23+
async fn query(&mut self, dependency: &ManifestDependency) -> Result<Vec<Summary>> {
1924
self.registry.query(dependency).await
2025
}
2126

2227
/// Fetch full package by its ID.
23-
pub async fn download(&mut self, package_id: PackageId) -> Result<Package> {
28+
async fn download(&mut self, package_id: PackageId) -> Result<Package> {
2429
self.registry.download(package_id).await
2530
}
2631
}

murek/src/core/registry/mod.rs

+7-62
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,16 @@
1-
use std::collections::HashMap;
2-
use std::ops::DerefMut;
3-
41
use anyhow::Result;
5-
use itertools::Itertools;
6-
use tracing::trace;
2+
use async_trait::async_trait;
73

8-
use crate::core::source::Source;
9-
#[cfg(doc)]
10-
use crate::core::Workspace;
11-
use crate::core::{Config, ManifestDependency, Package, PackageId, SourceId, Summary};
12-
use crate::sources::PathSource;
4+
use crate::core::{ManifestDependency, Package, PackageId, Summary};
135

146
pub mod cache;
7+
pub mod source_map;
158

16-
/// Source of information about a group of packages.
17-
pub struct Registry<'c> {
18-
config: &'c Config,
19-
sources: HashMap<SourceId, Box<dyn Source + 'c>>,
20-
}
21-
22-
impl<'c> Registry<'c> {
23-
/// Preload the registry with already loaded [`Package`]s.
24-
///
25-
/// For example, a [`Workspace`] may load packages during construction/parsing/early phases
26-
/// for various operations, and this preload step avoids doubly-loading and
27-
/// parsing packages on the filesystem by inserting them all into the registry
28-
/// with their in-memory formats.
29-
pub fn preloaded(packages: impl Iterator<Item = Package>, config: &'c Config) -> Self {
30-
let sources = packages
31-
.sorted_by_key(|pkg| pkg.id.source_id)
32-
.group_by(|pkg| pkg.id.source_id);
33-
let sources = sources.into_iter().map(|(source_id, packages)| {
34-
let packages = packages.collect::<Vec<_>>();
35-
let source = PathSource::preloaded(&packages, config);
36-
let source: Box<dyn Source + 'c> = Box::new(source);
37-
(source_id, source)
38-
});
39-
let sources = HashMap::from_iter(sources);
40-
41-
Self { config, sources }
42-
}
43-
44-
fn ensure_loaded(&mut self, source_id: SourceId) -> Result<&mut (dyn Source + 'c)> {
45-
// We can't use Entry API here because `load` usage of &self conflicts with it.
46-
#[allow(clippy::map_entry)]
47-
if !self.sources.contains_key(&source_id) {
48-
let source = self.load(source_id)?;
49-
self.sources.insert(source_id, source);
50-
}
51-
52-
Ok(self.sources.get_mut(&source_id).unwrap().deref_mut())
53-
}
54-
55-
fn load(&self, source_id: SourceId) -> Result<Box<dyn Source + 'c>> {
56-
trace!("loading source: {source_id}");
57-
source_id.load(self.config)
58-
}
59-
9+
#[async_trait(?Send)]
10+
pub trait Registry {
6011
/// Attempt to find the packages that match a dependency request.
61-
pub async fn query(&mut self, dependency: &ManifestDependency) -> Result<Vec<Summary>> {
62-
let source = self.ensure_loaded(dependency.source_id)?;
63-
source.query(dependency).await
64-
}
12+
async fn query(&mut self, dependency: &ManifestDependency) -> Result<Vec<Summary>>;
6513

6614
/// Fetch full package by its ID.
67-
pub async fn download(&mut self, package_id: PackageId) -> Result<Package> {
68-
let source = self.ensure_loaded(package_id.source_id)?;
69-
source.download(package_id).await
70-
}
15+
async fn download(&mut self, package_id: PackageId) -> Result<Package>;
7116
}

murek/src/core/registry/source_map.rs

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
use std::collections::HashMap;
2+
use std::ops::DerefMut;
3+
4+
use anyhow::Result;
5+
use async_trait::async_trait;
6+
use itertools::Itertools;
7+
use tracing::trace;
8+
9+
use crate::core::registry::Registry;
10+
use crate::core::source::Source;
11+
#[cfg(doc)]
12+
use crate::core::Workspace;
13+
use crate::core::{Config, ManifestDependency, Package, PackageId, SourceId, Summary};
14+
use crate::sources::PathSource;
15+
16+
/// Source of information about a group of packages.
17+
pub struct SourceMap<'c> {
18+
config: &'c Config,
19+
sources: HashMap<SourceId, Box<dyn Source + 'c>>,
20+
}
21+
22+
impl<'c> SourceMap<'c> {
23+
/// Preload the registry with already loaded [`Package`]s.
24+
///
25+
/// For example, a [`Workspace`] may load packages during construction/parsing/early phases
26+
/// for various operations, and this preload step avoids doubly-loading and
27+
/// parsing packages on the filesystem by inserting them all into the registry
28+
/// with their in-memory formats.
29+
pub fn preloaded(packages: impl Iterator<Item = Package>, config: &'c Config) -> Self {
30+
let sources = packages
31+
.sorted_by_key(|pkg| pkg.id.source_id)
32+
.group_by(|pkg| pkg.id.source_id);
33+
let sources = sources.into_iter().map(|(source_id, packages)| {
34+
let packages = packages.collect::<Vec<_>>();
35+
let source = PathSource::preloaded(&packages, config);
36+
let source: Box<dyn Source + 'c> = Box::new(source);
37+
(source_id, source)
38+
});
39+
let sources = HashMap::from_iter(sources);
40+
41+
Self { config, sources }
42+
}
43+
44+
fn ensure_loaded(&mut self, source_id: SourceId) -> Result<&mut (dyn Source + 'c)> {
45+
// We can't use Entry API here because `load` usage of &self conflicts with it.
46+
#[allow(clippy::map_entry)]
47+
if !self.sources.contains_key(&source_id) {
48+
let source = self.load(source_id)?;
49+
self.sources.insert(source_id, source);
50+
}
51+
52+
Ok(self.sources.get_mut(&source_id).unwrap().deref_mut())
53+
}
54+
55+
fn load(&self, source_id: SourceId) -> Result<Box<dyn Source + 'c>> {
56+
trace!("loading source: {source_id}");
57+
source_id.load(self.config)
58+
}
59+
}
60+
61+
#[async_trait(?Send)]
62+
impl<'c> Registry for SourceMap<'c> {
63+
/// Attempt to find the packages that match a dependency request.
64+
async fn query(&mut self, dependency: &ManifestDependency) -> Result<Vec<Summary>> {
65+
let source = self.ensure_loaded(dependency.source_id)?;
66+
source.query(dependency).await
67+
}
68+
69+
/// Fetch full package by its ID.
70+
async fn download(&mut self, package_id: PackageId) -> Result<Package> {
71+
let source = self.ensure_loaded(package_id.source_id)?;
72+
source.download(package_id).await
73+
}
74+
}

murek/src/ops/resolve.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use anyhow::Result;
55
use crate::core::package::{Package, PackageId};
66
use crate::core::registry::cache::RegistryCache;
77
use crate::core::registry::Registry;
8+
use crate::core::registry::source_map::SourceMap;
89
use crate::core::resolver::Resolve;
910
use crate::core::workspace::Workspace;
1011
use crate::internal::asyncx::AwaitSync;
@@ -23,8 +24,8 @@ pub struct WorkspaceResolution {
2324
)]
2425
pub fn resolve_workspace(ws: &Workspace<'_>) -> Result<WorkspaceResolution> {
2526
async {
26-
let registry = Registry::preloaded(ws.members(), ws.config());
27-
let mut registry_cache = RegistryCache::new(registry);
27+
let source_map = SourceMap::preloaded(ws.members(), ws.config());
28+
let mut registry_cache = RegistryCache::new(source_map);
2829

2930
let members_summaries = ws
3031
.members()

murek/src/resolver/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::collections::HashMap;
33
use anyhow::{anyhow, Result};
44
use petgraph::graphmap::DiGraphMap;
55

6-
use crate::core::registry::cache::RegistryCache;
6+
use crate::core::registry::Registry;
77
use crate::core::resolver::Resolve;
88
use crate::core::{Config, PackageId, Summary};
99

@@ -18,12 +18,14 @@ use crate::core::{Config, PackageId, Summary};
1818
/// * `registry` - this is the source from which all package summaries are loaded.
1919
/// It is expected that this is extensively configured ahead of time and is idempotent with
2020
/// our requests to it (aka returns the same results for the same query every time).
21+
/// It is also advised to implement internal caching, as the resolver may frequently ask
22+
/// repetitive queries.
2123
///
2224
/// * `config` - [`Config`] object.
2325
#[tracing::instrument(level = "trace", skip_all)]
2426
pub async fn resolve(
2527
summaries: &[Summary],
26-
registry: &mut RegistryCache<'_>,
28+
registry: &mut dyn Registry,
2729
_config: &Config,
2830
) -> Result<Resolve> {
2931
let mut graph = DiGraphMap::new();

0 commit comments

Comments
 (0)