REQ-3540: 备份

This commit is contained in:
yanglin 2025-03-13 14:10:04 +08:00
parent 9ba3caf8d3
commit a4cc104cb0
52 changed files with 930 additions and 314 deletions

View File

@ -24,7 +24,7 @@ public class DatabaseAccessConfig {
/**
* 协作企业可见范围. ALL_ORGS_IN_PROJECT: 项目内所有企业可见, ORGS_BY_COOPERATE_TYPES: 指定参建单位可见
*/
private CooperationAccessOption cooperationAccessOption;
private CooperationAccessOption coopAccessOption;
/**
* 指定参建单位可见. 1: 总包, 13: 设计单位, 12: 勘察单位, 3: 监理单位, 5: 专业分包, 4: 劳务分包, 9: 项目内班组

View File

@ -12,8 +12,8 @@ import lombok.Setter;
public class DirectoryAttributes {
/**
* 是否为模版文件夹
* 是否为资料库文件夹
*/
private boolean isTemplateDir;
private boolean isTemplateDatabaseDir;
}

View File

@ -1,3 +1,4 @@
package cn.axzo.nanopart.doc.api.domain;
import java.math.BigDecimal;
@ -13,14 +14,14 @@ import lombok.Setter;
@Getter
public class FileTemplateNodeInfo {
/**
* 文件模版状态. UNPUBLISH: 未上架, PUBLISHED: 已上架
*/
private FileTemplateState state;
/**
* 文件模版状态. UNPUBLISH: 未上架, PUBLISHED: 已上架
*/
private FileTemplateState state;
/**
* 费用
*/
private BigDecimal fee;
/**
* 费用
*/
private BigDecimal fee;
}
}

View File

@ -13,10 +13,19 @@ import lombok.Setter;
@Getter
public class IndexNodeAttributes {
/**
* 数据库属性
*/
private DatabaseAttributes databaseAttributes;
/**
* 目录属性
*/
private DirectoryAttributes directoryAttributes;
/**
* 文件属性
*/
private FileAttributes fileAttributes;
public static IndexNodeAttributes create() {

View File

@ -52,9 +52,9 @@ public class IndexNodeInfo {
private DatabaseScope scope;
/**
* 作用范围id. 单位数据库存ouId, 项目数据库存workspaceId, 个人数据库存personId
* 作用范围code
*/
private Long scopeId;
private String scopeCode;
/**
* 路径, id拼起来, 以斜杠开头和结束. /1/2/3/
@ -77,14 +77,14 @@ public class IndexNodeInfo {
private IndexNodeState state;
/**
* 子结点
* 子结点, 只有getTree接口会返回
*/
private List<IndexNodeInfo> children;
// !! custom
/**
* 是否可以添加更多的子节点
* 是否可以添加更多的子节点, 只有getTree接口会返回
*/
private boolean addMoreChildren;
@ -93,4 +93,6 @@ public class IndexNodeInfo {
*/
private FileTemplateNodeInfo fileTemplateNodeInfo;
private IndexNodeAttributes attributes;
}

View File

@ -14,4 +14,4 @@ public interface IndexNodeParentScope {
return "";
}
}
}

View File

@ -38,4 +38,4 @@ public interface IndexNodeScope {
}
};
}
}

View File

@ -26,4 +26,4 @@ public interface NodeCreate extends IndexNodeParentScope {
return null;
}
}
}

View File

@ -5,5 +5,5 @@ package cn.axzo.nanopart.doc.api.enums;
* @author yanglin
*/
public enum CooperationType {
PRIVATE, SHARED
NONE, PRIVATE, SHARED
}

View File

@ -1,16 +1,25 @@
package cn.axzo.nanopart.doc.api.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* @author yanglin
*/
@Getter
@RequiredArgsConstructor
public enum DatabaseScope {
//
NONE,
NONE(DatabaseType.NONE),
// 企业数据库
ENT_DATABASE,
ENT_DATABASE(DatabaseType.CREATED_BY_SYSTEM),
// 项目数据库
PROJECT_DATABASE,
PROJECT_DATABASE(DatabaseType.CREATED_BY_SYSTEM),
// 个人数据库: 为单位建的
PERSONAL_FOR_ENT;
}
PERSONAL_FOR_ENT(DatabaseType.CREATED_BY_USER_FOR_ENT);
private final DatabaseType databaseType;
}

View File

@ -1,3 +1,4 @@
package cn.axzo.nanopart.doc.api.enums;
/**
@ -5,10 +6,10 @@ package cn.axzo.nanopart.doc.api.enums;
*/
public enum DatabaseType {
NONE,
// 平台资料库
CREATED_BY_SYSTEM,
// 专属资料库
CREATED_BY_USER_FOR_ENT
NONE,
// 平台资料库
CREATED_BY_SYSTEM,
// 专属资料库
CREATED_BY_USER_FOR_ENT
}
}

View File

@ -15,4 +15,4 @@ public enum IndexNodeState {
// 复制中
COPING,
}
}

View File

@ -0,0 +1,12 @@
package cn.axzo.nanopart.doc.api.enums;
/**
* @author yanglin
*/
public enum TemplateDatabaseState {
// 有效的
VALID,
// 删除
DELETED
}

View File

@ -1,3 +1,4 @@
package cn.axzo.nanopart.doc.api.filedb;
import javax.validation.Valid;
@ -21,34 +22,34 @@ import cn.azxo.framework.common.model.Page;
@FeignClient(name = "nanopart", url = "${axzo.service.nanopart:http://nanopart:8080}")
public interface FileDatabaseApi {
/**
* 添加添加租户
*/
@PostMapping("/api/templateDatabase/createDatabase")
CommonResponse<Void> addWorkspace(@RequestBody @Valid FileDatabaseAddWorkspaceRequest request);
/**
* 添加添加租户
*/
@PostMapping("/api/templateDatabase/createDatabase")
CommonResponse<Void> addWorkspace(@RequestBody @Valid FileDatabaseAddWorkspaceRequest request);
/**
* 开通
*/
@PostMapping("/api/templateDatabase/active")
CommonResponse<Void> addWorkspace(@RequestBody @Valid FileDatabaseActiveRequest request);
/**
* 开通
*/
@PostMapping("/api/templateDatabase/active")
CommonResponse<Void> active(@RequestBody @Valid FileDatabaseActiveRequest request);
/**
* 扩容
*/
@PostMapping("/api/templateDatabase/expandCapacity")
CommonResponse<Void> expandCapacity(@RequestBody @Valid FileDatabaseExpandCapacityRequest request);
/**
* 扩容
*/
@PostMapping("/api/templateDatabase/expandCapacity")
CommonResponse<Void> expandCapacity(@RequestBody @Valid FileDatabaseExpandCapacityRequest request);
/**
* 移除
*/
@PostMapping("/api/templateDatabase/remove")
CommonResponse<Void> remove(@RequestBody @Valid FileDatabaseRemoveRequest request);
/**
* 移除
*/
@PostMapping("/api/templateDatabase/remove")
CommonResponse<Void> remove(@RequestBody @Valid FileDatabaseRemoveRequest request);
/**
* 搜索
*/
@PostMapping("/api/templateDatabase/search")
CommonResponse<Page<FileDatabaseInfoResponse>> search(@RequestBody @Valid FileDatabaseSearchRequest request);
/**
* 搜索
*/
@PostMapping("/api/templateDatabase/search")
CommonResponse<Page<FileDatabaseInfoResponse>> search(@RequestBody @Valid FileDatabaseSearchRequest request);
}
}

View File

@ -1,3 +1,4 @@
package cn.axzo.nanopart.doc.api.filedb.request;
import javax.validation.constraints.Min;
@ -9,24 +10,25 @@ import lombok.Setter;
/**
* @author yanglin
*/
@Setter @Getter
@Setter
@Getter
public class FileDatabaseActiveRequest {
/**
* 资料库id
*/
@NotNull(message = "id不能为空")
private Long id;
/**
* 资料库code
*/
@NotNull(message = "code不能为空")
private String code;
/**
* 容量, 单位GB
*/
@NotNull(message = "allowedCapacity不能为空")
@Min(1)
private Integer allowedCapacity;
/**
* 容量, 单位GB
*/
@NotNull(message = "allowedCapacity不能为空")
@Min(1)
private Integer allowedCapacity;
/**
* 过期时间, unix时间戳
*/
@NotNull(message = "expiredDateMs不能为空")
private Long expiredDateMs;
}
/**
* 过期时间, unix时间戳
*/
@NotNull(message = "expiredDateMs不能为空")
private Long expiredDateMs;
}

View File

@ -1,5 +1,7 @@
package cn.axzo.nanopart.doc.api.filedb.request;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@ -9,19 +11,33 @@ import lombok.Setter;
/**
* @author yanglin
*/
@Setter @Getter
@Setter
@Getter
public class FileDatabaseAddWorkspaceRequest {
/**
* 租户id
*/
@NotNull(message = "workspaceId不能为空")
private Long workspaceId;
/**
* 租户id
*/
@NotNull(message = "workspaceId不能为空")
private Long workspaceId;
/**
* 资料库code
*/
@NotBlank(message = "templateDatabaseCode不能为空")
private String templateDatabaseCode;
/**
* 资料库code
*/
@NotBlank(message = "templateDatabaseCode不能为空")
private String templateDatabaseCode;
}
/**
* 容量, 单位GB
*/
@NotNull(message = "allowedCapacity不能为空")
@Min(1)
private Integer allowedCapacity;
/**
* 过期时间, unix时间戳
*/
@NotNull(message = "expiredDateMs不能为空")
private Long expiredDateMs;
}

View File

