Skip to content

Commit

Permalink
spi-obj: fix obs copy failed (#831)
Browse files Browse the repository at this point in the history
* os: fix obs copy failed

* iam:fix bug (icon  in set cate modify empty failed)

* spi-obs: update

* spi-obj: complete comments

* code format

---------

Co-authored-by: ZzIsGod1019 <1498852723@11.com>
  • Loading branch information
ZzIsGod1019 and ZzIsGod1019 authored Aug 31, 2024
1 parent 01237ee commit 6fda4c9
Show file tree
Hide file tree
Showing 11 changed files with 220 additions and 28 deletions.
2 changes: 1 addition & 1 deletion backend/basic/src/spi/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ macro_rules! spi_dispatch_service {
$(
$(#[$attr])*
pub async fn $service($($arg: $type,)* funs: &tardis::TardisFunsInst, ctx: &tardis::basic::dto::TardisContext) -> $ret {
let arc_inst = funs.init(ctx, $mgr, $init).await?;
let arc_inst = funs.init(None, ctx, $mgr, $init).await?;
let inst = arc_inst.as_ref();
$crate::spi_dispatch_service!(@dispatch $service, funs, ctx, inst, @dispatch: $dispatch, @args: {$($arg),*})
}
Expand Down
13 changes: 9 additions & 4 deletions backend/basic/src/spi/spi_funs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ fn get_spi_bs_caches() -> &'static RwLock<HashMap<String, Arc<SpiBsInst>>> {

#[async_trait]
pub trait SpiBsInstExtractor {
async fn init<'a, F, T>(&self, ctx: &'a TardisContext, mgr: bool, init_funs: F) -> TardisResult<Arc<SpiBsInst>>
async fn init<'a, F, T>(&self, custom_cache_key: Option<String>, ctx: &'a TardisContext, mgr: bool, init_funs: F) -> TardisResult<Arc<SpiBsInst>>
where
F: Fn(SpiBsCertResp, &'a TardisContext, bool) -> T + Send + Sync,
T: Future<Output = TardisResult<SpiBsInst>> + Send;
Expand All @@ -72,19 +72,24 @@ impl SpiBsInstExtractor for TardisFunsInst {
///
/// # Arguments
///
/// * `custom_cache_key` - Customize the cache key, if it is none, the default cache key will be used.
/// * `ctx` - Request Context
/// * `mgr` - Whether it is a managed request
/// * `init_fun` - The initialization function called when the backend service instance is not initialized
///
/// # Return
///
/// the backend service instance kind
async fn init<'a, F, T>(&self, ctx: &'a TardisContext, mgr: bool, init_fun: F) -> TardisResult<Arc<SpiBsInst>>
async fn init<'a, F, T>(&self, custom_cache_key: Option<String>, ctx: &'a TardisContext, mgr: bool, init_fun: F) -> TardisResult<Arc<SpiBsInst>>
where
F: Fn(SpiBsCertResp, &'a TardisContext, bool) -> T + Send + Sync,
T: Future<Output = TardisResult<SpiBsInst>> + Send,
{
let cache_key = format!("{}-{}", self.module_code(), ctx.ak);
let cache_key = if let Some(custom_cache_key) = custom_cache_key {
format!("{}-{}-{}", self.module_code(), ctx.ak, custom_cache_key)
} else {
format!("{}-{}", self.module_code(), ctx.ak)
};
{
let read = get_spi_bs_caches().read().await;
if let Some(inst) = read.get(&cache_key).cloned() {
Expand Down Expand Up @@ -136,7 +141,7 @@ impl SpiBsInstExtractor for TardisFunsInst {
F: Fn(SpiBsCertResp, &'a TardisContext, bool) -> T + Send + Sync,
T: Future<Output = TardisResult<SpiBsInst>> + Send,
{
self.init(ctx, mgr, init_fun).await?;
self.init(None, ctx, mgr, init_fun).await?;
self.bs(ctx).await
}

Expand Down
2 changes: 1 addition & 1 deletion backend/spi/spi-graph/src/serv/graph_basic_serv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub async fn delete_rels(
"400-spi-graph-key-require",
));
}
let inst = funs.init(ctx, true, graph_initializer::init_fun).await?;
let inst = funs.init(None, ctx, true, graph_initializer::init_fun).await?;
match inst.kind_code() {
#[cfg(feature = "spi-pg")]
spi_constants::SPI_PG_KIND_CODE => pg::graph_pg_basic_serv::delete_rels(tag, from_key, to_key, from_version, to_version, funs, ctx, &inst).await,
Expand Down
98 changes: 94 additions & 4 deletions backend/spi/spi-object/src/api/ci/object_ci_obj_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,42 @@ use crate::serv::object_obj_serv;
pub struct ObjectCiObjApi;

/// Interface Console Object API
///
/// When the built-in service is initialized, 4 buckets are created by default: pub,pri,spe,tamp.
/// pub bucket, we recommend setting it to public read and private write permissions, when is_private passes false, the bucket will be operated.
/// pri bucket, it is recommended to set it to private read-private write, use temporary address to manipulate the object to ensure data security. When is_private passes true, operate the bucket.
/// spe bucket, recommended for large files. When is_special passes true, manipulate this bucket.
/// The tamp bucket, recommended for temporary files, when obj_exp is passed true.
/// 接口控制台对象服务API
/// 内置服务初始化时,默认创建4个桶:pub,pri,spe,tamp
/// pub桶,建议设置为公共读私有写权限,当is_private传false时,操作该桶。
/// pri桶,建议设置为私有读私有写,使用临时地址操作对象,保证数据安全。当is_private传true时,操作该桶。
/// spe桶,建议操作大文件时使用该桶。当is_special传true时,操作该桶。
/// tamp桶,建议操作临时文件时使用该桶,当obj_exp传入时,操作该桶。
#[poem_openapi::OpenApi(prefix_path = "/ci/obj", tag = "bios_basic::ApiTag::Interface")]
impl ObjectCiObjApi {
/// Fetch URL for temporary authorization of file upload
///
/// 获取用于临时授权上传文件的 URL
#[oai(path = "/presign/put", method = "get")]
async fn presign_put_obj_url(
&self,
// 对象的路径
// path of object
object_path: Query<String>,
// 临时上传url的生效时长
// The length of time a temporary upload url is in effect
exp_secs: Query<u32>,
// 是否私有
// private or not
private: Query<Option<bool>>,
// 是否特殊
//Special or not
special: Query<Option<bool>>,
// 是否临时,数字表示文件生效时长。
// 使用obs时,传入数值不生效,仅表示使用tamp桶。
// Whether or not it is temporary, the number indicates the length of time the file will be in effect.
// When using obs, passing in a value does not take effect, it only indicates the use of the tamp bucket.
obj_exp: Query<Option<u32>>,
ctx: TardisContextExtractor,
) -> TardisApiResult<String> {
Expand All @@ -47,13 +73,27 @@ impl ObjectCiObjApi {
}

/// Fetch URL for temporary authorization of file delete
///
/// 获取文件删除临时授权的 URL
#[oai(path = "/presign/delete", method = "get")]
async fn presign_delete_obj_url(
&self,
// 对象的路径
// path of object
object_path: Query<String>,
// 临时上传url的生效时长
// The length of time a temporary upload url is in effect
exp_secs: Query<u32>,
// 是否私有
// private or not
private: Query<Option<bool>>,
// 是否特殊
//Special or not
special: Query<Option<bool>>,
// 是否临时,数字表示文件生效时长。
// 使用obs时,传入数值不生效,仅表示使用tamp桶。
// Whether or not it is temporary, the number indicates the length of time the file will be in effect.
// When using obs, passing in a value does not take effect, it only indicates the use of the tamp bucket.
obj_exp: Query<Option<u32>>,
ctx: TardisContextExtractor,
) -> TardisApiResult<String> {
Expand All @@ -75,13 +115,27 @@ impl ObjectCiObjApi {
}

/// Fetch URL for temporary authorization of file
///
/// 获取文件临时授权的 URL
#[oai(path = "/presign/view", method = "get")]
async fn presign_view_obj_url(
&self,
// 对象的路径
// path of object
object_path: Query<String>,
// 临时上传url的生效时长
// The length of time a temporary upload url is in effect
exp_secs: Query<u32>,
// 是否私有
// private or not
private: Query<Option<bool>>,
// 是否特殊
//Special or not
special: Query<Option<bool>>,
// 是否临时,数字表示文件生效时长。
// 使用obs时,传入数值不生效,仅表示使用tamp桶。
// Whether or not it is temporary, the number indicates the length of time the file will be in effect.
// When using obs, passing in a value does not take effect, it only indicates the use of the tamp bucket.
obj_exp: Query<Option<u32>>,
ctx: TardisContextExtractor,
) -> TardisApiResult<String> {
Expand All @@ -103,30 +157,38 @@ impl ObjectCiObjApi {
}

/// Batch fetch URL for temporary authorization of file
///
/// 批量获取文件临时授权的 URL
#[oai(path = "/presign/batch_view", method = "post")]
async fn batch_presign_view_obj_url(&self, req: Json<ObjectPresignBatchViewReq>, ctx: TardisContextExtractor) -> TardisApiResult<HashMap<String, String>> {
let funs = crate::get_tardis_inst();
let url = object_obj_serv::batch_get_presign_obj_url(req.0.object_path, req.0.expire_sec, req.0.private, req.0.special, req.0.obj_exp, &funs, &ctx.0).await?;
TardisResp::ok(url)
}

/// Initiate a Multipart Upload Task
/// Multipart Upload:Initiate a Multipart Upload Task
///
/// 分片上传: 启动分片上传任务
#[oai(path = "/multi_upload/initiate_multipart_upload", method = "post")]
async fn initiate_multipart_upload(&self, req: Json<ObjectInitiateMultipartUploadReq>, ctx: TardisContextExtractor) -> TardisApiResult<String> {
let funs = crate::get_tardis_inst();
let upload_id = object_obj_serv::initiate_multipart_upload(req.0, &funs, &ctx.0).await?;
TardisResp::ok(upload_id)
}

/// Create pre-signed URLs for each part
/// Multipart Upload:Create pre-signed URLs for each part
///
/// 分片上传: 为每个部分创建预签名 URL
#[oai(path = "/multi_upload/batch_build_create_presign_url", method = "post")]
async fn batch_build_create_presign_url(&self, req: Json<ObjectBatchBuildCreatePresignUrlReq>, ctx: TardisContextExtractor) -> TardisApiResult<Vec<String>> {
let funs = crate::get_tardis_inst();
let presign_urls = object_obj_serv::batch_build_create_presign_url(req.0, &funs, &ctx.0).await?;
TardisResp::ok(presign_urls)
}

/// Complete Multipart Upload Task
/// Multipart Upload:Complete Multipart Upload Task
///
/// 分片上传: 完成分片上传任务
#[oai(path = "/multi_upload/complete_multipart_upload", method = "post")]
async fn complete_multipart_upload(&self, req: Json<ObjectCompleteMultipartUploadReq>, ctx: TardisContextExtractor) -> TardisApiResult<Void> {
let funs = crate::get_tardis_inst();
Expand All @@ -135,6 +197,8 @@ impl ObjectCiObjApi {
}

/// Create A Copy Of An Object That Is Already Stored
///
/// 创建已存储对象的副本
#[oai(path = "/object/copy", method = "post")]
async fn object_copy(&self, req: Json<ObjectCopyReq>, ctx: TardisContextExtractor) -> TardisApiResult<Void> {
let funs = crate::get_tardis_inst();
Expand All @@ -143,12 +207,24 @@ impl ObjectCiObjApi {
}

/// Deleting A Single Object
///
/// 删除单个对象
#[oai(path = "/object", method = "delete")]
async fn object_delete(
&self,
// 对象的路径
// path of object
object_path: Query<String>,
// 是否私有
// private or not
private: Query<Option<bool>>,
// 是否特殊
//Special or not
special: Query<Option<bool>>,
// 是否临时,数字表示文件生效时长。
// 使用obs时,传入数值不生效,仅表示使用tamp桶。
// Whether or not it is temporary, the number indicates the length of time the file will be in effect.
// When using obs, passing in a value does not take effect, it only indicates the use of the tamp bucket.
obj_exp: Query<Option<u32>>,
ctx: TardisContextExtractor,
) -> TardisApiResult<Void> {
Expand All @@ -157,20 +233,34 @@ impl ObjectCiObjApi {
TardisResp::ok(Void)
}

/// Deleting Objects
/// Batch deleting Objects
///
/// 批量删除对象
#[oai(path = "/object/batch_delete", method = "delete")]
async fn batch_object_delete(&self, req: Json<ObjectBatchDeleteReq>, ctx: TardisContextExtractor) -> TardisApiResult<Vec<String>> {
let funs = crate::get_tardis_inst();
TardisResp::ok(object_obj_serv::batch_object_delete(req.0.object_path, req.0.private, req.0.special, req.0.obj_exp, &funs, &ctx.0).await?)
}

/// Check object is exist
///
/// 检查对象是否存在
#[oai(path = "/object/exist", method = "get")]
async fn object_exist(
&self,
// 对象的路径
// path of object
object_path: Query<String>,
// 是否私有
// private or not
private: Query<Option<bool>>,
// 是否特殊
//Special or not
special: Query<Option<bool>>,
// 是否临时,数字表示文件生效时长。
// 使用obs时,传入数值不生效,仅表示使用tamp桶。
// Whether or not it is temporary, the number indicates the length of time the file will be in effect.
// When using obs, passing in a value does not take effect, it only indicates the use of the tamp bucket.
obj_exp: Query<Option<u32>>,
ctx: TardisContextExtractor,
) -> TardisApiResult<bool> {
Expand Down
2 changes: 2 additions & 0 deletions backend/spi/spi-object/src/object_constants.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pub const DOMAIN_CODE: &str = "spi-object";
pub const SPI_S3_KIND_CODE: &str = "spi-bs-s3";
pub const SPI_OBS_KIND_CODE: &str = "spi-bs-obs";

pub const USE_REGION_ENDPOINT: &str = "use_region_endpoint";
29 changes: 18 additions & 11 deletions backend/spi/spi-object/src/serv/object_obj_serv.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use std::collections::HashMap;
use std::sync::Arc;

use bios_basic::spi::spi_funs::SpiBsInstExtractor;
use tardis::basic::dto::TardisContext;
use tardis::basic::result::TardisResult;
use tardis::tokio::sync::RwLock;
use tardis::TardisFunsInst;

use crate::dto::object_dto::{ObjectBatchBuildCreatePresignUrlReq, ObjectCompleteMultipartUploadReq, ObjectInitiateMultipartUploadReq, ObjectObjPresignKind};
use crate::object_constants::USE_REGION_ENDPOINT;
use crate::{object_constants, object_initializer};

use super::s3::S3 as _;
Expand All @@ -23,7 +26,7 @@ pub async fn presign_obj_url(
funs: &TardisFunsInst,
ctx: &TardisContext,
) -> TardisResult<String> {
let inst = funs.init(ctx, true, object_initializer::init_fun).await?;
let inst = funs.init(None, ctx, true, object_initializer::init_fun).await?;
match inst.kind_code() {
#[cfg(feature = "spi-s3")]
object_constants::SPI_S3_KIND_CODE => {
Expand All @@ -46,7 +49,7 @@ pub async fn batch_get_presign_obj_url(
funs: &TardisFunsInst,
ctx: &TardisContext,
) -> TardisResult<HashMap<String, String>> {
let inst = funs.init(ctx, true, object_initializer::init_fun).await?;
let inst = funs.init(None, ctx, true, object_initializer::init_fun).await?;
match inst.kind_code() {
#[cfg(feature = "spi-s3")]
object_constants::SPI_S3_KIND_CODE => {
Expand All @@ -61,7 +64,7 @@ pub async fn batch_get_presign_obj_url(
}

pub async fn initiate_multipart_upload(req: ObjectInitiateMultipartUploadReq, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<String> {
let inst = funs.init(ctx, true, object_initializer::init_fun).await?;
let inst = funs.init(None, ctx, true, object_initializer::init_fun).await?;
match inst.kind_code() {
#[cfg(feature = "spi-s3")]
object_constants::SPI_S3_KIND_CODE => {
Expand All @@ -76,7 +79,7 @@ pub async fn initiate_multipart_upload(req: ObjectInitiateMultipartUploadReq, fu
}

pub async fn batch_build_create_presign_url(req: ObjectBatchBuildCreatePresignUrlReq, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<Vec<String>> {
let inst = funs.init(ctx, true, object_initializer::init_fun).await?;
let inst = funs.init(None, ctx, true, object_initializer::init_fun).await?;
match inst.kind_code() {
#[cfg(feature = "spi-s3")]
object_constants::SPI_S3_KIND_CODE => {
Expand Down Expand Up @@ -113,7 +116,7 @@ pub async fn batch_build_create_presign_url(req: ObjectBatchBuildCreatePresignUr
}

pub async fn complete_multipart_upload(req: ObjectCompleteMultipartUploadReq, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> {
let inst = funs.init(ctx, true, object_initializer::init_fun).await?;
let inst = funs.init(None, ctx, true, object_initializer::init_fun).await?;
match inst.kind_code() {
#[cfg(feature = "spi-s3")]
object_constants::SPI_S3_KIND_CODE => {
Expand All @@ -135,7 +138,7 @@ pub async fn object_delete(
funs: &TardisFunsInst,
ctx: &TardisContext,
) -> TardisResult<()> {
let inst = funs.init(ctx, true, object_initializer::init_fun).await?;
let inst = funs.init(None, ctx, true, object_initializer::init_fun).await?;
match inst.kind_code() {
#[cfg(feature = "spi-s3")]
object_constants::SPI_S3_KIND_CODE => s3::object_s3_obj_serv::S3Service::object_delete(&object_path, private, special, obj_exp, funs, ctx, &inst).await,
Expand All @@ -153,7 +156,7 @@ pub async fn batch_object_delete(
funs: &TardisFunsInst,
ctx: &TardisContext,
) -> TardisResult<Vec<String>> {
let inst = funs.init(ctx, true, object_initializer::init_fun).await?;
let inst = funs.init(None, ctx, true, object_initializer::init_fun).await?;
match inst.kind_code() {
#[cfg(feature = "spi-s3")]
object_constants::SPI_S3_KIND_CODE => s3::object_s3_obj_serv::S3Service::batch_object_delete(object_paths, private, special, obj_exp, funs, ctx, &inst).await,
Expand All @@ -164,12 +167,16 @@ pub async fn batch_object_delete(
}

pub async fn object_copy(from: String, to: String, private: Option<bool>, special: Option<bool>, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> {
let inst = funs.init(ctx, true, object_initializer::init_fun).await?;
let mock_ctx = TardisContext {
ext: Arc::new(RwLock::new(HashMap::from([(USE_REGION_ENDPOINT.to_string(), "true".to_string())]))),
..ctx.clone()
};
let inst = funs.init(Some(USE_REGION_ENDPOINT.to_string()), &mock_ctx, true, object_initializer::init_fun).await?;
match inst.kind_code() {
#[cfg(feature = "spi-s3")]
object_constants::SPI_S3_KIND_CODE => s3::object_s3_obj_serv::S3Service::object_copy(&from, &to, private, special, funs, ctx, &inst).await,
object_constants::SPI_S3_KIND_CODE => s3::object_s3_obj_serv::S3Service::object_copy(&from, &to, private, special, funs, &mock_ctx, &inst).await,
#[cfg(feature = "spi-s3")]
object_constants::SPI_OBS_KIND_CODE => obs::object_obs_obj_serv::OBSService::object_copy(&from, &to, private, special, funs, ctx, &inst).await,
object_constants::SPI_OBS_KIND_CODE => obs::object_obs_obj_serv::OBSService::object_copy(&from, &to, private, special, funs, &mock_ctx, &inst).await,
kind_code => Err(funs.bs_not_implemented(kind_code)),
}
}
Expand All @@ -182,7 +189,7 @@ pub async fn object_exist(
funs: &TardisFunsInst,
ctx: &TardisContext,
) -> TardisResult<bool> {
let inst = funs.init(ctx, true, object_initializer::init_fun).await?;
let inst = funs.init(None, ctx, true, object_initializer::init_fun).await?;
match inst.kind_code() {
#[cfg(feature = "spi-s3")]
object_constants::SPI_S3_KIND_CODE => s3::object_s3_obj_serv::S3Service::object_exist(&object_paths, private, special, obj_exp, funs, ctx, &inst).await,
Expand Down
Loading

0 comments on commit 6fda4c9

Please sign in to comment.