wasm_pkg_client/caching/
mod.rs1use std::future::Future;
2use std::sync::Arc;
3
4use wasm_pkg_common::{
5 digest::ContentDigest,
6 package::{PackageRef, Version},
7 Error,
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
46pub struct CachingClient<T> {
49 client: Option<Client>,
50 cache: Arc<T>,
51}
52
53impl<T: Cache> Clone for CachingClient<T> {
54 fn clone(&self) -> Self {
55 Self {
56 client: self.client.clone(),
57 cache: self.cache.clone(),
58 }
59 }
60}
61
62impl<T: Cache> CachingClient<T> {
63 pub fn new(client: Option<Client>, cache: T) -> Self {
67 Self {
68 client,
69 cache: Arc::new(cache),
70 }
71 }
72
73 pub fn is_readonly(&self) -> bool {
75 self.client.is_none()
76 }
77
78 pub async fn list_all_versions(&self, package: &PackageRef) -> Result<Vec<VersionInfo>, Error> {
81 let client = self.client()?;
82 client.list_all_versions(package).await
83 }
84
85 pub async fn get_release(
87 &self,
88 package: &PackageRef,
89 version: &Version,
90 ) -> Result<Release, Error> {
91 if let Some(data) = self.cache.get_release(package, version).await? {
92 return Ok(data);
93 }
94
95 let client = self.client()?;
96 let release = client.get_release(package, version).await?;
97 self.cache.put_release(package, &release).await?;
98 Ok(release)
99 }
100
101 pub async fn get_content(
106 &self,
107 package: &PackageRef,
108 release: &Release,
109 ) -> Result<ContentStream, Error> {
110 if let Some(data) = self.cache.get_data(&release.content_digest).await? {
111 return Ok(data);
112 }
113
114 let client = self.client()?;
115 let stream = client.stream_content(package, release).await?;
116 self.cache
117 .put_data(release.content_digest.clone(), stream)
118 .await?;
119
120 self.cache
121 .get_data(&release.content_digest)
122 .await?
123 .ok_or_else(|| {
124 Error::CacheError(anyhow::anyhow!(
125 "Cached data was deleted after putting the data in cache"
126 ))
127 })
128 }
129
130 pub fn client(&self) -> Result<&Client, Error> {
135 self.client
136 .as_ref()
137 .ok_or_else(|| Error::CacheError(anyhow::anyhow!("Client is in read only mode")))
138 }
139
140 pub fn into_client(self) -> Result<Client, Error> {
143 self.client
144 .ok_or_else(|| Error::CacheError(anyhow::anyhow!("Client is in read only mode")))
145 }
146}