@ -1,3 +1,4 @@
package cn.axzo.nanopart.doc.api.filedb.request;
import lombok.Getter;

View File

@ -1,3 +1,4 @@
package cn.axzo.nanopart.doc.api.filedb.request;
import lombok.Getter;
@ -8,12 +9,13 @@ import javax.validation.constraints.NotNull;
/**
* @author yanglin
*/
@Setter @Getter
@Setter
@Getter
public class FileDatabaseRemoveRequest {
/**
* 资料库id
*/
@NotNull(message = "id不能为空")
private Long id;
/**
* 资料库code
*/
@NotNull(message = "code不能为空")
private String code;
}

View File

@ -1,34 +1,37 @@
package cn.axzo.nanopart.doc.api.filedb.request;
import cn.axzo.nanopart.doc.api.enums.FileDatabaseState;
import cn.axzo.basics.common.page.PageRequest;
import cn.axzo.nanopart.doc.api.enums.DatabaseType;
import cn.axzo.nanopart.doc.api.enums.FileDatabaseState;
import lombok.Getter;
import lombok.Setter;
/**
* @author yanglin
*/
@Setter @Getter
public class FileDatabaseSearchRequest {
@Setter
@Getter
public class FileDatabaseSearchRequest extends PageRequest {
/**
* 租户名称
*/
private String workspaceName;
/**
* 租户名称
*/
private String workspaceName;
/**
* 资料库状态. ACTIVATING: 开通中, ACTIVATED: 已开通, EXPIRED: 已到期
*/
private FileDatabaseState state;
/**
* 资料库状态. ACTIVATING: 开通中, ACTIVATED: 已开通, EXPIRED: 已到期
*/
private FileDatabaseState state;
/**
* 资料库类型. CREATED_BY_SYSTEM: 平台资料库, CREATED_BY_USER_FOR_ENT: 专属资料库
*/
private DatabaseType type;
/**
* 资料库类型. CREATED_BY_SYSTEM: 平台资料库, CREATED_BY_USER_FOR_ENT: 专属资料库
*/
private DatabaseType databaseType;
/**
* 资料库名称
*/
private String databaseName;
/**
* 资料库名称
*/
private String databaseName;
}
}

View File

@ -1,3 +1,4 @@
package cn.axzo.nanopart.doc.api.filedb.response;
import cn.axzo.nanopart.doc.api.enums.FileDatabaseState;
@ -7,47 +8,48 @@ import lombok.Setter;
/**
* @author yanglin
*/
@Setter @Getter
@Setter
@Getter
public class FileDatabaseInfoResponse {
/**
* 资料库id
*/
private Long id;
/**
* 资料库code
*/
private String code;
/**
* 租户id
*/
private Long workspaceId;
/**
* 租户id
*/
private Long workspaceId;
/**
* 租户名称
*/
private String workspaceName;
/**
* 租户名称
*/
private String workspaceName;
/**
* 状态. ACTIVATING: 开通中, ACTIVATED: 已开通, EXPIRED: 已到期
*/
private FileDatabaseState state;
/**
* 状态. ACTIVATING: 开通中, ACTIVATED: 已开通, EXPIRED: 已到期
*/
private FileDatabaseState state;
/**
* 资料库名称
*/
private String fileDatabaseName;
/**
* 资料库名称
*/
private String fileDatabaseName;
/**
* 过期时间, unix时间戳
*/
private Long expireDateMs;
/**
* 过期时间, unix时间戳
*/
private Long expireDateMs;
/**
* 购买容量, 单位GB
*/
private Integer allowedCapacity;
/**
* 购买容量, 单位GB
*/
private Integer allowedCapacity;
/**
* 已使用的容量, 单位GB
*/
private Integer usedCapacity;
/**
* 已使用的容量, 单位GB
*/
private Integer usedCapacity;
}
}

View File

@ -18,7 +18,7 @@ import cn.axzo.nanopart.doc.api.filetemplate.response.FileTemplateGetFileInfoRes
import cn.axzo.nanopart.doc.api.domain.IndexNodeInfo;
import cn.axzo.nanopart.doc.api.index.request.CopyNodeRequest;
import cn.axzo.nanopart.doc.api.index.request.DeleteNodeRequest;
import cn.axzo.nanopart.doc.api.index.request.IndexNodePageSearchRequest;
import cn.axzo.nanopart.doc.api.index.request.IndexNodeSearchRequest;
import cn.axzo.nanopart.doc.api.index.request.MoveNodeRequest;
import cn.axzo.nanopart.doc.api.index.request.RenameNodeRequest;
import cn.azxo.framework.common.model.CommonResponse;
@ -87,7 +87,7 @@ public interface FileTemplateApi {
* 文件模版: 搜索
*/
@PostMapping("/api/fileTemplate/search")
CommonResponse<Page<IndexNodeInfo>> search(@RequestBody @Valid IndexNodePageSearchRequest request);
CommonResponse<Page<IndexNodeInfo>> search(@RequestBody @Valid IndexNodeSearchRequest request);
/**
* 文件模版: 获取文件信息

View File

@ -17,7 +17,7 @@ import lombok.Setter;
*/
@Setter
@Getter
public class IndexNodePageSearchRequest extends PageRequest {
public class IndexNodeSearchRequest extends PageRequest {
/**
* 名称

View File

@ -12,7 +12,7 @@ import org.springframework.web.bind.annotation.RequestBody;
import cn.axzo.nanopart.doc.api.domain.IndexNodeInfo;
import cn.axzo.nanopart.doc.api.index.request.CopyNodeRequest;
import cn.axzo.nanopart.doc.api.index.request.DeleteNodeRequest;
import cn.axzo.nanopart.doc.api.index.request.IndexNodePageSearchRequest;
import cn.axzo.nanopart.doc.api.index.request.IndexNodeSearchRequest;
import cn.axzo.nanopart.doc.api.index.request.MoveNodeRequest;
import cn.axzo.nanopart.doc.api.index.request.RenameNodeRequest;
import cn.axzo.nanopart.doc.api.templatedb.reqeust.TemplateDatabaseCreateDatabaseRequest;
@ -95,7 +95,7 @@ public interface TemplateDatabaseApi {
* 项企资料库: 搜索
*/
@PostMapping("/api/templateDatabase/search")
CommonResponse<Page<IndexNodeInfo>> search(@RequestBody @Valid IndexNodePageSearchRequest request);
CommonResponse<Page<IndexNodeInfo>> search(@RequestBody @Valid IndexNodeSearchRequest request);
/**
* 项企资料库: 获取资料库或文件夹信息

View File

@ -1,10 +1,17 @@
package cn.axzo.nanopart.doc.api.templatedb.domain;
import cn.axzo.nanopart.doc.api.enums.DatabaseScope;
import lombok.Getter;
import lombok.Setter;
/**
* @author yanglin
*/
@Setter
@Getter
public class DatabaseOrDirInfo {
/**
* 名称
*/
@ -24,4 +31,10 @@ public class DatabaseOrDirInfo {
* 图标
*/
private String icon;
/**
* 归属. ENT_DATABASE: 企业数据库, PROJECT_DATABASE: 项目数据库
*/
private DatabaseScope scope;
}

View File

@ -3,7 +3,8 @@ package cn.axzo.nanopart.doc.api.templatedb.reqeust;
import javax.validation.constraints.NotNull;
import cn.axzo.nanopart.doc.api.enums.CooperationAccessOption;
import cn.axzo.nanopart.doc.api.domain.IndexNodeAttributes;
import cn.axzo.nanopart.doc.api.enums.CooperationType;
import cn.axzo.nanopart.doc.api.enums.DatabaseScope;
import lombok.Getter;
import lombok.Setter;
@ -22,9 +23,14 @@ public class TemplateDatabaseCreateDatabaseRequest extends TemplateDatabaseCreat
private DatabaseScope scope;
/**
* 协作模. NONE:, ALL_ORGS_IN_PROJECT: 项目内所有企业可见, ORGS_BY_COOPERATE_TYPES: 指定参建单位可见
* 协作模. NONE: , PRIVATE: 专属, SHARED: 共享
*/
@NotNull(message = "accessOption不能为空")
private CooperationAccessOption accessOption = CooperationAccessOption.NONE;
@NotNull(message = "coopType不能为空")
private CooperationType coopType;
}
@Override
public IndexNodeAttributes attributes() {
return null;
}
}

View File

@ -5,6 +5,7 @@ import javax.validation.constraints.NotBlank;
import org.apache.commons.lang3.StringUtils;
import cn.axzo.nanopart.doc.api.domain.IndexNodeAttributes;
import lombok.Getter;
import lombok.Setter;
@ -44,4 +45,10 @@ public class TemplateDatabaseCreateDirRequest extends NodeCreateTemplateDatabase
return StringUtils.isBlank(description) ? "" : description;
}
@Override
public IndexNodeAttributes attributes() {
IndexNodeAttributes attributes = IndexNodeAttributes.create();
attributes.getDirectoryAttributes().setTemplateDatabaseDir(true);
return attributes;
}
}

View File

@ -1,14 +1,14 @@
package cn.axzo.nanopart.doc.api.templatedb.reqeust;
import javax.validation.constraints.NotBlank;
import cn.axzo.nanopart.doc.api.domain.DatabaseAccessConfig;
import cn.axzo.nanopart.doc.api.domain.DatabaseFeeConfig;
import cn.axzo.nanopart.doc.api.templatedb.domain.DatabaseOrDirInfo;
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.NotBlank;
/**
* @author yanglin
*/

View File

