wasm_pkg_client/caching/
mod.rs1use std::future::Future;
2use std::sync::Arc;
3
4use wasm_pkg_common::{
5 Error,
6 digest::ContentDigest,
7 package::{PackageRef, Version},
8};
9
10use crate::{Client, ContentStream, Release, VersionInfo};
11
12mod file;
13
14pub use file::FileCache;
15
16pub trait Cache {
18 fn put_data(
20 &self,
21 digest: ContentDigest,
22 data: ContentStream,
23 ) -> impl Future<Output = Result<(), Error>> + Send;
24
25 fn get_data(
27 &self,
28 digest: &ContentDigest,
29 ) -> impl Future<Output = Result<Option<ContentStream>, Error>> + Send;
30
31 fn put_release(
33 &self,
34 package: &PackageRef,
35 release: &Release,
36 ) -> impl Future<Output = Result<(), Error>> + Send;
37
38 fn get_release(
40 &self,
41 package: &PackageRef,
42 version: &Version,
43 ) -> impl Future<Output = Result<Option<Release>, Error>> + Send;
44}
45
46#[derive(Clone)]
49pub struct CachingClient<T> {
50 client: Option<Client>,
51 cache: Arc<T>,
52}
53
54impl<T: Cache> CachingClient<T> {
55 pub fn new(client: Option<Client>, cache: T) -> Self {
59 Self {
60 client,
61 cache: Arc::new(cache),
62 }
63 }
64
65 pub fn is_readonly(&self) -> bool {
67 self.client.is_none()
68 }
69
70 pub async fn list_all_versions(&self, package: &PackageRef) -> Result<Vec<VersionInfo>, Error> {
73 let client = self.client()?;
74 client.list_all_versions(package).await
75 }
76
77 pub async fn get_release(
79 &self,
80 package: &PackageRef,
81 version: &Version,
82 ) -> Result<Release, Error> {
83 if let Some(data) = self.cache.get_release(package, version).await? {
84 return Ok(data);
85 }
86
87 let client = self.client()?;
88 let release = client.get_release(package, version).await?;
89 self.cache.put_release(package, &release).await?;
90 Ok(release)
91 }
92
93 pub async fn get_content(
98 &self,
99 package: &PackageRef,
100 release: &Release,
101 ) -> Result<ContentStream, Error> {
102 if let Some(data) = self.cache.get_data(&release.content_digest).await? {
103 return Ok(data);
104 }
105
106 let client = self.client()?;
107 let stream = client.stream_content(package, release).await?;
108 self.cache
109 .put_data(release.content_digest.clone(), stream)
110 .await?;
111
112 self.cache
113 .get_data(&release.content_digest)
114 .await?
115 .ok_or_else(|| {
116 Error::CacheError(anyhow::anyhow!(
117 "Cached data was deleted after putting the data in cache"
118 ))
119 })
120 }
121
122 pub fn client(&self) -> Result<&Client, Error> {
127 self.client
128 .as_ref()
129 .ok_or_else(|| Error::CacheError(anyhow::anyhow!("Client is in read only mode")))
130 }
131
132 pub fn into_client(self) -> Result<Client, Error> {
135 self.client
136 .ok_or_else(|| Error::CacheError(anyhow::anyhow!("Client is in read only mode")))
137 }
138}