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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
69 changed files with 1287 additions and 175 deletions

View File

@ -1,11 +1,13 @@
package com.databasir.api;
import com.databasir.api.common.LoginUserContext;
import com.databasir.common.JsonData;
import com.databasir.core.diff.data.RootDiff;
import com.databasir.core.domain.document.data.*;
import com.databasir.core.domain.document.generator.DocumentFileType;
import com.databasir.core.domain.document.service.DocumentService;
import com.databasir.core.domain.log.annotation.Operation;
import com.databasir.core.domain.project.service.ProjectService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
@ -20,6 +22,7 @@ import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBo
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Optional;
import static org.springframework.data.domain.Sort.Direction.DESC;
@ -30,11 +33,14 @@ public class DocumentController {
private final DocumentService documentService;
private final ProjectService projectService;
@PostMapping(Routes.Document.SYNC_ONE)
@Operation(module = Operation.Modules.PROJECT, name = "文档同步", involvedProjectId = "#projectId")
public JsonData<Void> sync(@PathVariable Integer projectId) {
documentService.syncByProjectId(projectId);
return JsonData.ok();
public JsonData<Integer> sync(@PathVariable Integer projectId) {
Integer userId = LoginUserContext.getLoginUserId();
Optional<Integer> taskIdOpt = projectService.createSyncTask(projectId, userId, false);
return JsonData.ok(taskIdOpt);
}
@GetMapping(Routes.Document.DIFF)
@ -56,14 +62,14 @@ public class DocumentController {
public JsonData<Page<DatabaseDocumentVersionResponse>> getVersionsByProjectId(@PathVariable Integer projectId,
@PageableDefault(sort = "id",
direction = DESC)
Pageable page) {
Pageable page) {
return JsonData.ok(documentService.getVersionsByProjectId(projectId, page));
}
@GetMapping(Routes.Document.EXPORT)
public ResponseEntity<StreamingResponseBody> getDocumentFiles(@PathVariable Integer projectId,
@RequestParam(required = false)
Long version,
Long version,
@RequestParam DocumentFileType fileType) {
HttpHeaders headers = new HttpHeaders();
String fileName = "project[" + projectId + "]." + fileType.getFileExtension();
@ -79,7 +85,7 @@ public class DocumentController {
@GetMapping(Routes.Document.GET_SIMPLE_ONE)
public JsonData<DatabaseDocumentSimpleResponse> getSimpleByProjectId(@PathVariable Integer projectId,
@RequestParam(required = false)
Long version) {
Long version) {
return JsonData.ok(documentService.getSimpleOneByProjectId(projectId, version));
}

View File

@ -5,6 +5,8 @@ import com.databasir.api.validator.CronExpressionValidator;
import com.databasir.common.JsonData;
import com.databasir.core.domain.log.annotation.Operation;
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.domain.project.service.ProjectService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
@ -17,6 +19,7 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
@RestController
@RequiredArgsConstructor
@ -71,7 +74,7 @@ public class ProjectController {
@GetMapping(Routes.GroupProject.LIST)
public JsonData<Page<ProjectSimpleResponse>> list(@PageableDefault(sort = "id", direction = Sort.Direction.DESC)
Pageable page,
Pageable page,
ProjectListCondition condition) {
DatabasirUserDetails user = (DatabasirUserDetails) SecurityContextHolder.getContext()
.getAuthentication()
@ -85,4 +88,10 @@ public class ProjectController {
projectService.testConnection(request);
return JsonData.ok();
}
@PostMapping(Routes.GroupProject.LIST_MANUAL_TASKS)
public JsonData<List<ProjectSimpleTaskResponse>> listManualTasks(@PathVariable Integer projectId,
@RequestBody ProjectTaskListCondition condition) {
return JsonData.ok(projectService.listManualTasks(projectId, condition));
}
}

View File

@ -70,6 +70,8 @@ public interface Routes {
String DELETE = BASE + "/groups/{groupId}/projects/{projectId}";
String TEST_CONNECTION = BASE + "/projects/test_connection";
String LIST_MANUAL_TASKS = BASE + "/projects/{projectId}/list_manual_tasks";
}
interface Document {

View File

@ -25,11 +25,11 @@ public class DatabasirAuthenticationEntryPoint implements AuthenticationEntryPoi
public void commence(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
log.warn("验证未通过. 提示信息 - {} - {} {}", request.getRequestURI(),
log.warn("验证未通过. 提示信息 - {} - {} - {}", request.getRequestURI(),
authException.getClass().getName(),
authException.getMessage());
DomainErrors err = DomainErrors.INVALID_REFRESH_TOKEN_OPERATION;
DomainErrors err = DomainErrors.INVALID_ACCESS_TOKEN;
JsonData<Void> data = JsonData.error(err.getErrCode(), err.getErrMessage());
String jsonString = objectMapper.writeValueAsString(data);
response.setStatus(HttpStatus.UNAUTHORIZED.value());

View File

@ -1,61 +0,0 @@
package com.databasir.job;
import com.databasir.common.JsonData;
import com.databasir.core.domain.document.service.DocumentService;
import com.databasir.core.domain.log.data.OperationLogRequest;
import com.databasir.core.domain.log.service.OperationLogService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
@RequiredArgsConstructor
@Slf4j
public class ProjectDocumentAutoSyncJob implements Job {
private final OperationLogService operationLogService;
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
JobDataMap dataMap = context.getMergedJobDataMap();
log.info("start sync project document: " + dataMap.toString());
DocumentService documentService = (DocumentService) dataMap.get("documentService");
Integer projectId = dataMap.getInt("projectId");
try {
documentService.syncByProjectId(projectId);
OperationLogRequest request = OperationLogRequest.builder()
.isSuccess(true)
.operatorNickname("system")
.operatorUsername("system")
.operatorUserId(-1)
.operationName("文档自动同步")
.operationCode("autoSyncDocumentation")
.operationModule("project")
.operationResponse(JsonData.ok())
.isSuccess(true)
.involvedProjectId(projectId)
.build();
operationLogService.save(request);
log.info("sync project document {} over....", projectId);
} catch (Exception e) {
OperationLogRequest request = OperationLogRequest.builder()
.isSuccess(true)
.operatorNickname("system")
.operatorUsername("system")
.operatorUserId(-1)
.operationName("文档自动同步")
.operationCode("autoSyncDocumentation")
.operationModule("project")
.operationResponse(JsonData.error("-1", e.getMessage()))
.isSuccess(false)
.involvedProjectId(projectId)
.build();
operationLogService.save(request);
throw e;
}
}
}

View File

@ -0,0 +1,24 @@
package com.databasir.job;
import com.databasir.core.domain.project.service.ProjectService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
@RequiredArgsConstructor
@Slf4j
public class ProjectSyncJob implements Job {
private final ProjectService projectService;
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
JobDataMap dataMap = context.getMergedJobDataMap();
Integer projectId = dataMap.getInt("projectId");
projectService.createSyncTask(projectId, -1, true);
}
}

View File

@ -16,10 +16,13 @@ import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* 用于启用 / 停用项目同步任务的调度器
*/
@Component
@RequiredArgsConstructor
@Slf4j
public class ProjectDocumentAutoSyncTriggerJob {
public class ProjectSyncJobScheduler {
private static final String JOB_IDENTITY_PATTERN = "JOB_PROJECT[%s]";
@ -141,7 +144,7 @@ public class ProjectDocumentAutoSyncTriggerJob {
dataMap.put("cron", rule.getAutoSyncCron());
dataMap.put("documentService", documentService);
JobDetail job = JobBuilder.newJob()
.ofType(ProjectDocumentAutoSyncJob.class)
.ofType(ProjectSyncJob.class)
.withIdentity(jobKey(projectId))
.withDescription("auto sync project document")
.usingJobData(dataMap)

View File

@ -0,0 +1,100 @@
package com.databasir.job;
import com.databasir.common.JsonData;
import com.databasir.core.domain.document.service.DocumentService;
import com.databasir.core.domain.log.data.OperationLogRequest;
import com.databasir.core.domain.log.service.OperationLogService;
import com.databasir.dao.enums.ProjectSyncTaskStatus;
import com.databasir.dao.impl.ProjectSyncTaskDao;
import com.databasir.dao.impl.UserDao;
import com.databasir.dao.tables.pojos.UserPojo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import java.util.Objects;
@Component
@RequiredArgsConstructor
@Slf4j
public class ProjectSyncTaskScheduler {
private final DocumentService documentService;
private final OperationLogService operationLogService;
private final UserDao userDao;
private final ProjectSyncTaskDao projectSyncTaskDao;
private final ThreadPoolTaskExecutor projectSyncTaskThreadPoolTaskExecutor;
/**
* 每隔 5s 执行一次
*/
@Scheduled(fixedRate = 5000L)
public void startSyncTask() {
final int size = 10;
projectSyncTaskDao.listNewTasks(size).forEach(task -> {
projectSyncTaskThreadPoolTaskExecutor.execute(() -> {
Integer taskId = task.getId();
Integer projectId = task.getProjectId();
Integer userId = task.getUserId();
sync(taskId, projectId, userId);
});
});
}
private void sync(Integer taskId, Integer projectId, Integer userId) {
try {
updateSyncTaskStatus(taskId, ProjectSyncTaskStatus.RUNNING, "running");
documentService.syncByProjectId(projectId);
updateSyncTaskStatus(taskId, ProjectSyncTaskStatus.FINISHED, "ok");
saveOperationLog(projectId, userId, null);
} catch (Exception e) {
updateSyncTaskStatus(taskId, ProjectSyncTaskStatus.FAILED, e.getMessage());
saveOperationLog(projectId, userId, e);
throw e;
}
}
private void updateSyncTaskStatus(Integer taskId, ProjectSyncTaskStatus status, String result) {
projectSyncTaskDao.updateStatusAndResultById(taskId, status, result);
}
private void saveOperationLog(Integer projectId, Integer userId, Exception ex) {
String operatorNickName;
String operatorUsername;
String operationName;
if (Objects.equals(-1, userId)) {
operatorNickName = "system";
operatorUsername = "system";
operationName = "文档定时同步";
} else {
UserPojo user = userDao.selectById(userId);
operatorNickName = user.getNickname();
operatorUsername = user.getUsername();
operationName = "文档手动同步";
}
JsonData response;
if (ex == null) {
response = JsonData.ok();
} else {
response = JsonData.error("-1", ex.getMessage());
}
OperationLogRequest operationLog = OperationLogRequest.builder()
.operatorNickname(operatorNickName)
.operatorUsername(operatorUsername)
.operatorUserId(userId)
.operationName(operationName)
.operationCode("autoSyncDocumentation")
.operationModule("project")
.operationResponse(response)
.isSuccess(ex == null)
.involvedProjectId(projectId)
.build();
operationLogService.save(operationLog);
}
}

View File

@ -0,0 +1,27 @@
package com.databasir.job.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
public class ProjectSyncTaskThreadPoolConfig {
@Bean
public ThreadPoolTaskExecutor projectSyncTaskThreadPoolTaskExecutor() {
final int maxCorePoolSize = 12;
final int maxPoolSize = 32;
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
int availableProcessorCount = Runtime.getRuntime().availableProcessors() + 2;
int corePoolSize = Math.min(maxCorePoolSize, availableProcessorCount);
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setAllowCoreThreadTimeOut(true);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
return executor;
}
}

View File

@ -0,0 +1,20 @@
@-webkit-keyframes running-line{to{stroke-dashoffset:-1000}}@keyframes running-line{to{stroke-dashoffset:-1000}}.text{font-size:14px;line-height:1.3rem}.item{margin-top:10px;margin-right:40px}.remark-card{margin-bottom:30px}.remark-header{display:flex;justify-content:space-between;align-items:center}.remark-header .remark-user{color:#6d6d6d}.remark-header .remark-time{color:#6d6d6d;font-size:.8rem;margin-left:10px}.remark-content{white-space:pre-wrap;text-align:left}.badge-item{margin-top:18px;margin-bottom:6px}.removed-item{background-color:#fef0f0!important;color:#f56c6c}.added-item{background-color:#f0f9eb!important;color:#67c23a}.modified-item{background-color:#fdf6ec!important;color:#e6a23c}.modified-original-item{background-color:#fdf6ec!important;color:#a8abb2}.copy-button{color:#fff}.copy-button,.copy-button:hover{position:absolute;right:12px;top:12px}.copy-button:hover{color:#67c23a}.table-quote{padding-left:8px;margin:12px 0 6px 0;font-size:16px}pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px;min-height:100px}/*!
Theme: Agate
Author: (c) Taufik Nurrohman <hi@taufik-nurrohman.com>
Maintainer: @taufik-nurrohman
Updated: 2021-04-24
#333
#62c8f3
#7bd694
#888
#a2fca2
#ade5fc
#b8d8a2
#c6b4f0
#d36363
#fc9b9b
#fcc28c
#ffa
#fff
*/.hljs{background:#333;color:#fff}.hljs-doctag,.hljs-meta-keyword,.hljs-name,.hljs-strong{font-weight:700}.hljs-code,.hljs-emphasis{font-style:italic}.hljs-section,.hljs-tag{color:#62c8f3}.hljs-selector-class,.hljs-selector-id,.hljs-template-variable,.hljs-variable{color:#ade5fc}.hljs-meta-string,.hljs-string{color:#a2fca2}.hljs-attr,.hljs-quote,.hljs-selector-attr{color:#7bd694}.hljs-tag .hljs-attr{color:inherit}.hljs-attribute,.hljs-title,.hljs-type{color:#ffa}.hljs-number,.hljs-symbol{color:#d36363}.hljs-bullet,.hljs-template-tag{color:#b8d8a2}.hljs-built_in,.hljs-keyword,.hljs-literal,.hljs-selector-tag{color:#fcc28c}.hljs-code,.hljs-comment,.hljs-formula{color:#888}.hljs-link,.hljs-regexp,.hljs-selector-pseudo{color:#c6b4f0}.hljs-meta{color:#fc9b9b}.hljs-deletion{background:#fc9b9b;color:#333}.hljs-addition{background:#a2fca2;color:#333}.hljs-subst{color:#fff}.hljs a{color:inherit}.hljs a:focus,.hljs a:hover{color:inherit;text-decoration:underline}.hljs mark{background:#555;color:inherit}.span-ellipsis{width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;flex:1;display:inline-block;align-items:left;justify-content:space-between;font-size:14px;padding:8px}.doc-toc-aside{overflow-wrap:break-word;text-overflow:ellipsis;bottom:0;top:100px;position:fixed;overflow-y:hidden;overflow-x:hidden;max-width:var(--el-aside-width);width:var(--el-aside-width);border-width:0 1px 0 0;border-color:#ddd;border-style:solid}.doc-toc-aside:hover{overflow-y:auto;scrollbar-width:thin}.search-input{border-width:0 0 1px 0;border-style:solid;width:90%;min-height:33px}.search-input::-moz-placeholder{color:hsla(0,0%,71%,.808)}.search-input:-ms-input-placeholder{color:hsla(0,0%,71%,.808)}.search-input::placeholder{color:hsla(0,0%,71%,.808)}.search-input:focus{outline:none;border-color:#000}

View File

@ -1 +1 @@
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>databasir</title><script defer="defer" type="module" src="/js/chunk-vendors.e6af1896.js"></script><script defer="defer" type="module" src="/js/app.87998218.js"></script><link href="/css/chunk-vendors.8e1003a6.css" rel="stylesheet"><link href="/css/app.15b40a89.css" rel="stylesheet"><script defer="defer" src="/js/chunk-vendors-legacy.ca57c54b.js" nomodule></script><script defer="defer" src="/js/app-legacy.4d38b7d6.js" nomodule></script></head><body><noscript><strong>We're sorry but databasir doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>databasir</title><script defer="defer" type="module" src="/js/chunk-vendors.787360f3.js"></script><script defer="defer" type="module" src="/js/app.e1b7b172.js"></script><link href="/css/chunk-vendors.8e1003a6.css" rel="stylesheet"><link href="/css/app.15b40a89.css" rel="stylesheet"><script defer="defer" src="/js/chunk-vendors-legacy.405c78b5.js" nomodule></script><script defer="defer" src="/js/app-legacy.43293c26.js" nomodule></script></head><body><noscript><strong>We're sorry but databasir doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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);
}
}

View File

@ -78,6 +78,12 @@ jooq {
includeExpression = 'mock_data_rule.mock_data_type'
includeTypes = '.*'
}
forcedType {
userType = 'com.databasir.dao.enums.ProjectSyncTaskStatus'
converter = 'com.databasir.dao.converter.ProjectSyncTaskStatusConverter'
includeExpression = 'project_sync_task.status'
includeTypes = '.*'
}
}
}
generate {

View File

@ -18,6 +18,7 @@ import com.databasir.dao.tables.OauthApp;
import com.databasir.dao.tables.OperationLog;
import com.databasir.dao.tables.Project;
import com.databasir.dao.tables.ProjectSyncRule;
import com.databasir.dao.tables.ProjectSyncTask;
import com.databasir.dao.tables.SysKey;
import com.databasir.dao.tables.SysMail;
import com.databasir.dao.tables.TableColumnDocument;
@ -120,6 +121,11 @@ public class Databasir extends SchemaImpl {
*/
public final ProjectSyncRule PROJECT_SYNC_RULE = ProjectSyncRule.PROJECT_SYNC_RULE;
/**
* The table <code>databasir.project_sync_task</code>.
*/
public final ProjectSyncTask PROJECT_SYNC_TASK = ProjectSyncTask.PROJECT_SYNC_TASK;
/**
* The table <code>databasir.sys_key</code>.
*/
@ -200,6 +206,7 @@ public class Databasir extends SchemaImpl {
OperationLog.OPERATION_LOG,
Project.PROJECT,
ProjectSyncRule.PROJECT_SYNC_RULE,
ProjectSyncTask.PROJECT_SYNC_TASK,
SysKey.SYS_KEY,
SysMail.SYS_MAIL,
TableColumnDocument.TABLE_COLUMN_DOCUMENT,

View File

@ -7,6 +7,7 @@ package com.databasir.dao;
import com.databasir.dao.tables.DataSourceProperty;
import com.databasir.dao.tables.DatabaseDocument;
import com.databasir.dao.tables.DocumentDiscussion;
import com.databasir.dao.tables.ProjectSyncTask;
import com.databasir.dao.tables.TableColumnDocument;
import com.databasir.dao.tables.TableDocument;
import com.databasir.dao.tables.TableForeignKeyDocument;
@ -37,8 +38,10 @@ public class Indexes {
public static final Index TABLE_TRIGGER_DOCUMENT_IDX_DATABASE_DOCUMENT_ID = Internal.createIndex(DSL.name("idx_database_document_id"), TableTriggerDocument.TABLE_TRIGGER_DOCUMENT, new OrderField[] { TableTriggerDocument.TABLE_TRIGGER_DOCUMENT.DATABASE_DOCUMENT_ID }, false);
public static final Index DATABASE_DOCUMENT_IDX_PROJECT_ID = Internal.createIndex(DSL.name("idx_project_id"), DatabaseDocument.DATABASE_DOCUMENT, new OrderField[] { DatabaseDocument.DATABASE_DOCUMENT.PROJECT_ID }, false);
public static final Index DOCUMENT_DISCUSSION_IDX_PROJECT_ID = Internal.createIndex(DSL.name("idx_project_id"), DocumentDiscussion.DOCUMENT_DISCUSSION, new OrderField[] { DocumentDiscussion.DOCUMENT_DISCUSSION.PROJECT_ID }, false);
public static final Index PROJECT_SYNC_TASK_IDX_PROJECT_ID = Internal.createIndex(DSL.name("idx_project_id"), ProjectSyncTask.PROJECT_SYNC_TASK, new OrderField[] { ProjectSyncTask.PROJECT_SYNC_TASK.PROJECT_ID }, false);
public static final Index TABLE_COLUMN_DOCUMENT_IDX_TABLE_DOCUMENT_ID = Internal.createIndex(DSL.name("idx_table_document_id"), TableColumnDocument.TABLE_COLUMN_DOCUMENT, new OrderField[] { TableColumnDocument.TABLE_COLUMN_DOCUMENT.TABLE_DOCUMENT_ID }, false);
public static final Index TABLE_FOREIGN_KEY_DOCUMENT_IDX_TABLE_DOCUMENT_ID = Internal.createIndex(DSL.name("idx_table_document_id"), TableForeignKeyDocument.TABLE_FOREIGN_KEY_DOCUMENT, new OrderField[] { TableForeignKeyDocument.TABLE_FOREIGN_KEY_DOCUMENT.TABLE_DOCUMENT_ID }, false);
public static final Index TABLE_INDEX_DOCUMENT_IDX_TABLE_DOCUMENT_ID = Internal.createIndex(DSL.name("idx_table_document_id"), TableIndexDocument.TABLE_INDEX_DOCUMENT, new OrderField[] { TableIndexDocument.TABLE_INDEX_DOCUMENT.TABLE_DOCUMENT_ID }, false);
public static final Index TABLE_TRIGGER_DOCUMENT_IDX_TABLE_DOCUMENT_ID = Internal.createIndex(DSL.name("idx_table_document_id"), TableTriggerDocument.TABLE_TRIGGER_DOCUMENT, new OrderField[] { TableTriggerDocument.TABLE_TRIGGER_DOCUMENT.TABLE_DOCUMENT_ID }, false);
public static final Index PROJECT_SYNC_TASK_IDX_USER_ID = Internal.createIndex(DSL.name("idx_user_id"), ProjectSyncTask.PROJECT_SYNC_TASK, new OrderField[] { ProjectSyncTask.PROJECT_SYNC_TASK.USER_ID }, false);
}

View File

@ -18,6 +18,7 @@ import com.databasir.dao.tables.OauthApp;
import com.databasir.dao.tables.OperationLog;
import com.databasir.dao.tables.Project;
import com.databasir.dao.tables.ProjectSyncRule;
import com.databasir.dao.tables.ProjectSyncTask;
import com.databasir.dao.tables.SysKey;
import com.databasir.dao.tables.SysMail;
import com.databasir.dao.tables.TableColumnDocument;
@ -42,6 +43,7 @@ import com.databasir.dao.tables.records.OauthAppRecord;
import com.databasir.dao.tables.records.OperationLogRecord;
import com.databasir.dao.tables.records.ProjectRecord;
import com.databasir.dao.tables.records.ProjectSyncRuleRecord;
import com.databasir.dao.tables.records.ProjectSyncTaskRecord;
import com.databasir.dao.tables.records.SysKeyRecord;
import com.databasir.dao.tables.records.SysMailRecord;
import com.databasir.dao.tables.records.TableColumnDocumentRecord;
@ -93,6 +95,7 @@ public class Keys {
public static final UniqueKey<ProjectRecord> KEY_PROJECT_UK_GROUP_ID_NAME_DELETED_TOKEN = Internal.createUniqueKey(Project.PROJECT, DSL.name("KEY_project_uk_group_id_name_deleted_token"), new TableField[] { Project.PROJECT.GROUP_ID, Project.PROJECT.NAME, Project.PROJECT.DELETED_TOKEN }, true);
public static final UniqueKey<ProjectSyncRuleRecord> KEY_PROJECT_SYNC_RULE_PRIMARY = Internal.createUniqueKey(ProjectSyncRule.PROJECT_SYNC_RULE, DSL.name("KEY_project_sync_rule_PRIMARY"), new TableField[] { ProjectSyncRule.PROJECT_SYNC_RULE.ID }, true);
public static final UniqueKey<ProjectSyncRuleRecord> KEY_PROJECT_SYNC_RULE_UK_PROJECT_ID = Internal.createUniqueKey(ProjectSyncRule.PROJECT_SYNC_RULE, DSL.name("KEY_project_sync_rule_uk_project_id"), new TableField[] { ProjectSyncRule.PROJECT_SYNC_RULE.PROJECT_ID }, true);
public static final UniqueKey<ProjectSyncTaskRecord> KEY_PROJECT_SYNC_TASK_PRIMARY = Internal.createUniqueKey(ProjectSyncTask.PROJECT_SYNC_TASK, DSL.name("KEY_project_sync_task_PRIMARY"), new TableField[] { ProjectSyncTask.PROJECT_SYNC_TASK.ID }, true);
public static final UniqueKey<SysKeyRecord> KEY_SYS_KEY_PRIMARY = Internal.createUniqueKey(SysKey.SYS_KEY, DSL.name("KEY_sys_key_PRIMARY"), new TableField[] { SysKey.SYS_KEY.ID }, true);
public static final UniqueKey<SysMailRecord> KEY_SYS_MAIL_PRIMARY = Internal.createUniqueKey(SysMail.SYS_MAIL, DSL.name("KEY_sys_mail_PRIMARY"), new TableField[] { SysMail.SYS_MAIL.ID }, true);
public static final UniqueKey<TableColumnDocumentRecord> KEY_TABLE_COLUMN_DOCUMENT_PRIMARY = Internal.createUniqueKey(TableColumnDocument.TABLE_COLUMN_DOCUMENT, DSL.name("KEY_table_column_document_PRIMARY"), new TableField[] { TableColumnDocument.TABLE_COLUMN_DOCUMENT.ID }, true);

View File

@ -18,6 +18,7 @@ import com.databasir.dao.tables.OauthApp;
import com.databasir.dao.tables.OperationLog;
import com.databasir.dao.tables.Project;
import com.databasir.dao.tables.ProjectSyncRule;
import com.databasir.dao.tables.ProjectSyncTask;
import com.databasir.dao.tables.SysKey;
import com.databasir.dao.tables.SysMail;
import com.databasir.dao.tables.TableColumnDocument;
@ -106,6 +107,11 @@ public class Tables {
*/
public static final ProjectSyncRule PROJECT_SYNC_RULE = ProjectSyncRule.PROJECT_SYNC_RULE;
/**
* The table <code>databasir.project_sync_task</code>.
*/
public static final ProjectSyncTask PROJECT_SYNC_TASK = ProjectSyncTask.PROJECT_SYNC_TASK;
/**
* The table <code>databasir.sys_key</code>.
*/

View File

@ -0,0 +1,186 @@
/*
* This file is generated by jOOQ.
*/
package com.databasir.dao.tables;
import com.databasir.dao.Databasir;
import com.databasir.dao.Indexes;
import com.databasir.dao.Keys;
import com.databasir.dao.converter.ProjectSyncTaskStatusConverter;
import com.databasir.dao.enums.ProjectSyncTaskStatus;
import com.databasir.dao.tables.records.ProjectSyncTaskRecord;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Identity;
import org.jooq.Index;
import org.jooq.Name;
import org.jooq.Record;
import org.jooq.Row8;
import org.jooq.Schema;
import org.jooq.Table;
import org.jooq.TableField;
import org.jooq.TableOptions;
import org.jooq.UniqueKey;
import org.jooq.impl.DSL;
import org.jooq.impl.SQLDataType;
import org.jooq.impl.TableImpl;
/**
* This class is generated by jOOQ.
*/
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class ProjectSyncTask extends TableImpl<ProjectSyncTaskRecord> {
private static final long serialVersionUID = 1L;
/**
* The reference instance of <code>databasir.project_sync_task</code>
*/
public static final ProjectSyncTask PROJECT_SYNC_TASK = new ProjectSyncTask();
/**
* The class holding records for this type
*/
@Override
public Class<ProjectSyncTaskRecord> getRecordType() {
return ProjectSyncTaskRecord.class;
}
/**
* The column <code>databasir.project_sync_task.id</code>.
*/
public final TableField<ProjectSyncTaskRecord, Integer> ID = createField(DSL.name("id"), SQLDataType.INTEGER.nullable(false).identity(true), this, "");
/**
* The column <code>databasir.project_sync_task.project_id</code>.
*/
public final TableField<ProjectSyncTaskRecord, Integer> PROJECT_ID = createField(DSL.name("project_id"), SQLDataType.INTEGER.nullable(false), this, "");
/**
* The column <code>databasir.project_sync_task.user_id</code>.
*/
public final TableField<ProjectSyncTaskRecord, Integer> USER_ID = createField(DSL.name("user_id"), SQLDataType.INTEGER.nullable(false), this, "");
/**
* The column <code>databasir.project_sync_task.status</code>. NEW RUNNING
* FINISHED FAILED CANCELED
*/
public final TableField<ProjectSyncTaskRecord, ProjectSyncTaskStatus> STATUS = createField(DSL.name("status"), SQLDataType.VARCHAR(32).nullable(false).defaultValue(DSL.inline("NEW", SQLDataType.VARCHAR)), this, "NEW RUNNING FINISHED FAILED CANCELED", new ProjectSyncTaskStatusConverter());
/**
* The column <code>databasir.project_sync_task.result</code>.
*/
public final TableField<ProjectSyncTaskRecord, String> RESULT = createField(DSL.name("result"), SQLDataType.VARCHAR(1024).nullable(false).defaultValue(DSL.inline("", SQLDataType.VARCHAR)), this, "");
/**
* The column <code>databasir.project_sync_task.run_at</code>.
*/
public final TableField<ProjectSyncTaskRecord, LocalDateTime> RUN_AT = createField(DSL.name("run_at"), SQLDataType.LOCALDATETIME(0), this, "");
/**
* The column <code>databasir.project_sync_task.update_at</code>.
*/
public final TableField<ProjectSyncTaskRecord, LocalDateTime> UPDATE_AT = createField(DSL.name("update_at"), SQLDataType.LOCALDATETIME(0).nullable(false).defaultValue(DSL.field("CURRENT_TIMESTAMP", SQLDataType.LOCALDATETIME)), this, "");
/**
* The column <code>databasir.project_sync_task.create_at</code>.
*/
public final TableField<ProjectSyncTaskRecord, LocalDateTime> CREATE_AT = createField(DSL.name("create_at"), SQLDataType.LOCALDATETIME(0).nullable(false).defaultValue(DSL.field("CURRENT_TIMESTAMP", SQLDataType.LOCALDATETIME)), this, "");
private ProjectSyncTask(Name alias, Table<ProjectSyncTaskRecord> aliased) {
this(alias, aliased, null);
}
private ProjectSyncTask(Name alias, Table<ProjectSyncTaskRecord> aliased, Field<?>[] parameters) {
super(alias, null, aliased, parameters, DSL.comment(""), TableOptions.table());
}
/**
* Create an aliased <code>databasir.project_sync_task</code> table
* reference
*/
public ProjectSyncTask(String alias) {
this(DSL.name(alias), PROJECT_SYNC_TASK);
}
/**
* Create an aliased <code>databasir.project_sync_task</code> table
* reference
*/
public ProjectSyncTask(Name alias) {
this(alias, PROJECT_SYNC_TASK);
}
/**
* Create a <code>databasir.project_sync_task</code> table reference
*/
public ProjectSyncTask() {
this(DSL.name("project_sync_task"), null);
}
public <O extends Record> ProjectSyncTask(Table<O> child, ForeignKey<O, ProjectSyncTaskRecord> key) {
super(child, key, PROJECT_SYNC_TASK);
}
@Override
public Schema getSchema() {
return aliased() ? null : Databasir.DATABASIR;
}
@Override
public List<Index> getIndexes() {
return Arrays.asList(Indexes.PROJECT_SYNC_TASK_IDX_PROJECT_ID, Indexes.PROJECT_SYNC_TASK_IDX_USER_ID);
}
@Override
public Identity<ProjectSyncTaskRecord, Integer> getIdentity() {
return (Identity<ProjectSyncTaskRecord, Integer>) super.getIdentity();
}
@Override
public UniqueKey<ProjectSyncTaskRecord> getPrimaryKey() {
return Keys.KEY_PROJECT_SYNC_TASK_PRIMARY;
}
@Override
public ProjectSyncTask as(String alias) {
return new ProjectSyncTask(DSL.name(alias), this);
}
@Override
public ProjectSyncTask as(Name alias) {
return new ProjectSyncTask(alias, this);
}
/**
* Rename this table
*/
@Override
public ProjectSyncTask rename(String name) {
return new ProjectSyncTask(DSL.name(name), null);
}
/**
* Rename this table
*/
@Override
public ProjectSyncTask rename(Name name) {
return new ProjectSyncTask(name, null);
}
// -------------------------------------------------------------------------
// Row8 type methods
// -------------------------------------------------------------------------
@Override
public Row8<Integer, Integer, Integer, ProjectSyncTaskStatus, String, LocalDateTime, LocalDateTime, LocalDateTime> fieldsRow() {
return (Row8) super.fieldsRow();
}
}

View File

@ -0,0 +1,193 @@
/*
* This file is generated by jOOQ.
*/
package com.databasir.dao.tables.pojos;
import com.databasir.dao.enums.ProjectSyncTaskStatus;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* This class is generated by jOOQ.
*/
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class ProjectSyncTaskPojo implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private Integer projectId;
private Integer userId;
private ProjectSyncTaskStatus status;
private String result;
private LocalDateTime runAt;
private LocalDateTime updateAt;
private LocalDateTime createAt;
public ProjectSyncTaskPojo() {}
public ProjectSyncTaskPojo(ProjectSyncTaskPojo value) {
this.id = value.id;
this.projectId = value.projectId;
this.userId = value.userId;
this.status = value.status;
this.result = value.result;
this.runAt = value.runAt;
this.updateAt = value.updateAt;
this.createAt = value.createAt;
}
public ProjectSyncTaskPojo(
Integer id,
Integer projectId,
Integer userId,
ProjectSyncTaskStatus status,
String result,
LocalDateTime runAt,
LocalDateTime updateAt,
LocalDateTime createAt
) {
this.id = id;
this.projectId = projectId;
this.userId = userId;
this.status = status;
this.result = result;
this.runAt = runAt;
this.updateAt = updateAt;
this.createAt = createAt;
}
/**
* Getter for <code>databasir.project_sync_task.id</code>.
*/
public Integer getId() {
return this.id;
}
/**
* Setter for <code>databasir.project_sync_task.id</code>.
*/
public void setId(Integer id) {
this.id = id;
}
/**
* Getter for <code>databasir.project_sync_task.project_id</code>.
*/
public Integer getProjectId() {
return this.projectId;
}
/**
* Setter for <code>databasir.project_sync_task.project_id</code>.
*/
public void setProjectId(Integer projectId) {
this.projectId = projectId;
}
/**
* Getter for <code>databasir.project_sync_task.user_id</code>.
*/
public Integer getUserId() {
return this.userId;
}
/**
* Setter for <code>databasir.project_sync_task.user_id</code>.
*/
public void setUserId(Integer userId) {
this.userId = userId;
}
/**
* Getter for <code>databasir.project_sync_task.status</code>. NEW RUNNING
* FINISHED FAILED CANCELED
*/
public ProjectSyncTaskStatus getStatus() {
return this.status;
}
/**
* Setter for <code>databasir.project_sync_task.status</code>. NEW RUNNING
* FINISHED FAILED CANCELED
*/
public void setStatus(ProjectSyncTaskStatus status) {
this.status = status;
}
/**
* Getter for <code>databasir.project_sync_task.result</code>.
*/
public String getResult() {
return this.result;
}
/**
* Setter for <code>databasir.project_sync_task.result</code>.
*/
public void setResult(String result) {
this.result = result;
}
/**
* Getter for <code>databasir.project_sync_task.run_at</code>.
*/
public LocalDateTime getRunAt() {
return this.runAt;
}
/**
* Setter for <code>databasir.project_sync_task.run_at</code>.
*/
public void setRunAt(LocalDateTime runAt) {
this.runAt = runAt;
}
/**
* Getter for <code>databasir.project_sync_task.update_at</code>.
*/
public LocalDateTime getUpdateAt() {
return this.updateAt;
}
/**
* Setter for <code>databasir.project_sync_task.update_at</code>.
*/
public void setUpdateAt(LocalDateTime updateAt) {
this.updateAt = updateAt;
}
/**
* Getter for <code>databasir.project_sync_task.create_at</code>.
*/
public LocalDateTime getCreateAt() {
return this.createAt;
}
/**
* Setter for <code>databasir.project_sync_task.create_at</code>.
*/
public void setCreateAt(LocalDateTime createAt) {
this.createAt = createAt;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("ProjectSyncTaskPojo (");
sb.append(id);
sb.append(", ").append(projectId);
sb.append(", ").append(userId);
sb.append(", ").append(status);
sb.append(", ").append(result);
sb.append(", ").append(runAt);
sb.append(", ").append(updateAt);
sb.append(", ").append(createAt);
sb.append(")");
return sb.toString();
}
}

View File

@ -0,0 +1,390 @@
/*
* This file is generated by jOOQ.
*/
package com.databasir.dao.tables.records;
import com.databasir.dao.enums.ProjectSyncTaskStatus;
import com.databasir.dao.tables.ProjectSyncTask;
import com.databasir.dao.tables.pojos.ProjectSyncTaskPojo;
import java.time.LocalDateTime;
import org.jooq.Field;
import org.jooq.Record1;
import org.jooq.Record8;
import org.jooq.Row8;
import org.jooq.impl.UpdatableRecordImpl;
/**
* This class is generated by jOOQ.
*/
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class ProjectSyncTaskRecord extends UpdatableRecordImpl<ProjectSyncTaskRecord> implements Record8<Integer, Integer, Integer, ProjectSyncTaskStatus, String, LocalDateTime, LocalDateTime, LocalDateTime> {
private static final long serialVersionUID = 1L;
/**
* Setter for <code>databasir.project_sync_task.id</code>.
*/
public void setId(Integer value) {
set(0, value);
}
/**
* Getter for <code>databasir.project_sync_task.id</code>.
*/
public Integer getId() {
return (Integer) get(0);
}
/**
* Setter for <code>databasir.project_sync_task.project_id</code>.
*/
public void setProjectId(Integer value) {
set(1, value);
}
/**
* Getter for <code>databasir.project_sync_task.project_id</code>.
*/
public Integer getProjectId() {
return (Integer) get(1);
}
/**
* Setter for <code>databasir.project_sync_task.user_id</code>.
*/
public void setUserId(Integer value) {
set(2, value);
}
/**
* Getter for <code>databasir.project_sync_task.user_id</code>.
*/
public Integer getUserId() {
return (Integer) get(2);
}
/**
* Setter for <code>databasir.project_sync_task.status</code>. NEW RUNNING
* FINISHED FAILED CANCELED
*/
public void setStatus(ProjectSyncTaskStatus value) {
set(3, value);
}
/**
* Getter for <code>databasir.project_sync_task.status</code>. NEW RUNNING
* FINISHED FAILED CANCELED
*/
public ProjectSyncTaskStatus getStatus() {
return (ProjectSyncTaskStatus) get(3);
}
/**
* Setter for <code>databasir.project_sync_task.result</code>.
*/
public void setResult(String value) {
set(4, value);
}
/**
* Getter for <code>databasir.project_sync_task.result</code>.
*/
public String getResult() {
return (String) get(4);
}
/**
* Setter for <code>databasir.project_sync_task.run_at</code>.
*/
public void setRunAt(LocalDateTime value) {
set(5, value);
}
/**
* Getter for <code>databasir.project_sync_task.run_at</code>.
*/
public LocalDateTime getRunAt() {
return (LocalDateTime) get(5);
}
/**
* Setter for <code>databasir.project_sync_task.update_at</code>.
*/
public void setUpdateAt(LocalDateTime value) {
set(6, value);
}
/**
* Getter for <code>databasir.project_sync_task.update_at</code>.
*/
public LocalDateTime getUpdateAt() {
return (LocalDateTime) get(6);
}
/**
* Setter for <code>databasir.project_sync_task.create_at</code>.
*/
public void setCreateAt(LocalDateTime value) {
set(7, value);
}
/**
* Getter for <code>databasir.project_sync_task.create_at</code>.
*/
public LocalDateTime getCreateAt() {
return (LocalDateTime) get(7);
}
// -------------------------------------------------------------------------
// Primary key information
// -------------------------------------------------------------------------
@Override
public Record1<Integer> key() {
return (Record1) super.key();
}
// -------------------------------------------------------------------------
// Record8 type implementation
// -------------------------------------------------------------------------
@Override
public Row8<Integer, Integer, Integer, ProjectSyncTaskStatus, String, LocalDateTime, LocalDateTime, LocalDateTime> fieldsRow() {
return (Row8) super.fieldsRow();
}
@Override
public Row8<Integer, Integer, Integer, ProjectSyncTaskStatus, String, LocalDateTime, LocalDateTime, LocalDateTime> valuesRow() {
return (Row8) super.valuesRow();
}
@Override
public Field<Integer> field1() {
return ProjectSyncTask.PROJECT_SYNC_TASK.ID;
}
@Override
public Field<Integer> field2() {
return ProjectSyncTask.PROJECT_SYNC_TASK.PROJECT_ID;
}
@Override
public Field<Integer> field3() {
return ProjectSyncTask.PROJECT_SYNC_TASK.USER_ID;
}
@Override
public Field<ProjectSyncTaskStatus> field4() {
return ProjectSyncTask.PROJECT_SYNC_TASK.STATUS;
}
@Override
public Field<String> field5() {
return ProjectSyncTask.PROJECT_SYNC_TASK.RESULT;
}
@Override
public Field<LocalDateTime> field6() {
return ProjectSyncTask.PROJECT_SYNC_TASK.RUN_AT;
}
@Override
public Field<LocalDateTime> field7() {
return ProjectSyncTask.PROJECT_SYNC_TASK.UPDATE_AT;
}
@Override
public Field<LocalDateTime> field8() {
return ProjectSyncTask.PROJECT_SYNC_TASK.CREATE_AT;
}
@Override
public Integer component1() {
return getId();
}
@Override
public Integer component2() {
return getProjectId();
}
@Override
public Integer component3() {
return getUserId();
}
@Override
public ProjectSyncTaskStatus component4() {
return getStatus();
}
@Override
public String component5() {
return getResult();
}
@Override
public LocalDateTime component6() {
return getRunAt();
}
@Override
public LocalDateTime component7() {
return getUpdateAt();
}
@Override
public LocalDateTime component8() {
return getCreateAt();
}
@Override
public Integer value1() {
return getId();
}
@Override
public Integer value2() {
return getProjectId();
}
@Override
public Integer value3() {
return getUserId();
}
@Override
public ProjectSyncTaskStatus value4() {
return getStatus();
}
@Override
public String value5() {
return getResult();
}
@Override
public LocalDateTime value6() {
return getRunAt();
}
@Override
public LocalDateTime value7() {
return getUpdateAt();
}
@Override
public LocalDateTime value8() {
return getCreateAt();
}
@Override
public ProjectSyncTaskRecord value1(Integer value) {
setId(value);
return this;
}
@Override
public ProjectSyncTaskRecord value2(Integer value) {
setProjectId(value);
return this;
}
@Override
public ProjectSyncTaskRecord value3(Integer value) {
setUserId(value);
return this;
}
@Override
public ProjectSyncTaskRecord value4(ProjectSyncTaskStatus value) {
setStatus(value);
return this;
}
@Override
public ProjectSyncTaskRecord value5(String value) {
setResult(value);
return this;
}
@Override
public ProjectSyncTaskRecord value6(LocalDateTime value) {
setRunAt(value);
return this;
}
@Override
public ProjectSyncTaskRecord value7(LocalDateTime value) {
setUpdateAt(value);
return this;
}
@Override
public ProjectSyncTaskRecord value8(LocalDateTime value) {
setCreateAt(value);
return this;
}
@Override
public ProjectSyncTaskRecord values(Integer value1, Integer value2, Integer value3, ProjectSyncTaskStatus value4, String value5, LocalDateTime value6, LocalDateTime value7, LocalDateTime value8) {
value1(value1);
value2(value2);
value3(value3);
value4(value4);
value5(value5);
value6(value6);
value7(value7);
value8(value8);
return this;
}
// -------------------------------------------------------------------------
// Constructors
// -------------------------------------------------------------------------
/**
* Create a detached ProjectSyncTaskRecord
*/
public ProjectSyncTaskRecord() {
super(ProjectSyncTask.PROJECT_SYNC_TASK);
}
/**
* Create a detached, initialised ProjectSyncTaskRecord
*/
public ProjectSyncTaskRecord(Integer id, Integer projectId, Integer userId, ProjectSyncTaskStatus status, String result, LocalDateTime runAt, LocalDateTime updateAt, LocalDateTime createAt) {
super(ProjectSyncTask.PROJECT_SYNC_TASK);
setId(id);
setProjectId(projectId);
setUserId(userId);
setStatus(status);
setResult(result);
setRunAt(runAt);
setUpdateAt(updateAt);
setCreateAt(createAt);
}
/**
* Create a detached, initialised ProjectSyncTaskRecord
*/
public ProjectSyncTaskRecord(ProjectSyncTaskPojo value) {
super(ProjectSyncTask.PROJECT_SYNC_TASK);
if (value != null) {
setId(value.getId());
setProjectId(value.getProjectId());
setUserId(value.getUserId());
setStatus(value.getStatus());
setResult(value.getResult());
setRunAt(value.getRunAt());
setUpdateAt(value.getUpdateAt());
setCreateAt(value.getCreateAt());
}
}
}

View File

@ -0,0 +1,12 @@
package com.databasir.dao.converter;
import com.databasir.dao.enums.ProjectSyncTaskStatus;
import org.jooq.impl.EnumConverter;
public class ProjectSyncTaskStatusConverter extends EnumConverter<String, ProjectSyncTaskStatus> {
public ProjectSyncTaskStatusConverter() {
super(String.class, ProjectSyncTaskStatus.class);
}
}

View File

@ -0,0 +1,9 @@
package com.databasir.dao.enums;
public enum ProjectSyncTaskStatus {
NEW,
RUNNING,
FINISHED,
FAILED,
CANCELLED
}

View File

@ -0,0 +1,59 @@
package com.databasir.dao.impl;
import com.databasir.dao.enums.ProjectSyncTaskStatus;
import com.databasir.dao.tables.pojos.ProjectSyncTaskPojo;
import com.databasir.dao.tables.records.ProjectSyncTaskRecord;
import lombok.Getter;
import org.jooq.DSLContext;
import org.jooq.UpdateSetMoreStep;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import static com.databasir.dao.Tables.PROJECT_SYNC_TASK;
@Repository
public class ProjectSyncTaskDao extends BaseDao<ProjectSyncTaskPojo> {
@Autowired
@Getter
private DSLContext dslContext;
public ProjectSyncTaskDao() {
super(PROJECT_SYNC_TASK, ProjectSyncTaskPojo.class);
}
public boolean existsByProjectId(Integer projectId, Collection<ProjectSyncTaskStatus> statusIn) {
if (statusIn == null || statusIn.isEmpty()) {
throw new IllegalArgumentException("statusIn must not be empty");
}
return dslContext.fetchExists(PROJECT_SYNC_TASK,
PROJECT_SYNC_TASK.PROJECT_ID.eq(projectId).and(PROJECT_SYNC_TASK.STATUS.in(statusIn)));
}
public List<ProjectSyncTaskPojo> listNewTasks(Integer size) {
return dslContext
.selectFrom(PROJECT_SYNC_TASK)
.where(PROJECT_SYNC_TASK.STATUS.eq(ProjectSyncTaskStatus.NEW))
.orderBy(PROJECT_SYNC_TASK.ID.asc())
.limit(size)
.fetchInto(ProjectSyncTaskPojo.class);
}
public int updateStatusAndResultById(Integer taskId, ProjectSyncTaskStatus status, String result) {
UpdateSetMoreStep<ProjectSyncTaskRecord> updateStep = dslContext
.update(PROJECT_SYNC_TASK)
.set(PROJECT_SYNC_TASK.STATUS, status)
.set(PROJECT_SYNC_TASK.RESULT, result);
if (status == ProjectSyncTaskStatus.RUNNING) {
updateStep = updateStep.set(PROJECT_SYNC_TASK.RUN_AT, LocalDateTime.now());
}
return updateStep
.where(PROJECT_SYNC_TASK.ID.eq(taskId))
.execute();
}
}

View File

@ -0,0 +1,14 @@
CREATE TABLE IF NOT EXISTS project_sync_task
(
`id` INT PRIMARY KEY AUTO_INCREMENT,
`project_id` INT NOT NULL,
`user_id` INT NOT NULL,
`status` VARCHAR(32) NOT NULL DEFAULT 'NEW' COMMENT 'NEW \ RUNNING \ FINISHED \ FAILED \ CANCELED',
`result` VARCHAR(1024) NOT NULL DEFAULT '',
`run_at` DATETIME DEFAULT NULL,
`update_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`create_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
INDEX idx_project_id (project_id),
INDEX idx_user_id (user_id)
) CHARSET utf8mb4
COLLATE utf8mb4_unicode_ci;