@ -13,7 +13,7 @@ import lombok.Setter;
*/
@Setter
@Getter
public class TemplateDatabaseUploadFileRequest extends NodeCreateTemplateDatabase{
public class TemplateDatabaseUploadFileRequest extends NodeCreateTemplateDatabase {
/**
* 上传的文件信息

View File

@ -20,15 +20,10 @@ public class TemplateDatabaseGetDatabaseOrDirInfoResponse {
*/
private IndexNodeType nodeType;
/**
* 范围, 可以直接显示的名称
*/
private String readableScope;
/**
* 基础信息
*/
private DatabaseOrDirInfo databaseOrDirInfo;
private DatabaseOrDirInfo databaseOrDirInfo = new DatabaseOrDirInfo();
/**
* 如果是空间的话, 空间的费用配置

View File

@ -20,7 +20,7 @@ public class DocLockDao extends ServiceImpl<DocLockMapper, DocLock> {
BizAssertions.assertTrue(TransactionSynchronizationManager.isActualTransactionActive(), "必须和事务搭配使用");
DocLock lock = lambdaQuery() //
.eq(DocLock::getKey, key) //
.last("for update") //
.last("FOR UPDATE") //
.one();
if (lock == null) {
lock = new DocLock();

View File

@ -1,14 +1,50 @@
package cn.axzo.nanopart.doc.dao;
import org.springframework.stereotype.Repository;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.axzo.nanopart.doc.api.enums.DatabaseScope;
import cn.axzo.nanopart.doc.api.util.BizAssertions;
import cn.axzo.nanopart.doc.entity.FileDatabase;
import cn.axzo.nanopart.doc.mapper.FileDatabaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Repository;
/**
* @author yanglin
*/
@Repository
public class FileDatabaseDao extends ServiceImpl<FileDatabaseMapper, FileDatabase> {
public FileDatabase findForUpdateOrNull(DatabaseScope scope, String scopeUniqueCode) {
return lambdaQuery() //
.eq(FileDatabase::getScope, scope) //
.eq(FileDatabase::getScopeUniqueCode, scopeUniqueCode) //
.last("FOR UPDATE") //
.one();
}
public FileDatabase getForUpdateOrThrow(String code) {
FileDatabase db = lambdaQuery() //
.eq(FileDatabase::getCode, code) //
.last("FOR UPDATE") //
.one();
BizAssertions.assertNotNull(code, "找不到资料库: {}", code);
return db;
}
public FileDatabase getOrThrow(String code) {
FileDatabase db = lambdaQuery() //
.eq(FileDatabase::getCode, code) //
.one();
BizAssertions.assertNotNull(code, "找不到资料库: {}", code);
return db;
}
public void deleteByCode(String code) {
lambdaUpdate() //
.eq(FileDatabase::getCode, code) //
.remove();
}
}

View File

@ -30,7 +30,7 @@ public class FileTemplateDao extends ServiceImpl<FileTemplateMapper, FileTemplat
.one();
}
public void deleteByCodes(Collection<String> codes) {
public void stateDeleteByCodes(Collection<String> codes) {
if (codes == null)
return;
lambdaUpdate() //

View File

@ -13,6 +13,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.axzo.nanopart.doc.api.domain.IndexNodeParentScope;
import cn.axzo.nanopart.doc.api.domain.IndexNodeScope;
import cn.axzo.nanopart.doc.api.enums.IndexNodeState;
import cn.axzo.nanopart.doc.api.enums.IndexNodeType;
import cn.axzo.nanopart.doc.api.util.BizAssertions;
import cn.axzo.nanopart.doc.entity.IndexNode;
import cn.axzo.nanopart.doc.mapper.IndexNodeMapper;
@ -25,26 +26,26 @@ import lombok.extern.slf4j.Slf4j;
@Repository
public class IndexNodeDao extends ServiceImpl<IndexNodeMapper, IndexNode> {
public IndexNode getNodeForUpdateOrThrow(String code) {
IndexNode node = findNodeForUpdateOrNull(code);
public IndexNode getForUpdateOrThrow(String code) {
IndexNode node = findForUpdateOrNull(code);
BizAssertions.assertNotNull(node, "节点不存在: {}", code);
return node;
}
public IndexNode findNodeForUpdateOrNull(String code) {
public IndexNode findForUpdateOrNull(String code) {
return lambdaQuery() //
.eq(IndexNode::getCode, code) //
.last("FOR UPDATE") //
.one();
}
public IndexNode getNodeOrThrow(String code) {
IndexNode node = findNodeOrNull(code);
public IndexNode getOrThrow(String code) {
IndexNode node = findOrNull(code);
BizAssertions.assertNotNull(node, "节点不存在: {}", code);
return node;
}
public IndexNode findNodeOrNull(String code) {
public IndexNode findOrNull(String code) {
return lambdaQuery() //
.eq(IndexNode::getCode, code) //
.one();
@ -57,10 +58,11 @@ public class IndexNodeDao extends ServiceImpl<IndexNodeMapper, IndexNode> {
.update();
}
public IndexNode findChildByName(IndexNodeScope nodeScope, String parentCode, String name) {
return parentOrScopeQuery(nodeScope, parentCode) //
.eq(IndexNode::getParentCode, parentCode) //
public IndexNode findValidChildByName(IndexNodeParentScope parentNode, IndexNodeType nodeType, String name) {
return parentOrScopeQuery(parentNode) //
.eq(IndexNode::getName, name) //
.eq(IndexNode::getNodeType, nodeType) //
.eq(IndexNode::getState, IndexNodeState.VALID) //
.last("limit 1") //
.one();
}
@ -79,36 +81,33 @@ public class IndexNodeDao extends ServiceImpl<IndexNodeMapper, IndexNode> {
.update();
}
public List<IndexNode> collectSubtree(String code) {
public List<IndexNode> collectValidSubtree(IndexNode indexNode) {
return lambdaQuery() //
.likeRight(IndexNode::getPath, code) //
.likeRight(IndexNode::getPath, indexNode.getPath()) //
.list();
}
public void deleteSubtree(String code) {
lambdaUpdate() //
.likeRight(IndexNode::getPath, code) //
.set(IndexNode::getState, IndexNodeState.DELETED) //
.update();
public int validSubtreeFileCount(IndexNode indexNode) {
return lambdaQuery() //
.likeRight(IndexNode::getPath, indexNode.getPath()) //
.eq(IndexNode::getState, IndexNodeState.VALID) //
.eq(IndexNode::getNodeType, IndexNodeType.FILE) //
.count();
}
public int countValidChild(IndexNodeParentScope parentScope) {
return parentOrScopeQuery(parentScope.nodeScope(), parentScope.parentCode()) //
public int validChildrenCount(String parentCode) {
BizAssertions.assertNotBlank(parentCode, "父节点不能为空");
return lambdaQuery() //
.eq(IndexNode::getParentCode, parentCode) //
.eq(IndexNode::getState, IndexNodeState.VALID) //
.count();
}
private LambdaQueryChainWrapper<IndexNode> parentOrScopeQuery(IndexNodeScope nodeScope, String parentCode) {
if (StringUtils.isBlank(parentCode))
return scopeQuery(nodeScope);
return lambdaQuery().eq(IndexNode::getParentCode, parentCode);
}
private LambdaQueryChainWrapper<IndexNode> scopeQuery(IndexNodeScope nodeScope) {
return lambdaQuery() //
.eq(IndexNode::getContext, nodeScope.context()) //
.eq(IndexNode::getScope, nodeScope.scope()) //
.eq(IndexNode::getScopeCode, nodeScope.scopeCode()).eq(IndexNode::getParentCode, "");
public void stateDeleteSubtree(IndexNode indexNode) {
lambdaUpdate() //
.likeRight(IndexNode::getPath, indexNode.getPath()) //
.set(IndexNode::getState, IndexNodeState.DELETED) //
.update();
}
public void updateFileSize(String code, long size) {
@ -118,4 +117,17 @@ public class IndexNodeDao extends ServiceImpl<IndexNodeMapper, IndexNode> {
.update();
}
private LambdaQueryChainWrapper<IndexNode> parentOrScopeQuery(IndexNodeParentScope parentScope) {
if (StringUtils.isBlank(parentScope.parentCode()))
return scopeQuery(parentScope.nodeScope());
return lambdaQuery().eq(IndexNode::getParentCode, parentScope.parentCode());
}
public LambdaQueryChainWrapper<IndexNode> scopeQuery(IndexNodeScope nodeScope) {
return lambdaQuery() //
.eq(IndexNode::getContext, nodeScope.context()) //
.eq(IndexNode::getScope, nodeScope.scope()) //
.eq(IndexNode::getScopeCode, nodeScope.scopeCode());
}
}

View File

@ -1,14 +1,34 @@
package cn.axzo.nanopart.doc.dao;
import java.util.List;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Repository;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.axzo.nanopart.doc.api.enums.TemplateDatabaseState;
import cn.axzo.nanopart.doc.entity.TemplateDatabase;
import cn.axzo.nanopart.doc.mapper.TemplateDatabaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Repository;
/**
* @author yanglin
*/
@Repository
public class TemplateDatabaseDao extends ServiceImpl<TemplateDatabaseMapper, TemplateDatabase> {
public TemplateDatabase findOrNull(String code) {
return lambdaQuery().eq(TemplateDatabase::getCode, code).one();
}
public void stateDeleteByCodes(List<String> codes) {
if (CollectionUtils.isEmpty(codes))
return;
lambdaUpdate() //
.in(TemplateDatabase::getCode, codes) //
.set(TemplateDatabase::getState, TemplateDatabaseState.DELETED) //
.remove();
}
}

View File

@ -3,12 +3,10 @@ package cn.axzo.nanopart.doc.entity;
import java.util.Date;
import cn.axzo.nanopart.doc.api.enums.CooperationAccessOption;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.annotation.TableName;
import cn.axzo.nanopart.doc.api.enums.DatabaseScope;
import cn.axzo.nanopart.doc.api.enums.DatabaseType;
import cn.axzo.nanopart.doc.api.enums.FileDatabaseState;
import cn.axzo.nanopart.doc.api.util.YesOrNo;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
@ -28,26 +26,21 @@ public class FileDatabase extends BaseEntity<FileDatabase> {
*/
private String code;
/**
* 业务编码
*/
private String bizCode;
/**
* 对应的模版数据的编码
*/
private String templateDatabaseCode;
/**
* 资料库类型. CREATED_BY_SYSTEM: 平台资料库, CREATED_BY_USER_FOR_ENT: 专属资料库
*/
private DatabaseType type;
/**
* 作用范围. NONE: , ENT_DATABASE: 企业数据库, PROJECT_DATABASE: 项目数据库, PERSONAL_DATABASE: 个人数据库
*/
private DatabaseScope scope;
/**
* 用户判断scope的唯一性
*/
private String scopeUniqueCode;
/**
* 人员id
*/
@ -58,26 +51,11 @@ public class FileDatabase extends BaseEntity<FileDatabase> {
*/
private Long workspaceId;
/**
* 单位id
*/
private Long ouId;
/**
* 协作模式, NONE: , ALL_ORGS_IN_PROJECT: 项目内所有企业可见, ORGS_BY_COOPERATE_TYPES: 指定参建单位可见
*/
private CooperationAccessOption coopAccessOption;
/**
* 状态. ACTIVATING: 开通中, ACTIVATED: 已开通, EXPIRED: 已到期
*/
private FileDatabaseState state;
/**
* 是否需要付费. YES: 需要, NO: 不需要
*/
private YesOrNo needFee;
/**
* 到期时间
*/
@ -93,6 +71,14 @@ public class FileDatabase extends BaseEntity<FileDatabase> {
*/
private Integer usedCapacity;
public boolean isActivated() {
return state == FileDatabaseState.ACTIVATED;
}
public boolean isActivating() {
return state == FileDatabaseState.ACTIVATING;
}
@Override
public String toString() {
return JSON.toJSONString(this);

View File

@ -78,7 +78,7 @@ public class IndexNode extends BaseEntity<IndexNode> implements NodeValue, Index
private DatabaseScope scope;
/**
* 作用范围id. 单位数据库存ouId, 项目数据库存workspaceId, 个人数据库存personId
* 作用范围code
*/
private String scopeCode;
@ -127,6 +127,14 @@ public class IndexNode extends BaseEntity<IndexNode> implements NodeValue, Index
return nodeType == IndexNodeType.FILE;
}
public boolean isDirectory() {
return nodeType == IndexNodeType.DIRECTORY;
}
public boolean isDatabase() {
return nodeType == IndexNodeType.DATABASE;
}
@Override
public String toString() {
return JSON.toJSONString(this);

View File

@ -8,7 +8,9 @@ import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
import cn.axzo.nanopart.doc.api.domain.DatabaseAccessConfig;
import cn.axzo.nanopart.doc.api.domain.DatabaseFeeConfig;
import cn.axzo.nanopart.doc.api.enums.CooperationType;
import cn.axzo.nanopart.doc.api.enums.DatabaseScope;
import cn.axzo.nanopart.doc.api.enums.TemplateDatabaseState;
import cn.axzo.pudge.core.persistence.BaseEntity;
import lombok.Getter;
import lombok.Setter;
@ -31,6 +33,16 @@ public class TemplateDatabase extends BaseEntity<TemplateDatabase> {
*/
private DatabaseScope scope;
/**
* 协作模式. NONE: , PRIVATE: 专属, SHARED: 共享
*/
private CooperationType coopType;
/**
* 状态. VALID: 有效的, DELETED: 已删除
*/
private TemplateDatabaseState state;;
/**
* 费用配置
*/
@ -43,6 +55,18 @@ public class TemplateDatabase extends BaseEntity<TemplateDatabase> {
@TableField(typeHandler = FastjsonTypeHandler.class)
private DatabaseAccessConfig accessConfig;
public DatabaseFeeConfig getOrCreateFeeConfig() {
if (feeConfig == null)
feeConfig = new DatabaseFeeConfig();
return feeConfig;
}
public DatabaseAccessConfig getOrCreateAccessConfig() {
if (accessConfig == null)
accessConfig = new DatabaseAccessConfig();
return accessConfig;
}
@Override
public String toString() {
return JSON.toJSONString(this);

View File

@ -1,6 +1,9 @@
package cn.axzo.nanopart.doc.file.filedb;
import org.springframework.web.bind.annotation.RestController;
import cn.axzo.nanopart.doc.api.filedb.FileDatabaseApi;
import cn.axzo.nanopart.doc.api.filedb.request.FileDatabaseActiveRequest;
import cn.axzo.nanopart.doc.api.filedb.request.FileDatabaseAddWorkspaceRequest;
import cn.axzo.nanopart.doc.api.filedb.request.FileDatabaseExpandCapacityRequest;
@ -9,9 +12,6 @@ import cn.axzo.nanopart.doc.api.filedb.request.FileDatabaseSearchRequest;
import cn.axzo.nanopart.doc.api.filedb.response.FileDatabaseInfoResponse;
import cn.azxo.framework.common.model.CommonResponse;
import cn.azxo.framework.common.model.Page;
import org.springframework.web.bind.annotation.RestController;
import cn.axzo.nanopart.doc.api.filedb.FileDatabaseApi;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -23,30 +23,35 @@ import lombok.extern.slf4j.Slf4j;
@RequiredArgsConstructor
public class FileDatabaseApiController implements FileDatabaseApi {
private final FileDatabaseManager fileDatabaseManager;
private final FileDatabaseService fileDatabaseService;
@Override
public CommonResponse<Void> addWorkspace(FileDatabaseAddWorkspaceRequest request) {
return null;
fileDatabaseService.addWorkspace(request);
return CommonResponse.success();
}
@Override
public CommonResponse<Void> addWorkspace(FileDatabaseActiveRequest request) {
return null;
public CommonResponse<Void> active(FileDatabaseActiveRequest request) {
fileDatabaseService.active(request);
return CommonResponse.success();
}
@Override
public CommonResponse<Void> expandCapacity(FileDatabaseExpandCapacityRequest request) {
return null;
fileDatabaseService.expandCapacity(request);
return CommonResponse.success();
}
@Override
public CommonResponse<Void> remove(FileDatabaseRemoveRequest request) {
return null;
fileDatabaseService.remove(request);
return CommonResponse.success();
}
@Override
public CommonResponse<Page<FileDatabaseInfoResponse>> search(FileDatabaseSearchRequest request) {
return null;
return CommonResponse.success(fileDatabaseService.search(request));
}
}

View File

@ -1,13 +0,0 @@
package cn.axzo.nanopart.doc.file.filedb;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
/**
* @author yanglin
*/
@Component
@RequiredArgsConstructor
public class FileDatabaseManager {
}

View File

@ -0,0 +1,169 @@
package cn.axzo.nanopart.doc.file.filedb;
import static cn.axzo.nanopart.doc.api.util.BizAssertions.fail;
import static java.util.stream.Collectors.toList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import com.baomidou.mybatisplus.core.metadata.IPage;
import cn.axzo.apollo.workspace.api.workspace.WorkspaceApi;
import cn.axzo.apollo.workspace.api.workspace.req.GetSimpleWorkspaceReqV2;
import cn.axzo.apollo.workspace.api.workspace.res.SimpleWorkspaceRes;
import cn.axzo.nanopart.doc.api.domain.IndexNodeScope;
import cn.axzo.nanopart.doc.api.enums.DatabaseScope;
import cn.axzo.nanopart.doc.api.enums.DatabaseType;
import cn.axzo.nanopart.doc.api.enums.FileDatabaseState;
import cn.axzo.nanopart.doc.api.enums.IndexNodeType;
import cn.axzo.nanopart.doc.api.filedb.request.FileDatabaseActiveRequest;
import cn.axzo.nanopart.doc.api.filedb.request.FileDatabaseAddWorkspaceRequest;
import cn.axzo.nanopart.doc.api.filedb.request.FileDatabaseExpandCapacityRequest;
import cn.axzo.nanopart.doc.api.filedb.request.FileDatabaseRemoveRequest;
import cn.axzo.nanopart.doc.api.filedb.request.FileDatabaseSearchRequest;
import cn.axzo.nanopart.doc.api.filedb.response.FileDatabaseInfoResponse;
import cn.axzo.nanopart.doc.api.util.BizAssertions;
import cn.axzo.nanopart.doc.api.util.UUIDUtil;
import cn.axzo.nanopart.doc.dao.FileDatabaseDao;
import cn.axzo.nanopart.doc.entity.FileDatabase;
import cn.axzo.nanopart.doc.entity.IndexNode;
import cn.axzo.nanopart.doc.entity.TemplateDatabase;
import cn.axzo.nanopart.doc.file.index.IndexQueryService;
import cn.axzo.nanopart.doc.file.index.domain.IndexNodes;
import cn.axzo.nanopart.doc.file.templatedb.TemplateDatabaseManager;
import cn.axzo.nanopart.doc.utils.BizTransactional;
import cn.axzo.nanopart.doc.utils.RpcExternalUtil;
import cn.azxo.framework.common.model.Page;
import lombok.RequiredArgsConstructor;
/**
* @author yanglin
*/
@Component
@RequiredArgsConstructor
public class FileDatabaseService {
private final FileDatabaseDao fileDatabaseDao;
private final TemplateDatabaseManager templateDatabaseManager;
private final WorkspaceApi workspaceApi;
private final IndexQueryService indexQueryService;
@BizTransactional
public void addWorkspace(FileDatabaseAddWorkspaceRequest request) {
String scopeUniqueCode = String.valueOf(request.getWorkspaceId());
TemplateDatabase templateDatabase = templateDatabaseManager.getOrThrow(request.getTemplateDatabaseCode());
FileDatabase savedDb = fileDatabaseDao.findForUpdateOrNull(templateDatabase.getScope(), scopeUniqueCode);
if (savedDb != null)
throw fail("无法重复创建, 请刷新页面查询已创建的记录");
FileDatabase db = new FileDatabase();
db.setCode(UUIDUtil.uuidString());
db.setTemplateDatabaseCode(templateDatabase.getCode());
db.setScope(templateDatabase.getScope());
db.setScopeUniqueCode(scopeUniqueCode);
db.setWorkspaceId(request.getWorkspaceId());
db.setState(FileDatabaseState.ACTIVATING);
db.setExpireDate(new Date(request.getExpiredDateMs()));
db.setAllowedCapacity(request.getAllowedCapacity());
db.setUsedCapacity(0);
fileDatabaseDao.save(db);
}
public void active(FileDatabaseActiveRequest request) {
// TODO(yl): copy database from template
}
@BizTransactional
public void expandCapacity(FileDatabaseExpandCapacityRequest request) {
FileDatabase db = fileDatabaseDao.getForUpdateOrThrow(request.getCode());
BizAssertions.assertTrue(db.isActivated(), "只有激活状态的资料库才能扩容");
fileDatabaseDao.lambdaUpdate() //
.eq(FileDatabase::getCode, request.getCode()) //
.set(FileDatabase::getAllowedCapacity, request.getAllowedCapacity()) //
.set(FileDatabase::getExpireDate, new Date(request.getExpiredDateMs())) //
.update();
}
public void remove(FileDatabaseRemoveRequest request) {
fileDatabaseDao.deleteByCode(request.getCode());
}
@SuppressWarnings("unchecked")
public Page<FileDatabaseInfoResponse> search(FileDatabaseSearchRequest request) {
List<Long> seachWorkspaceIds = null;
if (StringUtils.isNotBlank(request.getWorkspaceName())) {
GetSimpleWorkspaceReqV2 workspaceSearchRequest1 = new GetSimpleWorkspaceReqV2();
workspaceSearchRequest1.setLikeName(request.getWorkspaceName());
seachWorkspaceIds = RpcExternalUtil.rpcApolloProcessor(
() -> workspaceApi.getListV2(workspaceSearchRequest1), "查询工作台列表1", workspaceSearchRequest1) //
.stream().map(SimpleWorkspaceRes::getId).collect(toList());
if (seachWorkspaceIds.isEmpty())
return Page.zero();
}
List<String> seachTemplateDatabaseCodes = null;
if (StringUtils.isNotBlank(request.getDatabaseName())) {
List<IndexNode> templateNodes = indexQueryService.getNameLike(IndexNodeScope.TEMPLATE_DATABASE_SCOPE,
request.getDatabaseName(), IndexNodeType.DATABASE);
if (templateNodes.isEmpty())
return Page.zero();
seachTemplateDatabaseCodes = templateNodes.stream().map(IndexNode::getCode).collect(toList());
}
List<DatabaseScope> seachScopes = null;
if (request.getDatabaseType() != null && request.getDatabaseType() != DatabaseType.NONE) {
seachScopes = Arrays.stream(DatabaseScope.values()) //
.filter(i -> i.getDatabaseType() == request.getDatabaseType()) //
.collect(toList());
if (seachScopes.isEmpty())
return Page.zero();
}
// @formatter:off
IPage<FileDatabase> page = fileDatabaseDao.lambdaQuery()
.eq(request.getState() != null, FileDatabase::getState, request.getState())
.in(CollectionUtils.isNotEmpty(seachWorkspaceIds), FileDatabase::getWorkspaceId, seachWorkspaceIds)
.in(CollectionUtils.isNotEmpty(seachTemplateDatabaseCodes), FileDatabase::getTemplateDatabaseCode, seachTemplateDatabaseCodes) //
.in(CollectionUtils.isNotEmpty(seachScopes), FileDatabase::getScope, seachScopes)
.orderByDesc(FileDatabase::getId)
.page(request.toPage());
// @formatter:on
IndexNodes indexNodes = IndexNodes.wrap(indexQueryService.get(page.getRecords().stream() //
.map(FileDatabase::getTemplateDatabaseCode) //
.collect(toList())));
Map<Long, SimpleWorkspaceRes> id2Workspace = new HashMap<>();
List<Long> resultWorkspaceIds = page.getRecords().stream() //
.map(FileDatabase::getWorkspaceId) //
.collect(toList());
if (!resultWorkspaceIds.isEmpty()) {
GetSimpleWorkspaceReqV2 workspaceSearchRequest2 = new GetSimpleWorkspaceReqV2();
workspaceSearchRequest2.setIds(resultWorkspaceIds);
RpcExternalUtil.rpcApolloProcessor(() -> workspaceApi.getListV2(workspaceSearchRequest2), "查询工作台列表2",
workspaceSearchRequest2).forEach(workspace -> id2Workspace.put(workspace.getId(), workspace));
}
List<FileDatabaseInfoResponse> records = page.getRecords().stream() //
.map(db -> { //
IndexNode dbNode = indexNodes.findOrNull(db.getCode());
SimpleWorkspaceRes workspace = id2Workspace.get(db.getWorkspaceId());
FileDatabaseInfoResponse resp = new FileDatabaseInfoResponse();
resp.setCode(db.getCode());
resp.setWorkspaceId(db.getWorkspaceId());
resp.setWorkspaceName(workspace == null ? "" : workspace.getName());
resp.setState(db.getState());
resp.setFileDatabaseName(dbNode == null ? "" : dbNode.getName());
resp.setExpireDateMs(db.getExpireDate() == null ? null : db.getExpireDate().getTime());
resp.setAllowedCapacity(db.getAllowedCapacity());
resp.setUsedCapacity(db.getUsedCapacity());
return resp;
}) //
.collect(toList());
return Page.toPage(request.getPage(), request.getPageSize(), page.getTotal(), records);
}
}

View File

@ -6,6 +6,7 @@ import java.util.List;
import org.springframework.web.bind.annotation.RestController;
import cn.axzo.basics.common.BeanMapper;
import cn.axzo.nanopart.doc.api.domain.IndexNodeInfo;
import cn.axzo.nanopart.doc.api.domain.IndexNodeScope;
import cn.axzo.nanopart.doc.api.filetemplate.FileTemplateApi;
import cn.axzo.nanopart.doc.api.filetemplate.request.FileTemplateCreateDirRequest;
@ -14,10 +15,9 @@ import cn.axzo.nanopart.doc.api.filetemplate.request.FileTemplateGetFileInfoRequ
import cn.axzo.nanopart.doc.api.filetemplate.request.FileTemplateUpdateFileInfoRequest;
import cn.axzo.nanopart.doc.api.filetemplate.request.FileTemplateUploadFileRequest;
import cn.axzo.nanopart.doc.api.filetemplate.response.FileTemplateGetFileInfoResponse;
import cn.axzo.nanopart.doc.api.domain.IndexNodeInfo;
import cn.axzo.nanopart.doc.api.index.request.CopyNodeRequest;
import cn.axzo.nanopart.doc.api.index.request.DeleteNodeRequest;
import cn.axzo.nanopart.doc.api.index.request.IndexNodePageSearchRequest;
import cn.axzo.nanopart.doc.api.index.request.IndexNodeSearchRequest;
import cn.axzo.nanopart.doc.api.index.request.MoveNodeRequest;
import cn.axzo.nanopart.doc.api.index.request.RenameNodeRequest;
import cn.axzo.nanopart.doc.entity.FileTemplate;
@ -95,7 +95,7 @@ public class FileTemplateApiController implements FileTemplateApi {
}
@Override
public CommonResponse<Page<IndexNodeInfo>> search(IndexNodePageSearchRequest request) {
public CommonResponse<Page<IndexNodeInfo>> search(IndexNodeSearchRequest request) {
log.info("search request:{}", request);
Page<IndexNode> page = indexQueryService.search(IndexNodeScope.FILE_TEMPLATE_SCOPE, request);
return CommonResponse.success(Page.toPage(page.getPageNum(), page.getPageSize(), page.getTotalElements(),

View File

@ -55,8 +55,8 @@ public class FileTemplateManager {
@BizTransactional
public void delete(DeleteNodeRequest request) {
IndexNodes nodes = IndexNodes.wrap(indexManager.delete(request.getCode()));
fileTemplateDao.deleteByCodes(nodes.collectCodes(IndexNodeType.FILE));
IndexNodes deletedNodes = IndexNodes.wrap(indexManager.delete(request.getCode()));
fileTemplateDao.stateDeleteByCodes(deletedNodes.collectCodes(IndexNodeType.FILE));
}
public FileTemplate findOrNull(String code) {

View File

@ -3,11 +3,16 @@ package cn.axzo.nanopart.doc.file.index;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionTemplate;
import cn.axzo.maokai.api.util.Ref;
import cn.axzo.maokai.api.vo.response.tree.Node;
import cn.axzo.maokai.api.vo.response.tree.RecursiveVisitor;
import cn.axzo.maokai.api.vo.response.tree.TreeBuilder;
import cn.axzo.maokai.api.vo.response.tree.WalkingDecision;
import cn.axzo.nanopart.doc.api.domain.NodeCreate;
import cn.axzo.nanopart.doc.api.domain.OssFile;
import cn.axzo.nanopart.doc.api.enums.FileFormat;
@ -41,14 +46,14 @@ public class IndexManager {
@BizTransactional
public IndexNode createDatabase(NodeCreate create) {
indexSupport.lockParentAndReleaseOnCommit(create);
indexSupport.ensureChildNameNotUsed(create);
indexSupport.ensureChildNameNotUsed(create, IndexNodeType.DATABASE);
return indexSupport.createNode(create, IndexNodeType.DATABASE);
}
@BizTransactional
public IndexNode createDir(NodeCreate create) {
indexSupport.lockParentAndReleaseOnCommit(create);
indexSupport.ensureChildNameNotUsed(create);
indexSupport.ensureChildNameNotUsed(create, IndexNodeType.DIRECTORY);
return indexSupport.createNode(create, IndexNodeType.DIRECTORY);
}
@ -58,7 +63,7 @@ public class IndexManager {
public OssFile uploadEmptyFile(NodeCreate create, FileFormat format) {
BizAssertions.assertTrue(format.creatable(), "无法创建: {}", format.readableName());
BizAssertions.assertFalse(TransactionSynchronizationManager.isActualTransactionActive(), "不能在事务中使用");
indexSupport.ensureChildNameNotUsed(create);
indexSupport.ensureChildNameNotUsed(create, IndexNodeType.FILE);
String emptyOssFileKey = format == FileFormat.WORD //
? docProps.getEmptyWordOssFileKey() //
: docProps.getEmptyExcelFileKey();
@ -67,14 +72,14 @@ public class IndexManager {
@BizTransactional
public IndexNode uploadFile(NodeCreate node, OssFile ossFile) {
indexSupport.ensureChildNameNotUsed(node);
indexSupport.ensureChildNameNotUsed(node, IndexNodeType.FILE);
IndexNode fileNode = createFile(node, ossFile);
updateFileSize(fileNode.getCode(), ossFile.getSize());
return fileNode;
}
public void updateFileSize(String code, int size) {
IndexNode fileNode = indexNodeDao.getNodeOrThrow(code);
IndexNode fileNode = getOrThrow(code);
BizAssertions.assertTrue(fileNode.isFile(), "不是文件节点, 无法更新文件大小");
indexNodeDao.updateFileSize(code, size);
}
@ -85,7 +90,7 @@ public class IndexManager {
return transactionTemplate.execute(unused -> {
indexSupport.lockParentAndReleaseOnCommit(node);
try {
indexSupport.ensureChildNameNotUsed(node);
indexSupport.ensureChildNameNotUsed(node, IndexNodeType.FILE);
}
catch (NameUsedException e) {
deleteOssFile.set(true);
@ -95,10 +100,11 @@ public class IndexManager {
fileNode.getOrCreateAttributes().getOrCreateFileAttributes().setOssFileKey(ossFile.getOssFileKey());
fileNode.getOrCreateAttributes().getOrCreateFileAttributes().setFileFormat(ossFile.getFormat());
indexNodeDao.updateAttributes(fileNode);
return indexNodeDao.findNodeOrNull(fileNode.getCode());
return findOrNull(fileNode.getCode());
});
}
finally {
// 不要放到事务中
if (deleteOssFile.get())
fileBroadcaster.fireDeleteOssFile(ossFile.getOssFileKey(), "create file failed");
}
@ -106,29 +112,65 @@ public class IndexManager {
@BizTransactional
public void rename(String code, String newName) {
IndexNode indexNode = indexNodeDao.getNodeOrThrow(code);
indexSupport.lockParentAndReleaseOnCommit(indexNode);
IndexNode indexNode = getOrThrow(code);
if (indexNode.getName().equals(newName))
return;
indexSupport.ensureChildNameNotUsed(indexNode, indexNode.getParentCode(), newName);
indexSupport.lockParentAndReleaseOnCommit(indexNode);
indexSupport.ensureChildNameNotUsed(indexNode, indexNode.getNodeType(), newName);
indexNodeDao.rename(code, newName);
if (indexNode.isFile())
fileBroadcaster.fireRenameIndexNodeOssFile(code);
}
/**
* 先做成一次性删完整个子树
*/
@BizTransactional
public List<IndexNode> delete(String code) {
List<IndexNode> subtree = indexNodeDao.collectSubtree(code);
indexNodeDao.deleteSubtree(code);
IndexNode indexNode = getOrThrow(code);
List<IndexNode> subtree = indexNodeDao.collectValidSubtree(indexNode);
indexNodeDao.stateDeleteSubtree(indexNode);
return subtree;
}
public IndexNode copy(String node, String destParentCode) {
public IndexNode copy(String srcCode, String destParentCode) {
// TODO(yl): 文件夹不能拷贝到文件下面
return null;
}
public IndexNode move(String node, String destParentCode) {
public IndexNode move(String srcCode, String destParentCode) {
IndexNode srcNode = getOrThrow(srcCode);
List<IndexNode> indexNodes = indexNodeDao.validSubtreeFileCount();
TreeBuilder.build(indexNodes).walkDown(new RecursiveVisitor() {
@Override
public WalkingDecision visit(Node node) {
if (node.isTreeRoot())
return WalkingDecision.CONTINUE;
IndexNode value = node.<IndexNode> asValueNode().getValue();
return WalkingDecision.CONTINUE;
}
});
// TODO(yl): 文件夹不能移动到文件下面
return null;
}
public IndexNode findOrNull(String code) {
return indexNodeDao.findOrNull(code);
}
public IndexNode getOrThrow(String code) {
return indexNodeDao.getOrThrow(code);
}
public void updateBizInfo(String code, String bizCode, String description, String icon) {
if (StringUtils.isBlank(bizCode) && StringUtils.isBlank(description) && StringUtils.isBlank(icon))
return;
indexNodeDao.lambdaUpdate() //
.eq(IndexNode::getCode, code) //
.set(StringUtils.isNotBlank(bizCode), IndexNode::getBizCode, bizCode) //
.set(StringUtils.isNotBlank(description), IndexNode::getDescription, description) //
.set(StringUtils.isNotBlank(icon), IndexNode::getIcon, icon) //
.update();
}
}

View File

@ -2,12 +2,16 @@
package cn.axzo.nanopart.doc.file.index;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import cn.axzo.nanopart.doc.api.domain.IndexNodeScope;
import cn.axzo.nanopart.doc.api.index.request.IndexNodePageSearchRequest;
import cn.axzo.nanopart.doc.api.enums.IndexNodeType;
import cn.axzo.nanopart.doc.api.index.request.IndexNodeSearchRequest;
import cn.axzo.nanopart.doc.dao.IndexNodeDao;
import cn.axzo.nanopart.doc.entity.IndexNode;
import cn.azxo.framework.common.model.Page;
@ -26,9 +30,23 @@ public class IndexQueryService {
return new ArrayList<>();
}
public Page<IndexNode> search(IndexNodeScope nodeScope, IndexNodePageSearchRequest search) {
public Page<IndexNode> search(IndexNodeScope nodeScope, IndexNodeSearchRequest search) {
//todo valid state
return null;
}
public List<IndexNode> getNameLike(IndexNodeScope nodeScope, String name, IndexNodeType... nodeTypes) {
List<IndexNodeType> effectiveNodeTypes = nodeTypes == null ? Collections.emptyList() : Arrays.asList(nodeTypes);
return indexNodeDao.scopeQuery(nodeScope) //
.like(IndexNode::getName, name) //
.in(!effectiveNodeTypes.isEmpty(), IndexNode::getNodeType, effectiveNodeTypes) //
.list();
}
public List<IndexNode> get(List<String> codes) {
if (CollectionUtils.isEmpty(codes))
return Collections.emptyList();
return indexNodeDao.lambdaQuery().in(IndexNode::getCode, codes).list();
}
}

View File

@ -35,23 +35,10 @@ class IndexSupport {
IndexNode createNode(NodeCreate create, IndexNodeType nodeType) {
String code = UUIDUtil.uuidString();
if (nodeType == IndexNodeType.DATABASE)
BizAssertions.assertBlank(create.parentCode(), "创建空间时不能指定父节点");
BizAssertions.assertTrue(indexNodeDao.countValidChild(create) <= docProps.getIndexNodeMaxChildrenSize(),
"子节点数量超过限制{}, 无法再创建新节点", docProps.getIndexNodeMaxChildrenSize());
IndexNode parent = null;
if (StringUtils.isNotBlank(create.parentCode())) {
parent = indexNodeDao.getNodeOrThrow(create.parentCode());
BizAssertions.assertTrue(parent.path().depth() < docProps.getIndexNodeMaxDepth(), //
"节点深度超过限制{}, 无法再创建新节点", docProps.getIndexNodeMaxDepth());
BizAssertions.assertEquals(parent.getContext(), create.nodeScope().context(), //
"创建子节点时父子context不匹配: {}", create.parentCode());
BizAssertions.assertEquals(parent.getScope(), create.nodeScope(), //
"创建子节点时父子scope不匹配: {}", create.parentCode());
BizAssertions.assertEquals(parent.getScopeCode(), create.nodeScope().scopeCode(), //
"创建子节点时父子scopeId不匹配: {}", create.parentCode());
if (nodeType == IndexNodeType.DIRECTORY)
BizAssertions.assertFalse(parent.isFile(), "不能在文件下建立文件夹");
parent = indexNodeDao.getOrThrow(create.parentCode());
validateBeforeCreateChild(parent, create, nodeType);
}
IndexNode child = new IndexNode();
child.setCode(code);
@ -71,29 +58,42 @@ class IndexSupport {
indexNodeDao.save(child);
Path basePath = parent == null ? Path.empty() : parent.path();
indexNodeDao.updatePath(child.getCode(), basePath.append(String.valueOf(child.getId())).toString());
return indexNodeDao.getNodeOrThrow(child.getCode());
return indexNodeDao.getOrThrow(child.getCode());
}
void ensureChildNameNotUsed(NodeCreate create) {
ensureChildNameNotUsed(create.nodeScope(), create.parentCode(), create.name());
private void validateBeforeCreateChild(IndexNode parent, NodeCreate create, IndexNodeType nodeType) {
BizAssertions.assertTrue(
indexNodeDao.validChildrenCount(parent.getCode()) < docProps.getIndexNodeMaxChildrenSize(),
"创建失败, 子节点数量不能超过 {}", docProps.getIndexNodeMaxChildrenSize());
BizAssertions.assertTrue(parent.path().depth() < docProps.getIndexNodeMaxDepth(), //
"节点深度超过限制{}, 无法再创建新节点", docProps.getIndexNodeMaxDepth());
BizAssertions.assertEquals(parent.getContext(), create.nodeScope().context(), //
"创建子节点时父子context不匹配: {}", create.parentCode());
BizAssertions.assertEquals(parent.getScope(), create.nodeScope(), //
"创建子节点时父子scope不匹配: {}", create.parentCode());
BizAssertions.assertEquals(parent.getScopeCode(), create.nodeScope().scopeCode(), //
"创建子节点时父子scopeId不匹配: {}", create.parentCode());
if (nodeType == IndexNodeType.DIRECTORY)
BizAssertions.assertFalse(parent.isFile(), "不能在文件下建立文件夹");
}
void ensureChildNameNotUsed(IndexNodeScope nodeScope, String parentCode, String childName) {
IndexNode child = indexNodeDao.findChildByName(nodeScope, parentCode, childName);
void ensureChildNameNotUsed(NodeCreate create, IndexNodeType nodeType) {
ensureChildNameNotUsed(create, nodeType, create.name());
}
void ensureChildNameNotUsed(IndexNodeParentScope parentNode, IndexNodeType nodeType, String childName) {
IndexNode child = indexNodeDao.findValidChildByName(parentNode, nodeType, childName);
if (child != null)
throw new NameUsedException("名称已被使用");
}
void lockParentAndReleaseOnCommit(IndexNodeParentScope parentScope) {
lockParentAndReleaseOnCommit(parentScope.nodeScope(), parentScope.parentCode());
}
void lockParentAndReleaseOnCommit(IndexNodeScope nodeScope, String parentCode) {
BizAssertions.assertTrue(TransactionSynchronizationManager.isActualTransactionActive(), "必须和事务搭配使用");
if (StringUtils.isNotBlank(parentCode)) {
indexNodeDao.getNodeForUpdateOrThrow(parentCode);
BizAssertions.assertTrue(TransactionSynchronizationManager.isActualTransactionActive(), "必须和事务搭配使用");
if (StringUtils.isNotBlank(parentScope.parentCode())) {
indexNodeDao.getForUpdateOrThrow(parentScope.parentCode());
return;
}
IndexNodeScope nodeScope = parentScope.nodeScope();
docLockDao.lockAndReleaseOnCommit(idbuilder() //
.append("INDEX_NODE") //
.append(nodeScope.context()) //

View File

@ -7,8 +7,8 @@ import java.util.Collections;
import java.util.List;
import cn.axzo.basics.common.BeanMapper;
import cn.axzo.nanopart.doc.api.enums.IndexNodeType;
import cn.axzo.nanopart.doc.api.domain.IndexNodeInfo;
import cn.axzo.nanopart.doc.api.enums.IndexNodeType;
import cn.axzo.nanopart.doc.entity.IndexNode;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
@ -37,4 +37,11 @@ public class IndexNodes {
return Collections.emptyList();
return BeanMapper.copyList(indexNodes, IndexNodeInfo.class);
}
public IndexNode findOrNull(String code) {
return indexNodes.stream() //
.filter(node -> node.getCode().equals(code)) //
.findFirst() //
.orElse(null);
}
}

View File

@ -32,12 +32,23 @@ public class IndexNodeRenameOssFileHandler implements EventHandler, Initializing
public void onEvent(Event event, EventConsumer.Context context) {
RenameIndexNodeOssFileMessage message = event.normalizedData(RenameIndexNodeOssFileMessage.class);
log.info("receive rename index node oss file message: {}", message);
IndexNode indexNode = indexNodeDao.findNodeOrNull(message.getIndexNodeCode());
if (indexNode == null)
IndexNode indexNode = indexNodeDao.findOrNull(message.getIndexNodeCode());
if (indexNode == null) {
log.warn("index node not found: {}", message.getIndexNodeCode());
return;
}
String ossFileKey = indexNode.getOrCreateAttributes().getOrCreateFileAttributes().getOssFileKey();
if (StringUtils.isNotBlank(ossFileKey))
if (StringUtils.isBlank(ossFileKey)) {
log.warn("try to rename index node oss file ({}) but oss file key not found", indexNode.getCode());
return;
}
try {
ossClient.rename(ossFileKey, indexNode.getName());
}
catch (Exception e) {
log.error("删除oss file失败", e);
throw e;
}
}
@Override

View File

@ -33,6 +33,7 @@ public class OssFileDeleteHandler implements EventHandler, InitializingBean {
}
catch (Exception e) {
log.error("删除oss file失败", e);
throw e;
}
}

View File

@ -3,13 +3,12 @@ package cn.axzo.nanopart.doc.file.templatedb;
import java.util.List;
import cn.axzo.nanopart.doc.entity.IndexNode;
import org.springframework.web.bind.annotation.RestController;
import cn.axzo.nanopart.doc.api.domain.IndexNodeInfo;
import cn.axzo.nanopart.doc.api.index.request.CopyNodeRequest;
import cn.axzo.nanopart.doc.api.index.request.DeleteNodeRequest;
import cn.axzo.nanopart.doc.api.index.request.IndexNodePageSearchRequest;
import cn.axzo.nanopart.doc.api.index.request.IndexNodeSearchRequest;
import cn.axzo.nanopart.doc.api.index.request.MoveNodeRequest;
import cn.axzo.nanopart.doc.api.index.request.RenameNodeRequest;
import cn.axzo.nanopart.doc.api.templatedb.TemplateDatabaseApi;
@ -20,6 +19,7 @@ import cn.axzo.nanopart.doc.api.templatedb.reqeust.TemplateDatabaseGetDatabaseOr
import cn.axzo.nanopart.doc.api.templatedb.reqeust.TemplateDatabaseUpdateDatabaseOrDirInfoRequest;
import cn.axzo.nanopart.doc.api.templatedb.reqeust.TemplateDatabaseUploadFileRequest;
import cn.axzo.nanopart.doc.api.templatedb.response.TemplateDatabaseGetDatabaseOrDirInfoResponse;
import cn.axzo.nanopart.doc.entity.IndexNode;
import cn.axzo.nanopart.doc.file.index.IndexManager;
import cn.azxo.framework.common.model.CommonResponse;
import cn.azxo.framework.common.model.Page;
@ -36,6 +36,7 @@ public class TemplateDatabaseApiController implements TemplateDatabaseApi {
private final TemplateDatabaseManager templateDatabaseManager;
private final IndexManager indexManager;
private final TemplateDatabaseQueryService templateDatabaseQueryService;
@Override
public CommonResponse<String> createDatabase(TemplateDatabaseCreateDatabaseRequest request) {
@ -81,7 +82,8 @@ public class TemplateDatabaseApiController implements TemplateDatabaseApi {
@Override
public CommonResponse<Void> delete(DeleteNodeRequest request) {
return null;
templateDatabaseManager.delete(request);
return CommonResponse.success();
}
@Override
@ -90,19 +92,20 @@ public class TemplateDatabaseApiController implements TemplateDatabaseApi {
}
@Override
public CommonResponse<Page<IndexNodeInfo>> search(IndexNodePageSearchRequest request) {
public CommonResponse<Page<IndexNodeInfo>> search(IndexNodeSearchRequest request) {
return null;
}
@Override
public CommonResponse<TemplateDatabaseGetDatabaseOrDirInfoResponse> getDatabaseOrDirInfo(
TemplateDatabaseGetDatabaseOrDirInfoRequest request) {
return null;
return CommonResponse.success(templateDatabaseQueryService.getDatabaseOrDirInfo(request));
}
@Override
public CommonResponse<Void> updateDatabaseOrDirInfo(TemplateDatabaseUpdateDatabaseOrDirInfoRequest request) {
return null;
templateDatabaseManager.updateDatabaseOrDirInfo(request);
return CommonResponse.success();
}
}

View File

@ -1,19 +1,25 @@
package cn.axzo.nanopart.doc.file.templatedb;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSON;
import cn.axzo.nanopart.doc.api.domain.OssFile;
import cn.axzo.nanopart.doc.api.enums.DatabaseScope;
import cn.axzo.nanopart.doc.api.enums.IndexNodeType;
import cn.axzo.nanopart.doc.api.index.request.DeleteNodeRequest;
import cn.axzo.nanopart.doc.api.templatedb.reqeust.TemplateDatabaseCreateDatabaseRequest;
import cn.axzo.nanopart.doc.api.templatedb.reqeust.TemplateDatabaseCreateDirRequest;
import cn.axzo.nanopart.doc.api.templatedb.reqeust.TemplateDatabaseCreateFileRequest;
import cn.axzo.nanopart.doc.api.templatedb.reqeust.TemplateDatabaseUpdateDatabaseOrDirInfoRequest;
import cn.axzo.nanopart.doc.api.templatedb.reqeust.TemplateDatabaseUploadFileRequest;
import cn.axzo.nanopart.doc.api.util.BizAssertions;
import cn.axzo.nanopart.doc.dao.TemplateDatabaseDao;
import cn.axzo.nanopart.doc.entity.IndexNode;
import cn.axzo.nanopart.doc.entity.TemplateDatabase;
import cn.axzo.nanopart.doc.file.index.IndexManager;
import cn.axzo.nanopart.doc.file.index.domain.IndexNodes;
import cn.axzo.nanopart.doc.utils.BizTransactional;
import lombok.RequiredArgsConstructor;
@ -29,12 +35,12 @@ public class TemplateDatabaseManager {
@BizTransactional
public String createDatabase(TemplateDatabaseCreateDatabaseRequest request) {
if (request.getScope() == DatabaseScope.PROJECT_DATABASE)
BizAssertions.assertFalse(request.getAccessOption().isNone(), "项目数据库必须指定协作模式");
request.setParentCode("");
IndexNode indexNode = indexManager.createDatabase(request);
TemplateDatabase db = new TemplateDatabase();
db.setCode(indexNode.getCode());
db.setScope(request.getScope());
db.setCoopType(request.getCoopType());
templateDatabaseDao.save(db);
return indexNode.getCode();
}
@ -52,4 +58,38 @@ public class TemplateDatabaseManager {
return indexManager.uploadFile(request, request.getOssFile()).getCode();
}
@BizTransactional
public void delete(DeleteNodeRequest request) {
IndexNodes deletedNodes = IndexNodes.wrap(indexManager.delete(request.getCode()));
templateDatabaseDao.stateDeleteByCodes(deletedNodes.collectCodes(IndexNodeType.DATABASE));
}
public TemplateDatabase getOrThrow(String code) {
TemplateDatabase db = findOrNull(code);
BizAssertions.assertNotNull(db, "找不到对应的资料库模版");
return db;
}
public TemplateDatabase findOrNull(String code) {
return templateDatabaseDao.findOrNull(code);
}
@BizTransactional
public void updateDatabaseOrDirInfo(TemplateDatabaseUpdateDatabaseOrDirInfoRequest request) {
String name = request.getDatabaseOrDirInfo() == null ? null : request.getDatabaseOrDirInfo().getName();
if (StringUtils.isNotBlank(name))
indexManager.rename(request.getCode(), name);
indexManager.updateBizInfo(request.getCode(),
request.getDatabaseOrDirInfo() == null ? null : request.getDatabaseOrDirInfo().getBizCode(),
request.getDatabaseOrDirInfo() == null ? null : request.getDatabaseOrDirInfo().getDescription(),
request.getDatabaseOrDirInfo() == null ? null : request.getDatabaseOrDirInfo().getIcon());
templateDatabaseDao.lambdaUpdate() //
.eq(TemplateDatabase::getCode, request.getCode()) //
.set(request.getFeeConfig() != null, TemplateDatabase::getFeeConfig,
JSON.toJSONString(request.getFeeConfig())) //
.set(request.getAccessConfig() != null, TemplateDatabase::getAccessConfig,
JSON.toJSONString(request.getAccessConfig())) //
.update();
}
}

View File

@ -0,0 +1,48 @@
package cn.axzo.nanopart.doc.file.templatedb;
import org.springframework.stereotype.Service;
import cn.axzo.nanopart.doc.api.templatedb.reqeust.TemplateDatabaseGetDatabaseOrDirInfoRequest;
import cn.axzo.nanopart.doc.api.templatedb.response.TemplateDatabaseGetDatabaseOrDirInfoResponse;
import cn.axzo.nanopart.doc.dao.TemplateDatabaseDao;
import cn.axzo.nanopart.doc.entity.IndexNode;
import cn.axzo.nanopart.doc.entity.TemplateDatabase;
import cn.axzo.nanopart.doc.file.index.IndexManager;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
/**
* @author yanglin
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class TemplateDatabaseQueryService {
private final IndexManager indexManager;;
private final TemplateDatabaseDao templateDatabaseDao;
public TemplateDatabaseGetDatabaseOrDirInfoResponse getDatabaseOrDirInfo(
TemplateDatabaseGetDatabaseOrDirInfoRequest request) {
IndexNode indexNode = indexManager.findOrNull(request.getCode());
if (indexNode == null)
return null;
TemplateDatabaseGetDatabaseOrDirInfoResponse response = new TemplateDatabaseGetDatabaseOrDirInfoResponse();
response.setNodeType(indexNode.getNodeType());
response.getDatabaseOrDirInfo().setName(indexNode.getName());
response.getDatabaseOrDirInfo().setBizCode(indexNode.getBizCode());
response.getDatabaseOrDirInfo().setDescription(indexNode.getDescription());
response.getDatabaseOrDirInfo().setIcon(indexNode.getIcon());
if (indexNode.isDatabase()) {
TemplateDatabase template = templateDatabaseDao.findOrNull(request.getCode());
if (template != null) {
response.setFeeConfig(template.getFeeConfig());
response.setAccessConfig(template.getAccessConfig());
response.getDatabaseOrDirInfo().setScope(template.getScope());
}
}
return response;
}
}

View File

@ -0,0 +1,117 @@
package cn.axzo.nanopart.doc.utils;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Supplier;
import cn.axzo.apollo.core.web.Result;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.framework.domain.ServiceException;
import cn.axzo.framework.domain.web.result.ApiListResult;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.azxo.framework.common.model.CommonResponse;
import cn.hutool.core.date.StopWatch;
import cn.hutool.core.lang.Assert;
import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
/**
* 外部rpc接口 返回 CommonResponse
* @author tanjie@axzo.cn
* @date 2022/5/23 11:08
*/
@Slf4j
public class RpcExternalUtil {
/**
* 常用的RPC请求返回值解析如果 被请求方 返回非200会抛出异常
*
*/
public static <T> T rpcProcessor(Supplier<CommonResponse<T>> supplier, String operationType, Object... param) {
return rpcProcessorMayThrow(supplier, operationType, commonResponse -> {
throw new ServiceException(commonResponse.getMsg());
}, param);
}
public static <T> T rpcApolloProcessor(Supplier<Result<T>> supplier, String operationType, Object... param) {
log.info(operationType + "-Param: " + JSONUtil.toJsonStr(param));
Result<T> result = printLatency(supplier, operationType);
log.info(operationType + "-Result: " + JSONUtil.toJsonStr(result));
Assert.notNull(result, "服务调用异常");
Assert.isTrue(result.getCode() == 200, "服务调用异常:" + result.getMsg());
return result.getData();
}
public static <T> T rpcApiResultProcessor(Supplier<ApiResult<T>> supplier, String operationType, Object... param) {
log.info(operationType + "-Param: " + JSONUtil.toJsonStr(param));
ApiResult<T> result = printLatency(supplier, operationType);
log.info(operationType + "-Result: " + JSONUtil.toJsonStr(result));
Assert.notNull(result, "服务调用异常");
Assert.isTrue(result.getCode() == 200, "服务调用异常:" + result.getMsg());
return result.getData();
}
/**
* 常用的RPC请求返回值解析如果 被请求方 返回非200会抛出异常
*
* @param supplier ApiListResult类型的RPC接口
* @param operationType 接口方法描述
* @param param 接口入参
* @return 接口返回值
*/
public static <T> List<T> rpcApiListResultProcessor(Supplier<ApiListResult<T>> supplier, String operationType,
Object... param) {
log.info(operationType + "-Param: " + JSONUtil.toJsonStr(param));
ApiListResult<T> result = printLatency(supplier, operationType);
log.info(operationType + "-Result: " + JSONUtil.toJsonStr(result));
Assert.notNull(result, "服务调用异常");
Assert.isTrue(result.isSuccess(), "服务调用异常:" + result.getMsg());
return result.getData();
}
public static <T> T rpcProcessorMayThrow(Supplier<CommonResponse<T>> supplier, String operationType,
Consumer<CommonResponse<T>> throwConsumer, Object... param) {
AssertUtil.notNull(throwConsumer, "自定义的异常处理不可为空");
log.info(operationType + "-Param: " + JSONUtil.toJsonStr(param));
CommonResponse<T> result = printLatency(supplier, operationType);
log.info(operationType + "-Result: " + JSONUtil.toJsonStr(result));
Assert.notNull(result, "服务调用异常");
// 200自定义处理
if (HttpStatus.HTTP_OK != result.getCode()) {
throwConsumer.accept(result);
}
return result.getData();
}
public static <R> R printLatency(Supplier<R> function, String optType) {
StopWatch stopWatch = new StopWatch(optType);
stopWatch.start(optType);
R r = function.get();
stopWatch.stop();
log.info(stopWatch.shortSummary(TimeUnit.MILLISECONDS));
return r;
}
public static <T> T rpcProfileProcessor(Supplier<CommonResponse<T>> supplier, String operationType,
Object... param) {
log.info(operationType + "-Param: " + JSONUtil.toJsonStr(param));
StopWatch stopWatch = new StopWatch(operationType);
stopWatch.start(operationType);
CommonResponse<T> result = supplier.get();
stopWatch.stop();
log.info("-Result: " + JSONUtil.toJsonStr(result));
log.info(stopWatch.shortSummary(TimeUnit.MILLISECONDS));
Assert.notNull(result, "服务调用异常");
// 200自定义处理
if (HttpStatus.HTTP_OK != result.getCode() && 404 != result.getCode()) {
throw new ServiceException(result.getMsg());
}
return result.getData();
}
}