fix: duplicate project version when concurrency (#108)
This commit is contained in:
parent
821a3673d3
commit
ad4b1d9fe0
|
@ -1,5 +1,6 @@
|
|||
package com.databasir.job;
|
||||
|
||||
import com.databasir.common.DatabasirException;
|
||||
import com.databasir.core.domain.project.service.ProjectService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
@ -18,7 +19,11 @@ public class ProjectSyncJob implements Job {
|
|||
public void execute(JobExecutionContext context) throws JobExecutionException {
|
||||
JobDataMap dataMap = context.getMergedJobDataMap();
|
||||
Integer projectId = dataMap.getInt("projectId");
|
||||
projectService.createSyncTask(projectId, -1, true);
|
||||
try {
|
||||
projectService.createSyncTask(projectId, -1, true);
|
||||
} catch (DatabasirException e) {
|
||||
log.warn("Failed to create sync task for project {}, {}", projectId, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ public enum DomainErrors implements DatabasirErrors {
|
|||
INVALID_MOCK_DATA_SCRIPT("A_10029", "不合法的表达式"),
|
||||
CANNOT_DELETE_SELF("A_10030", "无法对自己执行删除账号操作"),
|
||||
DRIVER_CLASS_NOT_FOUND("A_10031", "获取驱动类名失败"),
|
||||
;
|
||||
DATABASE_DOCUMENT_DUPLICATE_KEY("A_10032", "文档版本重复");
|
||||
|
||||
private final String errCode;
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.databasir.core.domain.document.service;
|
||||
|
||||
import com.databasir.common.DatabasirException;
|
||||
import com.databasir.core.Databasir;
|
||||
import com.databasir.core.DatabasirConfig;
|
||||
import com.databasir.core.diff.Diffs;
|
||||
|
@ -21,6 +22,7 @@ import com.databasir.dao.value.DocumentDiscussionCountPojo;
|
|||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jooq.tools.StringUtils;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
@ -146,7 +148,13 @@ public class DocumentService {
|
|||
Integer projectId) {
|
||||
|
||||
var pojo = documentPojoConverter.toDatabasePojo(projectId, meta, version);
|
||||
final Integer docId = databaseDocumentDao.insertAndReturnId(pojo);
|
||||
final Integer docId;
|
||||
try {
|
||||
docId = databaseDocumentDao.insertAndReturnId(pojo);
|
||||
} catch (DuplicateKeyException e) {
|
||||
log.warn("ignore insert database document projectId={} version={}", projectId, version);
|
||||
throw new DatabasirException(DomainErrors.DATABASE_DOCUMENT_DUPLICATE_KEY);
|
||||
}
|
||||
meta.getTables().forEach(table -> {
|
||||
TableDocumentPojo tableMeta =
|
||||
documentPojoConverter.toTablePojo(docId, table);
|
||||
|
|
|
@ -188,12 +188,12 @@ public class ProjectService {
|
|||
@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();
|
||||
log.warn("create sync task failed, because project not exists, projectId={}", projectId);
|
||||
throw DomainErrors.PROJECT_NOT_FOUND.exception();
|
||||
}
|
||||
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);
|
||||
log.warn("create sync task failed, it's already exists, projectId={}", projectId);
|
||||
return Optional.empty();
|
||||
}
|
||||
ProjectSyncTaskPojo projectSyncTask = new ProjectSyncTaskPojo();
|
||||
|
|
|
@ -5,7 +5,6 @@ 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;
|
||||
|
@ -36,7 +35,6 @@ public class Indexes {
|
|||
public static final Index TABLE_FOREIGN_KEY_DOCUMENT_IDX_DATABASE_DOCUMENT_ID = Internal.createIndex(DSL.name("idx_database_document_id"), TableForeignKeyDocument.TABLE_FOREIGN_KEY_DOCUMENT, new OrderField[] { TableForeignKeyDocument.TABLE_FOREIGN_KEY_DOCUMENT.DATABASE_DOCUMENT_ID }, false);
|
||||
public static final Index TABLE_INDEX_DOCUMENT_IDX_DATABASE_DOCUMENT_ID = Internal.createIndex(DSL.name("idx_database_document_id"), TableIndexDocument.TABLE_INDEX_DOCUMENT, new OrderField[] { TableIndexDocument.TABLE_INDEX_DOCUMENT.DATABASE_DOCUMENT_ID }, false);
|
||||
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);
|
||||
|
|
|
@ -76,6 +76,7 @@ public class Keys {
|
|||
public static final UniqueKey<DataSourceRecord> KEY_DATA_SOURCE_UK_PROJECT_ID = Internal.createUniqueKey(DataSource.DATA_SOURCE, DSL.name("KEY_data_source_uk_project_id"), new TableField[] { DataSource.DATA_SOURCE.PROJECT_ID }, true);
|
||||
public static final UniqueKey<DataSourcePropertyRecord> KEY_DATA_SOURCE_PROPERTY_PRIMARY = Internal.createUniqueKey(DataSourceProperty.DATA_SOURCE_PROPERTY, DSL.name("KEY_data_source_property_PRIMARY"), new TableField[] { DataSourceProperty.DATA_SOURCE_PROPERTY.ID }, true);
|
||||
public static final UniqueKey<DatabaseDocumentRecord> KEY_DATABASE_DOCUMENT_PRIMARY = Internal.createUniqueKey(DatabaseDocument.DATABASE_DOCUMENT, DSL.name("KEY_database_document_PRIMARY"), new TableField[] { DatabaseDocument.DATABASE_DOCUMENT.ID }, true);
|
||||
public static final UniqueKey<DatabaseDocumentRecord> KEY_DATABASE_DOCUMENT_UK_PROJECT_ID_VERSION_IS_ARCHIVE = Internal.createUniqueKey(DatabaseDocument.DATABASE_DOCUMENT, DSL.name("KEY_database_document_uk_project_id_version_is_archive"), new TableField[] { DatabaseDocument.DATABASE_DOCUMENT.PROJECT_ID, DatabaseDocument.DATABASE_DOCUMENT.VERSION, DatabaseDocument.DATABASE_DOCUMENT.IS_ARCHIVE }, true);
|
||||
public static final UniqueKey<DatabaseTypeRecord> KEY_DATABASE_TYPE_PRIMARY = Internal.createUniqueKey(DatabaseType.DATABASE_TYPE, DSL.name("KEY_database_type_PRIMARY"), new TableField[] { DatabaseType.DATABASE_TYPE.ID }, true);
|
||||
public static final UniqueKey<DatabaseTypeRecord> KEY_DATABASE_TYPE_UK_DATABASE_TYPE_DELETED_DELETED_TOKEN = Internal.createUniqueKey(DatabaseType.DATABASE_TYPE, DSL.name("KEY_database_type_uk_database_type_deleted_deleted_token"), new TableField[] { DatabaseType.DATABASE_TYPE.DATABASE_TYPE_, DatabaseType.DATABASE_TYPE.DELETED, DatabaseType.DATABASE_TYPE.DELETED_TOKEN }, true);
|
||||
public static final UniqueKey<DocumentDescriptionRecord> KEY_DOCUMENT_DESCRIPTION_PRIMARY = Internal.createUniqueKey(DocumentDescription.DOCUMENT_DESCRIPTION, DSL.name("KEY_document_description_PRIMARY"), new TableField[] { DocumentDescription.DOCUMENT_DESCRIPTION.ID }, true);
|
||||
|
|
|
@ -5,7 +5,6 @@ package com.databasir.dao.tables;
|
|||
|
||||
|
||||
import com.databasir.dao.Databasir;
|
||||
import com.databasir.dao.Indexes;
|
||||
import com.databasir.dao.Keys;
|
||||
import com.databasir.dao.tables.records.DatabaseDocumentRecord;
|
||||
|
||||
|
@ -16,7 +15,6 @@ 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.Row10;
|
||||
|
@ -141,11 +139,6 @@ public class DatabaseDocument extends TableImpl<DatabaseDocumentRecord> {
|
|||
return aliased() ? null : Databasir.DATABASIR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Index> getIndexes() {
|
||||
return Arrays.asList(Indexes.DATABASE_DOCUMENT_IDX_PROJECT_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identity<DatabaseDocumentRecord, Integer> getIdentity() {
|
||||
return (Identity<DatabaseDocumentRecord, Integer>) super.getIdentity();
|
||||
|
@ -156,6 +149,11 @@ public class DatabaseDocument extends TableImpl<DatabaseDocumentRecord> {
|
|||
return Keys.KEY_DATABASE_DOCUMENT_PRIMARY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UniqueKey<DatabaseDocumentRecord>> getUniqueKeys() {
|
||||
return Arrays.asList(Keys.KEY_DATABASE_DOCUMENT_UK_PROJECT_ID_VERSION_IS_ARCHIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseDocument as(String alias) {
|
||||
return new DatabaseDocument(DSL.name(alias), this);
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
ALTER TABLE database_document
|
||||
ADD CONSTRAINT UNIQUE uk_project_id_version_is_archive (project_id, version, is_archive);
|
||||
ALTER TABLE database_document
|
||||
DROP INDEX idx_project_id;
|
Loading…
Reference in New Issue