/build/source/nativelink-store/src/r2_store.rs
Line | Count | Source |
1 | | // Copyright 2026 The NativeLink Authors. All rights reserved. |
2 | | // |
3 | | // Licensed under the Functional Source License, Version 1.1, Apache 2.0 Future License (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // See LICENSE file for details |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | use core::time::Duration; |
16 | | use std::sync::Arc; |
17 | | |
18 | | use aws_config::default_provider::credentials::DefaultCredentialsChain; |
19 | | use aws_config::provider_config::ProviderConfig; |
20 | | use aws_config::{AppName, BehaviorVersion}; |
21 | | use aws_sdk_s3::Client; |
22 | | use aws_sdk_s3::config::{Credentials, Region}; |
23 | | use nativelink_config::stores::{ExperimentalAwsSpec, ExperimentalR2Spec}; |
24 | | use nativelink_error::Error; |
25 | | use nativelink_util::instant_wrapper::InstantWrapper; |
26 | | |
27 | | use crate::common_s3_utils::TlsClient; |
28 | | use crate::s3_store::S3Store; |
29 | | |
30 | | /// R2-shaped config adapter over [`S3Store`]. Builds an S3 SDK client |
31 | | /// pointed at R2 (custom endpoint, region `auto`, optional explicit |
32 | | /// credentials) and hands it to `S3Store::new_with_client_and_jitter`. |
33 | | #[derive(Debug, Clone, Copy)] |
34 | | pub struct R2Store; |
35 | | |
36 | | impl R2Store { |
37 | 0 | pub async fn new<I, NowFn>( |
38 | 0 | spec: &ExperimentalR2Spec, |
39 | 0 | now_fn: NowFn, |
40 | 0 | ) -> Result<Arc<S3Store<NowFn>>, Error> |
41 | 0 | where |
42 | 0 | I: InstantWrapper, |
43 | 0 | NowFn: Fn() -> I + Send + Sync + Unpin + 'static, |
44 | 0 | { |
45 | 0 | let aws_spec = Self::build_aws_spec(spec); |
46 | 0 | let jitter_fn = spec.common.retry.make_jitter_fn(); |
47 | | |
48 | 0 | let http_client = TlsClient::new(&spec.common.clone()); |
49 | 0 | let endpoint = Self::derive_endpoint(spec); |
50 | | |
51 | 0 | let mut config_loader = aws_config::defaults(BehaviorVersion::latest()) |
52 | 0 | .app_name(AppName::new("nativelink").expect("valid app name")) |
53 | 0 | .timeout_config( |
54 | 0 | aws_config::timeout::TimeoutConfig::builder() |
55 | 0 | .connect_timeout(Duration::from_secs(15)) |
56 | 0 | .build(), |
57 | | ) |
58 | 0 | .region(Region::new("auto")) |
59 | 0 | .endpoint_url(&endpoint) |
60 | 0 | .http_client(http_client.clone()); |
61 | | |
62 | 0 | config_loader = |
63 | 0 | match (&spec.access_key_id, &spec.secret_access_key) { |
64 | 0 | (Some(key_id), Some(secret)) => config_loader.credentials_provider( |
65 | 0 | Credentials::new(key_id, secret, None, None, "r2-explicit"), |
66 | | ), |
67 | | _ => { |
68 | 0 | let default_chain = DefaultCredentialsChain::builder() |
69 | 0 | .configure( |
70 | 0 | ProviderConfig::without_region() |
71 | 0 | .with_region(Some(Region::new("auto"))) |
72 | 0 | .with_http_client(http_client), |
73 | 0 | ) |
74 | 0 | .build() |
75 | 0 | .await; |
76 | 0 | config_loader.credentials_provider(default_chain) |
77 | | } |
78 | | }; |
79 | | |
80 | 0 | let config = config_loader.load().await; |
81 | 0 | let s3_client = Client::new(&config); |
82 | | |
83 | 0 | S3Store::new_with_client_and_jitter(&aws_spec, s3_client, jitter_fn, now_fn) |
84 | 0 | } |
85 | | |
86 | 1 | pub fn derive_endpoint(spec: &ExperimentalR2Spec) -> String { |
87 | 1 | format!("https://{}.r2.cloudflarestorage.com", spec.account_id) |
88 | 1 | } |
89 | | |
90 | 1 | pub fn build_aws_spec(spec: &ExperimentalR2Spec) -> ExperimentalAwsSpec { |
91 | 1 | ExperimentalAwsSpec { |
92 | 1 | region: "auto".to_string(), |
93 | 1 | bucket: spec.bucket.clone(), |
94 | 1 | common: spec.common.clone(), |
95 | 1 | } |
96 | 1 | } |
97 | | } |