pub struct AzureStore { /* private fields */ }Expand description
Production ObjectStore backed by azure_storage_blob.
Implementations§
Source§impl AzureStore
impl AzureStore
Sourcepub async fn from_remote_url(url: &RemoteUrl) -> Result<Self, ObjectStoreError>
pub async fn from_remote_url(url: &RemoteUrl) -> Result<Self, ObjectStoreError>
Build an AzureStore from a parsed RemoteUrl.
Like the S3 backend, the RemoteUrl::Azure::prefix field is
intentionally not consumed here; callers compose it into keys
themselves.
Marked async for symmetry with S3Store::from_remote_url,
which awaits the AWS provider chain. The Azure path resolves
credentials synchronously today; the signature stays async so
future credential providers (e.g. one that fetches an OIDC
token at construction) can plug in without breaking callers.
§Errors
Returns ObjectStoreError::Other if url is not the Azure
variant or if credential resolution fails.
Trait Implementations§
Source§impl Debug for AzureStore
impl Debug for AzureStore
Source§impl ObjectStore for AzureStore
impl ObjectStore for AzureStore
Source§fn get_bytes_range<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
range: Range<u64>,
) -> Pin<Box<dyn Future<Output = Result<Bytes, ObjectStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_bytes_range<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
range: Range<u64>,
) -> Pin<Box<dyn Future<Output = Result<Bytes, ObjectStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Issue a Get Blob with a Range<usize> covering [start, end).
HTTP 416 maps to ObjectStoreError::RangeNotSatisfiable with
the original Range<u64> so the wire-line names what the
caller asked for. All other failures route through [classify].
The Azure SDK exposes BlobClientDownloadOptions::range as
Option<Range<usize>>. usize is at least 64 bits on every
supported target, so casting from u64 is lossless; the cast
is documented here so a future 32-bit port surfaces as a
compile error rather than silent truncation.
Azure silently truncates a ranged GET to EOF when the requested
range overruns the blob — start < body.len() <= end returns
start..body.len() bytes with HTTP 206 and no error. The
post-flight length check via [super::verify_range_response_length]
elevates that mismatch to ObjectStoreError::RangeNotSatisfiable
so callers (notably the packchain reader) cannot mistake a
truncated slice for the full requested range.
Source§fn put_path<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
src: &'life2 Path,
opts: PutOpts,
) -> Pin<Box<dyn Future<Output = Result<(), ObjectStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn put_path<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
src: &'life2 Path,
opts: PutOpts,
) -> Pin<Box<dyn Future<Output = Result<(), ObjectStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Stream a local file to key without buffering its full body.
Above [super::multipart::MULTIPART_PUT_THRESHOLD] this routes through explicit
stage_block + commit_block_list, paralleling the S3 backend
(issue #53). Below the threshold the single Put Blob path
preserves the one-round-trip cost for small bundles and lock
files.
On the multipart path each task opens its own
tokio::fs::File, seeks to its part offset, reads the part
into a Bytes, then calls BlockBlobClient::stage_block. With
MULTIPART_PUT_MAX_CONCURRENCY = 8 and
MULTIPART_PUT_PART_SIZE = 16 MiB, peak memory is bounded at
128 MiB regardless of file size.
On the single-PUT path we wrap tokio::fs::File in
FileStream so the body is delivered as
Body::SeekableStream. The per-try signing policy reads
request.body().len(), which SeekableStream reports faithfully
via len().
Source§fn presigned_get_url<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
ttl: Duration,
) -> Pin<Box<dyn Future<Output = Result<String, ObjectStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn presigned_get_url<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
ttl: Duration,
) -> Pin<Box<dyn Future<Output = Result<String, ObjectStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Build a service-blob SAS URL for key valid for ttl.
Used by the bundle-uri capability (issue #76) to advertise
time-limited download URLs against private containers.
Only the shared-key / connection-string credential paths can
produce a SAS — the SAS env-var path has no key to re-sign
with, and the Entra-ID TokenCredential path requires
user-delegation SAS (out of scope per the issue). Both
fall through to ObjectStoreError::Unsupported.
§Errors
ObjectStoreError::Unsupportedwhen the credential is not a shared key.ObjectStoreError::Otherwhen SAS construction fails (HMAC init / base64 decode / time overflow).
Source§fn list<'life0, 'life1, 'async_trait>(
&'life0 self,
prefix: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<ObjectMeta>, ObjectStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn list<'life0, 'life1, 'async_trait>(
&'life0 self,
prefix: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<ObjectMeta>, ObjectStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
prefix as a byte prefix.Source§fn get_to_file<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
dest: &'life2 Path,
opts: GetOpts,
) -> Pin<Box<dyn Future<Output = Result<(), ObjectStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn get_to_file<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 str,
dest: &'life2 Path,
opts: GetOpts,
) -> Pin<Box<dyn Future<Output = Result<(), ObjectStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
dest. The destination’s parent
directory must already exist. opts.progress, when set, fires
at chunk boundaries with the count of bytes just received.Source§fn get_bytes<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Bytes, ObjectStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_bytes<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Bytes, ObjectStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn put_bytes<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
body: Bytes,
opts: PutOpts,
) -> Pin<Box<dyn Future<Output = Result<(), ObjectStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn put_bytes<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
body: Bytes,
opts: PutOpts,
) -> Pin<Box<dyn Future<Output = Result<(), ObjectStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
body to key, overwriting any existing object.Source§fn put_if_absent<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
body: Bytes,
) -> Pin<Box<dyn Future<Output = Result<bool, ObjectStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn put_if_absent<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
body: Bytes,
) -> Pin<Box<dyn Future<Output = Result<bool, ObjectStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
key if and only if it does not exist. Returns Ok(true)
when the object was created, Ok(false) when the key was already
present.Source§fn head<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<ObjectMeta, ObjectStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn head<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<ObjectMeta, ObjectStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn copy<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
src: &'life1 str,
dst: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<(), ObjectStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn copy<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
src: &'life1 str,
dst: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<(), ObjectStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
src to dst. The body is preserved on every backend;
user metadata is not guaranteed to survive — callers must not
rely on metadata round-tripping through copy. Read moreSource§fn delete<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(), ObjectStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn delete<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(), ObjectStoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
key. Returns Err(ObjectStoreError::NotFound) if the key was
not present.Auto Trait Implementations§
impl !RefUnwindSafe for AzureStore
impl !UnwindSafe for AzureStore
impl Freeze for AzureStore
impl Send for AzureStore
impl Sync for AzureStore
impl Unpin for AzureStore
impl UnsafeUnpin for AzureStore
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more