1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use crate::types::preprocess_callback::PreprocessError;
use crate::types::preprocess_callback::{PreprocessCallback, UploadMetadata};
use anyhow::Result;
use async_trait::async_trait;
use aws_sdk_s3::operation::get_object::GetObjectOutput;
// Uncomment the following line if you need to use `HashMap` for user-defined metadata.
// use std::collections::HashMap;
// This struct represents a user-defined preprocessed callback.
// It can be used to implement custom preprocessing logic before uploading objects to S3.
pub struct UserDefinedPreprocessCallback {
pub enable: bool,
}
impl UserDefinedPreprocessCallback {
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
// Todo: If you need to enable the callback, set `enable` to `true`
// Lua scripting preprocess callback is disabled if UserDefinedPreprocessCallback is enabled.
Self { enable: false }
}
pub fn is_enabled(&self) -> bool {
self.enable
}
}
#[async_trait]
#[cfg_attr(coverage_nightly, coverage(off))]
impl PreprocessCallback for UserDefinedPreprocessCallback {
// If you want to implement a custom preprocess callback, you can do so by modifying this function.
// The callbacks are called serially, and the callback function MUST return immediately.
// If a callback function takes a long time to execute, it may block a whole pipeline.
#[cfg_attr(coverage_nightly, coverage(off))]
async fn preprocess_before_upload(
&mut self,
_key: &str, // The key of the object being uploaded
_source_object: &GetObjectOutput, // The source object being uploaded(read only)
_metadata: &mut UploadMetadata, // The metadata for the upload, which can be modified
) -> Result<()> {
// Todo: Implement your custom preprocessing logic here.
// If we want to cancel the upload, return an error with PreprocessError::Cancelled
Err(anyhow::Error::from(PreprocessError::Cancelled))
// The following code is an example of how to modify the user-defined metadata before uploading based on the source object.
/*
let content_length = _source_object.content_length.unwrap().to_string();
if let Some(user_defined_metadata) = _metadata.metadata.as_mut() {
user_defined_metadata.insert("mycontent-length".to_string(), content_length);
} else {
let mut user_defined_metadata = HashMap::new();
user_defined_metadata.insert("mycontent-length".to_string(), content_length);
_metadata.metadata = Some(user_defined_metadata);
}
*/
// Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::types::preprocess_callback::is_callback_cancelled;
#[tokio::test]
async fn preprocess_before_upload_returns_cancelled() {
let mut callback = UserDefinedPreprocessCallback::new();
assert!(!callback.is_enabled());
let source_object = GetObjectOutput::builder().build();
let mut metadata = UploadMetadata::default();
let result = callback
.preprocess_before_upload("key", &source_object, &mut metadata)
.await;
// The default implementation cancels the upload.
assert!(is_callback_cancelled(&result.unwrap_err()));
}
}