From 2f4fcd5c43b94e7eea28bda2bb30e5d34fa7ff71 Mon Sep 17 00:00:00 2001 From: Martin Kaeser Date: Thu, 25 May 2023 12:14:10 +0200 Subject: [PATCH 1/3] feat(common): Refactor SyncRecordService (BaseSyncRecordService) into common module --- .../exception/BpdmSyncConflictException.kt | 5 +- .../exception/BpdmSyncStateException.kt | 2 +- .../bpdm/common/model/BaseSyncRecord.kt | 42 +++++ .../tractusx/bpdm/common}/model/SyncStatus.kt | 2 +- .../common/service/BaseSyncRecordService.kt | 145 ++++++++++++++++++ .../pool/api/model/response/SyncResponse.kt | 2 +- .../tractusx/bpdm/pool/entity/SyncRecord.kt | 32 ++-- .../bpdm/pool/service/SyncRecordService.kt | 125 ++------------- .../tractusx/bpdm/pool/util/TestHelpers.kt | 2 +- 9 files changed, 224 insertions(+), 133 deletions(-) rename {bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool => bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common}/exception/BpdmSyncConflictException.kt (89%) rename {bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool => bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common}/exception/BpdmSyncStateException.kt (95%) create mode 100644 bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/model/BaseSyncRecord.kt rename {bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api => bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common}/model/SyncStatus.kt (95%) create mode 100644 bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/service/BaseSyncRecordService.kt diff --git a/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/exception/BpdmSyncConflictException.kt b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/exception/BpdmSyncConflictException.kt similarity index 89% rename from bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/exception/BpdmSyncConflictException.kt rename to bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/exception/BpdmSyncConflictException.kt index d0bf71125..42520a77a 100644 --- a/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/exception/BpdmSyncConflictException.kt +++ b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/exception/BpdmSyncConflictException.kt @@ -17,13 +17,12 @@ * SPDX-License-Identifier: Apache-2.0 ******************************************************************************/ -package org.eclipse.tractusx.bpdm.pool.exception +package org.eclipse.tractusx.bpdm.common.exception -import org.eclipse.tractusx.bpdm.pool.api.model.SyncType import org.springframework.http.HttpStatus import org.springframework.web.bind.annotation.ResponseStatus @ResponseStatus(HttpStatus.CONFLICT) class BpdmSyncConflictException( - val type: SyncType + val type: Enum<*> ) : RuntimeException("Synchronization of type $type already running") \ No newline at end of file diff --git a/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/exception/BpdmSyncStateException.kt b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/exception/BpdmSyncStateException.kt similarity index 95% rename from bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/exception/BpdmSyncStateException.kt rename to bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/exception/BpdmSyncStateException.kt index 8ff4c200f..3fada6e42 100644 --- a/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/exception/BpdmSyncStateException.kt +++ b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/exception/BpdmSyncStateException.kt @@ -17,7 +17,7 @@ * SPDX-License-Identifier: Apache-2.0 ******************************************************************************/ -package org.eclipse.tractusx.bpdm.pool.exception +package org.eclipse.tractusx.bpdm.common.exception class BpdmSyncStateException( msg: String diff --git a/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/model/BaseSyncRecord.kt b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/model/BaseSyncRecord.kt new file mode 100644 index 000000000..644ce3e28 --- /dev/null +++ b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/model/BaseSyncRecord.kt @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2021,2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ******************************************************************************/ + +package org.eclipse.tractusx.bpdm.common.model + +import java.time.Instant + +interface BaseSyncRecord { + var type: SYNC_TYPE + + var status: SyncStatus + + var fromTime: Instant + + var progress: Float + + var count: Int + + var errorDetails: String? + + var errorSave: String? + + var startedAt: Instant? + + var finishedAt: Instant? +} diff --git a/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/SyncStatus.kt b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/model/SyncStatus.kt similarity index 95% rename from bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/SyncStatus.kt rename to bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/model/SyncStatus.kt index 37bdf2e29..aa926981a 100644 --- a/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/SyncStatus.kt +++ b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/model/SyncStatus.kt @@ -17,7 +17,7 @@ * SPDX-License-Identifier: Apache-2.0 ******************************************************************************/ -package org.eclipse.tractusx.bpdm.pool.api.model +package org.eclipse.tractusx.bpdm.common.model enum class SyncStatus{ NOT_SYNCED, diff --git a/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/service/BaseSyncRecordService.kt b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/service/BaseSyncRecordService.kt new file mode 100644 index 000000000..1fa2dca72 --- /dev/null +++ b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/service/BaseSyncRecordService.kt @@ -0,0 +1,145 @@ +/******************************************************************************* + * Copyright (c) 2021,2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ******************************************************************************/ + +package org.eclipse.tractusx.bpdm.common.service + +import mu.KLogger +import org.eclipse.tractusx.bpdm.common.exception.BpdmSyncConflictException +import org.eclipse.tractusx.bpdm.common.exception.BpdmSyncStateException +import org.eclipse.tractusx.bpdm.common.model.BaseSyncRecord +import org.eclipse.tractusx.bpdm.common.model.SyncStatus +import org.springframework.transaction.annotation.Isolation +import org.springframework.transaction.annotation.Transactional +import java.time.Instant +import java.time.LocalDateTime +import java.time.ZoneOffset +import java.time.temporal.ChronoUnit + +/** + * Uses transaction isolation level "serializable" in order to make sure that in case of parallel execution on different spring boot instances, + * only one instance can get the sync record and make changes like setting it to "running" state at the same time. + */ +abstract class BaseSyncRecordService, SYNC_RECORD : BaseSyncRecord> { + companion object { + val syncStartTime: Instant = LocalDateTime.of(2000, 1, 1, 0, 0).toInstant(ZoneOffset.UTC) + } + + protected abstract val logger: KLogger + + protected abstract fun newSyncRecord(type: SYNC_TYPE, syncStartTime: Instant): SYNC_RECORD + + protected abstract fun save(record: SYNC_RECORD): SYNC_RECORD + + protected abstract fun findByType(type: SYNC_TYPE): SYNC_RECORD? + + @Transactional(isolation = Isolation.SERIALIZABLE) + open fun getOrCreateRecord(type: SYNC_TYPE): SYNC_RECORD { + return findByType(type) ?: run { + logger.info { "Create new sync record entry for type $type" } + val newEntry = newSyncRecord(type, syncStartTime) + save(newEntry) + } + } + + @Transactional(isolation = Isolation.SERIALIZABLE) + open fun setSynchronizationStart(type: SYNC_TYPE): SYNC_RECORD { + val record = getOrCreateRecord(type) + + if (record.status == SyncStatus.RUNNING) + throw BpdmSyncConflictException(type) + + logger.debug { "Set sync of type ${record.type} to status ${SyncStatus.RUNNING}" } + + record.errorDetails = null + + if (record.status != SyncStatus.ERROR) { + record.fromTime = record.startedAt ?: syncStartTime + record.errorDetails = null + record.errorSave = null + record.startedAt = Instant.now().truncatedTo(ChronoUnit.MICROS) + record.finishedAt = null + record.count = 0 + record.progress = 0f + } + record.status = SyncStatus.RUNNING + + return save(record) + } + + @Transactional(isolation = Isolation.SERIALIZABLE) + open fun setSynchronizationSuccess(type: SYNC_TYPE): SYNC_RECORD { + val record = getOrCreateRecord(type) + if (record.status != SyncStatus.RUNNING) + throw BpdmSyncStateException("Synchronization of type ${record.type} can't switch from state ${record.status} to ${SyncStatus.SUCCESS}.") + + logger.debug { "Set sync of type ${record.type} to status ${SyncStatus.SUCCESS}" } + + record.finishedAt = Instant.now().truncatedTo(ChronoUnit.MICROS) + record.progress = 1f + record.status = SyncStatus.SUCCESS + record.errorDetails = null + record.errorSave = null + + return save(record) + } + + @Transactional(isolation = Isolation.SERIALIZABLE) + open fun setSynchronizationError(type: SYNC_TYPE, errorMessage: String, saveState: String?): SYNC_RECORD { + val record = getOrCreateRecord(type) + logger.debug { "Set sync of type ${record.type} to status ${SyncStatus.ERROR} with message $errorMessage" } + + record.finishedAt = Instant.now().truncatedTo(ChronoUnit.MICROS) + record.status = SyncStatus.ERROR + record.errorDetails = errorMessage.take(255) + record.errorSave = saveState + + return save(record) + } + + @Transactional(isolation = Isolation.SERIALIZABLE) + open fun setProgress(type: SYNC_TYPE, count: Int, progress: Float): SYNC_RECORD { + val record = getOrCreateRecord(type) + if (record.status != SyncStatus.RUNNING) + throw BpdmSyncStateException("Synchronization of type ${record.type} can't change progress when not running.") + + logger.debug { "Update progress of sync type ${record.type} to $progress" } + + record.count = count + record.progress = progress + + return save(record) + } + + @Transactional(isolation = Isolation.SERIALIZABLE) + open fun reset(type: SYNC_TYPE): SYNC_RECORD { + val record = getOrCreateRecord(type) + logger.debug { "Reset sync status of type ${record.type}" } + + record.status = SyncStatus.NOT_SYNCED + record.errorDetails = null + record.errorSave = null + record.startedAt = null + record.finishedAt = null + record.count = 0 + record.progress = 0f + record.fromTime = syncStartTime + + return save(record) + } +} \ No newline at end of file diff --git a/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/response/SyncResponse.kt b/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/response/SyncResponse.kt index 99ba51793..e4b7d049d 100644 --- a/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/response/SyncResponse.kt +++ b/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/response/SyncResponse.kt @@ -19,7 +19,7 @@ package org.eclipse.tractusx.bpdm.pool.api.model.response -import org.eclipse.tractusx.bpdm.pool.api.model.SyncStatus +import org.eclipse.tractusx.bpdm.common.model.SyncStatus import org.eclipse.tractusx.bpdm.pool.api.model.SyncType import java.time.Instant diff --git a/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/entity/SyncRecord.kt b/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/entity/SyncRecord.kt index cb2046e78..c3701c759 100644 --- a/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/entity/SyncRecord.kt +++ b/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/entity/SyncRecord.kt @@ -21,7 +21,8 @@ package org.eclipse.tractusx.bpdm.pool.entity import jakarta.persistence.* import org.eclipse.tractusx.bpdm.common.model.BaseEntity -import org.eclipse.tractusx.bpdm.pool.api.model.SyncStatus +import org.eclipse.tractusx.bpdm.common.model.BaseSyncRecord +import org.eclipse.tractusx.bpdm.common.model.SyncStatus import org.eclipse.tractusx.bpdm.pool.api.model.SyncType import java.time.Instant @@ -30,24 +31,31 @@ import java.time.Instant class SyncRecord( @Enumerated(EnumType.STRING) @Column(name = "type", nullable = false, unique = true) - var type: SyncType, + override var type: SyncType, + @Enumerated(EnumType.STRING) @Column(name = "status", nullable = false) - var status: SyncStatus, + override var status: SyncStatus, + @Column(name = "from_time", nullable = false) - var fromTime: Instant, + override var fromTime: Instant, + @Column(name = "progress", nullable = false) - var progress: Float = 0f, + override var progress: Float = 0f, + @Column(name = "count", nullable = false) - var count: Int = 0, + override var count: Int = 0, + @Column(name = "status_details") - var errorDetails: String? = null, + override var errorDetails: String? = null, + @Column(name = "save_state") - var errorSave: String? = null, + override var errorSave: String? = null, + @Column(name = "started_at") - var startedAt: Instant? = null, - @Column(name = "finished_at") - var finishedAt: Instant? = null, - ): BaseEntity() + override var startedAt: Instant? = null, + @Column(name = "finished_at") + override var finishedAt: Instant? = null +) : BaseEntity(), BaseSyncRecord diff --git a/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/SyncRecordService.kt b/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/SyncRecordService.kt index f4e8cbf96..4a57a927c 100644 --- a/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/SyncRecordService.kt +++ b/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/SyncRecordService.kt @@ -20,130 +20,27 @@ package org.eclipse.tractusx.bpdm.pool.service import mu.KotlinLogging -import org.eclipse.tractusx.bpdm.pool.api.model.SyncStatus +import org.eclipse.tractusx.bpdm.common.model.SyncStatus +import org.eclipse.tractusx.bpdm.common.service.BaseSyncRecordService import org.eclipse.tractusx.bpdm.pool.api.model.SyncType import org.eclipse.tractusx.bpdm.pool.entity.SyncRecord -import org.eclipse.tractusx.bpdm.pool.exception.BpdmSyncConflictException -import org.eclipse.tractusx.bpdm.pool.exception.BpdmSyncStateException import org.eclipse.tractusx.bpdm.pool.repository.SyncRecordRepository import org.springframework.stereotype.Service -import org.springframework.transaction.annotation.Isolation -import org.springframework.transaction.annotation.Transactional import java.time.Instant -import java.time.LocalDateTime -import java.time.ZoneOffset -import java.time.temporal.ChronoUnit -/** - * Uses transaction isolation level "serializable" in order to make sure that in case of parallel execution on different spring boot instances, - * only one instance can get the sync record and make changes like setting it to "running" state at the same time. - */ @Service class SyncRecordService( private val syncRecordRepository: SyncRecordRepository -) { - companion object { - val syncStartTime = LocalDateTime.of(2000, 1, 1, 0, 0).toInstant(ZoneOffset.UTC) - } +) : BaseSyncRecordService() { - private val logger = KotlinLogging.logger { } + override val logger = KotlinLogging.logger { } - @Transactional(isolation = Isolation.SERIALIZABLE) - fun getOrCreateRecord(type: SyncType): SyncRecord { - return syncRecordRepository.findByType(type) ?: run { - logger.info { "Create new sync record entry for type $type" } - val newEntry = SyncRecord( - type, - SyncStatus.NOT_SYNCED, - syncStartTime - ) - syncRecordRepository.save(newEntry) - } - } + override fun newSyncRecord(type: SyncType, syncStartTime: Instant) = + SyncRecord(type, SyncStatus.NOT_SYNCED, syncStartTime) - @Transactional(isolation = Isolation.SERIALIZABLE) - fun setSynchronizationStart(type: SyncType): SyncRecord { - val record = getOrCreateRecord(type) + override fun save(record: SyncRecord) = + syncRecordRepository.save(record) - if (record.status == SyncStatus.RUNNING) - throw BpdmSyncConflictException(SyncType.SAAS_IMPORT) - - logger.debug { "Set sync of type ${record.type} to status ${SyncStatus.RUNNING}" } - - record.errorDetails = null - - if (record.status != SyncStatus.ERROR) { - record.fromTime = record.startedAt ?: syncStartTime - record.errorDetails = null - record.errorSave = null - record.startedAt = Instant.now().truncatedTo(ChronoUnit.MICROS) - record.finishedAt = null - record.count = 0 - record.progress = 0f - } - record.status = SyncStatus.RUNNING - - return syncRecordRepository.save(record) - } - - @Transactional(isolation = Isolation.SERIALIZABLE) - fun setSynchronizationSuccess(type: SyncType): SyncRecord { - val record = getOrCreateRecord(type) - if (record.status != SyncStatus.RUNNING) - throw BpdmSyncStateException("Synchronization of type ${record.type} can't switch from state ${record.status} to ${SyncStatus.SUCCESS}.") - - logger.debug { "Set sync of type ${record.type} to status ${SyncStatus.SUCCESS}" } - - record.finishedAt = Instant.now().truncatedTo(ChronoUnit.MICROS) - record.progress = 1f - record.status = SyncStatus.SUCCESS - record.errorDetails = null - record.errorSave = null - - return syncRecordRepository.save(record) - } - - @Transactional(isolation = Isolation.SERIALIZABLE) - fun setSynchronizationError(type: SyncType, errorMessage: String, saveState: String?): SyncRecord { - val record = getOrCreateRecord(type) - logger.debug { "Set sync of type ${record.type} to status ${SyncStatus.ERROR} with message $errorMessage" } - - record.finishedAt = Instant.now().truncatedTo(ChronoUnit.MICROS) - record.status = SyncStatus.ERROR - record.errorDetails = errorMessage.take(255) - record.errorSave = saveState - - return syncRecordRepository.save(record) - } - - @Transactional(isolation = Isolation.SERIALIZABLE) - fun setProgress(type: SyncType, count: Int, progress: Float): SyncRecord { - val record = getOrCreateRecord(type) - if (record.status != SyncStatus.RUNNING) - throw BpdmSyncStateException("Synchronization of type ${record.type} can't change progress when not running.") - - logger.debug { "Update progress of sync type ${record.type} to $progress" } - - record.count = count - record.progress = progress - - return syncRecordRepository.save(record) - } - - @Transactional(isolation = Isolation.SERIALIZABLE) - fun reset(type: SyncType): SyncRecord { - val record = getOrCreateRecord(type) - logger.debug { "Reset sync status of type ${record.type}" } - - record.status = SyncStatus.NOT_SYNCED - record.errorDetails = null - record.errorSave = null - record.startedAt = null - record.finishedAt = null - record.count = 0 - record.progress = 0f - record.fromTime = syncStartTime - - return syncRecordRepository.save(record) - } -} \ No newline at end of file + override fun findByType(type: SyncType) = + syncRecordRepository.findByType(type) +} diff --git a/bpdm-pool/src/test/kotlin/org/eclipse/tractusx/bpdm/pool/util/TestHelpers.kt b/bpdm-pool/src/test/kotlin/org/eclipse/tractusx/bpdm/pool/util/TestHelpers.kt index 0c57f0340..d8f8ea4c0 100644 --- a/bpdm-pool/src/test/kotlin/org/eclipse/tractusx/bpdm/pool/util/TestHelpers.kt +++ b/bpdm-pool/src/test/kotlin/org/eclipse/tractusx/bpdm/pool/util/TestHelpers.kt @@ -23,8 +23,8 @@ import jakarta.persistence.EntityManager import jakarta.persistence.EntityManagerFactory import org.assertj.core.api.Assertions import org.assertj.core.api.RecursiveComparisonAssert +import org.eclipse.tractusx.bpdm.common.model.SyncStatus import org.eclipse.tractusx.bpdm.pool.api.client.PoolClientImpl -import org.eclipse.tractusx.bpdm.pool.api.model.SyncStatus import org.eclipse.tractusx.bpdm.pool.api.model.request.IdentifiersSearchRequest import org.eclipse.tractusx.bpdm.pool.api.model.response.ErrorCode import org.eclipse.tractusx.bpdm.pool.api.model.response.ErrorInfo From 859cb2b1d6fb7ed79c7c5de9dc485a4035c77af5 Mon Sep 17 00:00:00 2001 From: Martin Kaeser Date: Thu, 25 May 2023 14:54:01 +0200 Subject: [PATCH 2/3] feat(bridge): Add SyncRecord for tracking syncs --- .../bpdm/bridge/dummy/entity/SyncRecord.kt | 60 +++++++++++++++++++ .../bpdm/bridge/dummy/entity/SyncType.kt | 24 ++++++++ .../dummy/repository/SyncRecordRepository.kt | 29 +++++++++ .../bridge/dummy/service/SyncRecordService.kt | 46 ++++++++++++++ .../bpdm/bridge/dummy/service/SyncService.kt | 15 +++-- 5 files changed, 169 insertions(+), 5 deletions(-) create mode 100644 bpdm-bridge-dummy/src/main/kotlin/com/catenax/bpdm/bridge/dummy/entity/SyncRecord.kt create mode 100644 bpdm-bridge-dummy/src/main/kotlin/com/catenax/bpdm/bridge/dummy/entity/SyncType.kt create mode 100644 bpdm-bridge-dummy/src/main/kotlin/com/catenax/bpdm/bridge/dummy/repository/SyncRecordRepository.kt create mode 100644 bpdm-bridge-dummy/src/main/kotlin/com/catenax/bpdm/bridge/dummy/service/SyncRecordService.kt diff --git a/bpdm-bridge-dummy/src/main/kotlin/com/catenax/bpdm/bridge/dummy/entity/SyncRecord.kt b/bpdm-bridge-dummy/src/main/kotlin/com/catenax/bpdm/bridge/dummy/entity/SyncRecord.kt new file mode 100644 index 000000000..a8f6fee05 --- /dev/null +++ b/bpdm-bridge-dummy/src/main/kotlin/com/catenax/bpdm/bridge/dummy/entity/SyncRecord.kt @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2021,2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ******************************************************************************/ + +package com.catenax.bpdm.bridge.dummy.entity + +import jakarta.persistence.* +import org.eclipse.tractusx.bpdm.common.model.BaseEntity +import org.eclipse.tractusx.bpdm.common.model.BaseSyncRecord +import org.eclipse.tractusx.bpdm.common.model.SyncStatus +import java.time.Instant + +@Entity +@Table(name = "sync_records") +class SyncRecord( + @Enumerated(EnumType.STRING) + @Column(name = "type", nullable = false, unique = true) + override var type: SyncType, + + @Enumerated(EnumType.STRING) + @Column(name = "status", nullable = false) + override var status: SyncStatus, + + @Column(name = "from_time", nullable = false) + override var fromTime: Instant, + + @Column(name = "progress", nullable = false) + override var progress: Float = 0f, + + @Column(name = "count", nullable = false) + override var count: Int = 0, + + @Column(name = "status_details") + override var errorDetails: String? = null, + + @Column(name = "save_state") + override var errorSave: String? = null, + + @Column(name = "started_at") + override var startedAt: Instant? = null, + + @Column(name = "finished_at") + override var finishedAt: Instant? = null + +) : BaseEntity(), BaseSyncRecord diff --git a/bpdm-bridge-dummy/src/main/kotlin/com/catenax/bpdm/bridge/dummy/entity/SyncType.kt b/bpdm-bridge-dummy/src/main/kotlin/com/catenax/bpdm/bridge/dummy/entity/SyncType.kt new file mode 100644 index 000000000..dd745ad13 --- /dev/null +++ b/bpdm-bridge-dummy/src/main/kotlin/com/catenax/bpdm/bridge/dummy/entity/SyncType.kt @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2021,2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ******************************************************************************/ + +package com.catenax.bpdm.bridge.dummy.entity + +enum class SyncType { + GATE_TO_POOL +} \ No newline at end of file diff --git a/bpdm-bridge-dummy/src/main/kotlin/com/catenax/bpdm/bridge/dummy/repository/SyncRecordRepository.kt b/bpdm-bridge-dummy/src/main/kotlin/com/catenax/bpdm/bridge/dummy/repository/SyncRecordRepository.kt new file mode 100644 index 000000000..b5efe5da0 --- /dev/null +++ b/bpdm-bridge-dummy/src/main/kotlin/com/catenax/bpdm/bridge/dummy/repository/SyncRecordRepository.kt @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2021,2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ******************************************************************************/ + +package com.catenax.bpdm.bridge.dummy.repository + +import com.catenax.bpdm.bridge.dummy.entity.SyncRecord +import com.catenax.bpdm.bridge.dummy.entity.SyncType +import org.springframework.data.repository.CrudRepository + +interface SyncRecordRepository : CrudRepository { + + fun findByType(type: SyncType): SyncRecord? +} diff --git a/bpdm-bridge-dummy/src/main/kotlin/com/catenax/bpdm/bridge/dummy/service/SyncRecordService.kt b/bpdm-bridge-dummy/src/main/kotlin/com/catenax/bpdm/bridge/dummy/service/SyncRecordService.kt new file mode 100644 index 000000000..f4a61a084 --- /dev/null +++ b/bpdm-bridge-dummy/src/main/kotlin/com/catenax/bpdm/bridge/dummy/service/SyncRecordService.kt @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2021,2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ******************************************************************************/ + +package com.catenax.bpdm.bridge.dummy.service + +import com.catenax.bpdm.bridge.dummy.entity.SyncRecord +import com.catenax.bpdm.bridge.dummy.entity.SyncType +import com.catenax.bpdm.bridge.dummy.repository.SyncRecordRepository +import mu.KotlinLogging +import org.eclipse.tractusx.bpdm.common.model.SyncStatus +import org.eclipse.tractusx.bpdm.common.service.BaseSyncRecordService +import org.springframework.stereotype.Service +import java.time.Instant + +@Service +class SyncRecordService( + private val syncRecordRepository: SyncRecordRepository +) : BaseSyncRecordService() { + + override val logger = KotlinLogging.logger { } + + override fun newSyncRecord(type: SyncType, syncStartTime: Instant) = + SyncRecord(type, SyncStatus.NOT_SYNCED, syncStartTime) + + override fun save(record: SyncRecord) = + syncRecordRepository.save(record) + + override fun findByType(type: SyncType) = + syncRecordRepository.findByType(type) +} diff --git a/bpdm-bridge-dummy/src/main/kotlin/com/catenax/bpdm/bridge/dummy/service/SyncService.kt b/bpdm-bridge-dummy/src/main/kotlin/com/catenax/bpdm/bridge/dummy/service/SyncService.kt index 1a1521806..3750696ca 100644 --- a/bpdm-bridge-dummy/src/main/kotlin/com/catenax/bpdm/bridge/dummy/service/SyncService.kt +++ b/bpdm-bridge-dummy/src/main/kotlin/com/catenax/bpdm/bridge/dummy/service/SyncService.kt @@ -19,15 +19,18 @@ package com.catenax.bpdm.bridge.dummy.service +import com.catenax.bpdm.bridge.dummy.entity.SyncType import mu.KotlinLogging import org.eclipse.tractusx.bpdm.gate.api.model.response.LsaType import org.springframework.stereotype.Service +import java.time.Instant @Service class SyncService( val gateQueryService: GateQueryService, val poolUpdateService: PoolUpdateService, - val gateUpdateService: GateUpdateService + val gateUpdateService: GateUpdateService, + val syncRecordService: SyncRecordService ) { private val logger = KotlinLogging.logger { } @@ -36,19 +39,21 @@ class SyncService( fun sync() { logger.info("Bridge sync started...") + val syncRecord = syncRecordService.setSynchronizationStart(SyncType.GATE_TO_POOL) try { - syncInternal() + syncInternal(syncRecord.fromTime) logger.info("Bridge sync completed") + syncRecordService.setSynchronizationSuccess(SyncType.GATE_TO_POOL) } catch (e: Exception) { logger.error("Bridge sync failed with critical error:", e) + syncRecordService.setSynchronizationError(SyncType.GATE_TO_POOL, e.toString(), null) throw e } } - private fun syncInternal() { + private fun syncInternal(modifiedAfter: Instant) { // Check changelog entries from Gate (after last sync time) - val externalIdsByType = gateQueryService.getChangedExternalIdsByLsaType(null) - // TODO persist syncAfter=LocalDateTime.now() + val externalIdsByType = gateQueryService.getChangedExternalIdsByLsaType(modifiedAfter) externalIdsByType[LsaType.LegalEntity]?.let { syncLegalEntities(it) } externalIdsByType[LsaType.Site]?.let { syncSites(it) } From 122e46208019d0d8c2ee9cf8fcb7a82686169892 Mon Sep 17 00:00:00 2001 From: Martin Kaeser Date: Thu, 25 May 2023 14:54:43 +0200 Subject: [PATCH 3/3] feat(bridge): Add Flyway migration for SyncRecord --- .../migration/V4_0_0_0__create_sequence.sql | 1 + .../V4_0_0_1__create_sync_records.sql | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 bpdm-bridge-dummy/src/main/resources/db/migration/V4_0_0_0__create_sequence.sql create mode 100644 bpdm-bridge-dummy/src/main/resources/db/migration/V4_0_0_1__create_sync_records.sql diff --git a/bpdm-bridge-dummy/src/main/resources/db/migration/V4_0_0_0__create_sequence.sql b/bpdm-bridge-dummy/src/main/resources/db/migration/V4_0_0_0__create_sequence.sql new file mode 100644 index 000000000..5f332f4b8 --- /dev/null +++ b/bpdm-bridge-dummy/src/main/resources/db/migration/V4_0_0_0__create_sequence.sql @@ -0,0 +1 @@ +CREATE SEQUENCE IF NOT EXISTS bpdm_sequence START WITH 1 INCREMENT BY 1; diff --git a/bpdm-bridge-dummy/src/main/resources/db/migration/V4_0_0_1__create_sync_records.sql b/bpdm-bridge-dummy/src/main/resources/db/migration/V4_0_0_1__create_sync_records.sql new file mode 100644 index 000000000..d5fb34194 --- /dev/null +++ b/bpdm-bridge-dummy/src/main/resources/db/migration/V4_0_0_1__create_sync_records.sql @@ -0,0 +1,23 @@ +CREATE TABLE sync_records +( + id BIGINT NOT NULL, + uuid UUID NOT NULL, + created_at TIMESTAMP with time zone NOT NULL, + updated_at TIMESTAMP with time zone NOT NULL, + type VARCHAR(255) NOT NULL, + status VARCHAR(255) NOT NULL, + progress FLOAT NOT NULL, + count INTEGER NOT NULL, + status_details VARCHAR(255), + save_state VARCHAR(255), + started_at TIMESTAMP with time zone, + finished_at TIMESTAMP with time zone, + from_time TIMESTAMP with time zone, + CONSTRAINT pk_sync_records PRIMARY KEY (id) +); + +ALTER TABLE sync_records + ADD CONSTRAINT uc_sync_records_type UNIQUE (type); + +ALTER TABLE sync_records + ADD CONSTRAINT uc_sync_records_uuid UNIQUE (uuid);