Skip to content

Commit b22a619

Browse files
committed
This is unparsimonious because special crate for one operation but THE OPERATION WORKS and that suffices for now
Signed-off-by: itowlson <[email protected]>
1 parent 220aefe commit b22a619

File tree

3 files changed

+113
-16
lines changed

3 files changed

+113
-16
lines changed

Cargo.lock

Lines changed: 78 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/blobstore-aws-s3/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ aws-config = "1.1.7"
1515
aws-credential-types = "1.1.7"
1616
aws-sdk-s3 = "1.68"
1717
aws-smithy-async = "1.2.3"
18+
bytes = { workspace = true }
1819
futures = { workspace = true }
1920
http-body = "1.0"
2021
http-body-util = "0.1"
22+
object_store = { version = "0.11", features = ["aws"] }
2123
serde = { workspace = true }
2224
spin-core = { path = "../core" }
2325
spin-factor-blobstore = { path = "../factor-blobstore" }

crates/blobstore-aws-s3/src/store.rs

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use spin_core::async_trait;
1111
use spin_factor_blobstore::{Error, Container, ContainerManager};
1212

1313
pub struct BlobStoreS3 {
14+
builder: object_store::aws::AmazonS3Builder,
1415
client: async_once_cell::Lazy<
1516
aws_sdk_s3::Client,
1617
std::pin::Pin<Box<dyn std::future::Future<Output = aws_sdk_s3::Client> + Send>>,
@@ -69,6 +70,16 @@ impl BlobStoreS3 {
6970
region: String,
7071
auth_options: BlobStoreS3AuthOptions,
7172
) -> Result<Self> {
73+
let builder = match &auth_options {
74+
BlobStoreS3AuthOptions::RuntimeConfigValues(config) =>
75+
object_store::aws::AmazonS3Builder::new()
76+
.with_region(&region)
77+
.with_access_key_id(&config.access_key)
78+
.with_secret_access_key(&config.secret_key)
79+
.with_token(config.token.clone().unwrap_or_default()),
80+
BlobStoreS3AuthOptions::Environmental => object_store::aws::AmazonS3Builder::from_env(),
81+
};
82+
7283
let region_clone = region.clone();
7384
let client_fut = Box::pin(async move {
7485
let sdk_config = match auth_options {
@@ -84,15 +95,18 @@ impl BlobStoreS3 {
8495
aws_sdk_s3::Client::new(&sdk_config)
8596
});
8697

87-
Ok(Self { client: async_once_cell::Lazy::from_future(client_fut) })
98+
Ok(Self { builder, client: async_once_cell::Lazy::from_future(client_fut) })
8899
}
89100
}
90101

91102
#[async_trait]
92103
impl ContainerManager for BlobStoreS3 {
93104
async fn get(&self, name: &str) -> Result<Arc<dyn Container>, Error> {
105+
let store = self.builder.clone().with_bucket_name(name).build().map_err(|e| e.to_string())?;
106+
94107
Ok(Arc::new(S3Container {
95108
name: name.to_owned(),
109+
store,
96110
client: self.client.get_unpin().await.clone(),
97111
}))
98112
}
@@ -108,6 +122,7 @@ impl ContainerManager for BlobStoreS3 {
108122

109123
struct S3Container {
110124
name: String,
125+
store: object_store::aws::AmazonS3,
111126
client: aws_sdk_s3::Client,
112127
}
113128

@@ -183,14 +198,25 @@ impl Container for S3Container {
183198
Ok(Box::new(S3IncomingData::new(resp)))
184199
}
185200

186-
async fn connect_stm(&self, name: &str, stm: tokio::io::ReadHalf<tokio::io::SimplexStream>, finished_tx: tokio::sync::mpsc::Sender<()>) -> anyhow::Result<()> {
187-
let client = self.client.clone();
188-
let bucket = self.name.clone();
189-
let name = name.to_owned();
190-
let byte_stm = to_byte_stream(stm);
201+
async fn connect_stm(&self, name: &str, mut stm: tokio::io::ReadHalf<tokio::io::SimplexStream>, finished_tx: tokio::sync::mpsc::Sender<()>) -> anyhow::Result<()> {
202+
let store = self.store.clone();
203+
let path = object_store::path::Path::from(name);
191204

192205
tokio::spawn(async move {
193-
client.put_object().bucket(&bucket).key(name).body(byte_stm).send().await.unwrap();
206+
use object_store::ObjectStore;
207+
let mupload = store.put_multipart(&path).await.unwrap();
208+
let mut writer = object_store::WriteMultipart::new(mupload);
209+
loop {
210+
use tokio::io::AsyncReadExt;
211+
let mut buf = vec![0; 5 * 1024 * 1024];
212+
let read_amount = stm.read(&mut buf).await.unwrap();
213+
if read_amount == 0 {
214+
break;
215+
}
216+
buf.truncate(read_amount);
217+
writer.put(buf.into());
218+
}
219+
writer.finish().await.unwrap();
194220
finished_tx.send(()).await.expect("should sent finish tx");
195221
});
196222

@@ -203,14 +229,6 @@ impl Container for S3Container {
203229
}
204230
}
205231

206-
fn to_byte_stream(read: tokio::io::ReadHalf<tokio::io::SimplexStream>) -> aws_sdk_s3::primitives::ByteStream {
207-
use futures::StreamExt;
208-
209-
let stm = tokio_util::io::ReaderStream::new(read).map(|item| item.map(|by| http_body::Frame::data(by)));
210-
let stm_body = http_body_util::StreamBody::new(stm);
211-
aws_sdk_s3::primitives::ByteStream::from_body_1_x(stm_body)
212-
}
213-
214232
struct S3IncomingData {
215233
get_obj_resp: Option<get_object::GetObjectOutput>,
216234
}

0 commit comments

Comments
 (0)