feature: synchronize documents asynchronously (#97)

* feat: update jooq model

* feat: add project sync task

* feat: update frontend resources
This commit is contained in:
vran
2022-04-16 13:44:06 +08:00
committed by GitHub
parent d257a65664
commit 3e70346bb3
69 changed files with 1287 additions and 175 deletions

View File

@@ -11,6 +11,7 @@ public enum DomainErrors implements DatabasirErrors {
REFRESH_TOKEN_EXPIRED("X_0001", "refresh token expired"),
INVALID_REFRESH_TOKEN_OPERATION("X_0002", "invalid refresh token operation"),
NETWORK_ERROR("X_0003", "网络似乎不稳定,请稍后再试"),
INVALID_ACCESS_TOKEN("X_0004", "无效的 access token"),
NOT_SUPPORT_DATABASE_TYPE("A_10000", "不支持的数据库类型, 请检查项目配置"),
PROJECT_NOT_FOUND("A_10001", "项目不存在"),

View File

@@ -43,6 +43,7 @@ public class LoginService {
.orElseThrow(DomainErrors.INVALID_REFRESH_TOKEN_OPERATION::exception);
// refresh-token 已过期
if (login.getRefreshTokenExpireAt().isBefore(LocalDateTime.now())) {
log.warn("refresh token expired, {} ", request);
throw DomainErrors.REFRESH_TOKEN_EXPIRED.exception();
}
// access-token 未过期(允许一分钟的误差)就开始刷新有可能是 refresh-token 泄露了,删除 refresh-token

View File

@@ -0,0 +1,17 @@
package com.databasir.core.domain.project.converter;
import com.databasir.core.domain.project.data.task.ProjectSimpleTaskResponse;
import com.databasir.dao.tables.pojos.ProjectSyncTaskPojo;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import java.util.List;
@Mapper(componentModel = "spring")
public interface ProjectSimpleTaskResponseConverter {
List<ProjectSimpleTaskResponse> of(List<ProjectSyncTaskPojo> pojos);
@Mapping(target = "taskId", source = "id")
ProjectSimpleTaskResponse of(ProjectSyncTaskPojo pojo);
}

View File

@@ -0,0 +1,14 @@
package com.databasir.core.domain.project.data.task;
import com.databasir.dao.enums.ProjectSyncTaskStatus;
import lombok.Data;
@Data
public class ProjectSimpleTaskResponse {
private Integer taskId;
private ProjectSyncTaskStatus status;
private String result;
}

View File

@@ -0,0 +1,29 @@
package com.databasir.core.domain.project.data.task;
import com.databasir.dao.Tables;
import com.databasir.dao.enums.ProjectSyncTaskStatus;
import lombok.Data;
import org.jooq.Condition;
import java.util.Collection;
import java.util.Collections;
@Data
public class ProjectTaskListCondition {
private Collection<Integer> taskIdIn = Collections.emptyList();
private Collection<ProjectSyncTaskStatus> taskStatusIn = Collections.emptyList();
public Condition toCondition(Integer projectId) {
Condition condition = Tables.PROJECT_SYNC_TASK.PROJECT_ID.eq(projectId);
if (taskIdIn != null && !taskIdIn.isEmpty()) {
condition = condition.and(Tables.PROJECT_SYNC_TASK.ID.in(taskIdIn));
}
if (taskStatusIn != null && !taskStatusIn.isEmpty()) {
condition = condition.and(Tables.PROJECT_SYNC_TASK.STATUS.in(taskStatusIn));
}
// ignore system user task
return condition.and(Tables.PROJECT_SYNC_TASK.USER_ID.ne(-1));
}
}

View File

@@ -5,11 +5,16 @@ import com.databasir.core.domain.DomainErrors;
import com.databasir.core.domain.project.converter.DataSourcePojoConverter;
import com.databasir.core.domain.project.converter.ProjectPojoConverter;
import com.databasir.core.domain.project.converter.ProjectResponseConverter;
import com.databasir.core.domain.project.converter.ProjectSimpleTaskResponseConverter;
import com.databasir.core.domain.project.data.*;
import com.databasir.core.domain.project.data.task.ProjectSimpleTaskResponse;
import com.databasir.core.domain.project.data.task.ProjectTaskListCondition;
import com.databasir.core.infrastructure.connection.DatabaseConnectionService;
import com.databasir.dao.enums.ProjectSyncTaskStatus;
import com.databasir.dao.impl.*;
import com.databasir.dao.tables.pojos.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
@@ -23,8 +28,11 @@ import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
@Slf4j
public class ProjectService {
private final DatabaseConnectionService databaseConnectionService;
private final ProjectDao projectDao;
private final ProjectSyncRuleDao projectSyncRuleDao;
@@ -37,13 +45,15 @@ public class ProjectService {
private final UserFavoriteProjectDao userFavoriteProjectDao;
private final ProjectSyncTaskDao projectSyncTaskDao;
private final DataSourcePojoConverter dataSourcePojoConverter;
private final ProjectPojoConverter projectPojoConverter;
private final ProjectResponseConverter projectResponseConverter;
private final DatabaseConnectionService databaseConnectionService;
private final ProjectSimpleTaskResponseConverter projectSimpleTaskResponseConverter;
public ProjectDetailResponse getOne(Integer id) {
return projectDao.selectOptionalById(id)
@@ -175,4 +185,26 @@ public class ProjectService {
properties);
}
@Transactional
public Optional<Integer> createSyncTask(Integer projectId, Integer userId, boolean ignoreIfExists) {
if (!projectDao.existsById(projectId)) {
log.info("create sync task failed, because project not exists, projectId={}", projectId);
return Optional.empty();
}
var validTaskStatus = List.of(ProjectSyncTaskStatus.NEW, ProjectSyncTaskStatus.RUNNING);
if (ignoreIfExists && projectSyncTaskDao.existsByProjectId(projectId, validTaskStatus)) {
log.info("create sync task failed, it's already exists, projectId={}", projectId);
return Optional.empty();
}
ProjectSyncTaskPojo projectSyncTask = new ProjectSyncTaskPojo();
projectSyncTask.setProjectId(projectId);
projectSyncTask.setStatus(ProjectSyncTaskStatus.NEW);
projectSyncTask.setUserId(userId);
return Optional.of(projectSyncTaskDao.insertAndReturnId(projectSyncTask));
}
public List<ProjectSimpleTaskResponse> listManualTasks(Integer projectId, ProjectTaskListCondition condition) {
var tasks = projectSyncTaskDao.selectList(condition.toCondition(projectId));
return projectSimpleTaskResponseConverter.of(tasks);
}
}