diff --git a/cli/flamingock-cli/src/main/java/io/flamingock/cli/service/AuditService.java b/cli/flamingock-cli/src/main/java/io/flamingock/cli/service/AuditService.java index 89023764d..7f3045dfa 100644 --- a/cli/flamingock-cli/src/main/java/io/flamingock/cli/service/AuditService.java +++ b/cli/flamingock-cli/src/main/java/io/flamingock/cli/service/AuditService.java @@ -109,7 +109,7 @@ public Optional getAuditEntryIssue(String changeId) { if (changeId == null || changeId.trim().isEmpty()) { throw new IllegalArgumentException("Change ID is required"); } - return opsClient.getAuditIssueByChange(changeId.trim()); + return opsClient.getAuditIssueByChangeId(changeId.trim()); } private OpsClient createOpsClient() { diff --git a/cloud/flamingock-cloud/src/main/java/io/flamingock/cloud/CloudAuditPersistenceImpl.java b/cloud/flamingock-cloud/src/main/java/io/flamingock/cloud/CloudAuditPersistenceImpl.java index 1479c0306..2cd357d7f 100644 --- a/cloud/flamingock-cloud/src/main/java/io/flamingock/cloud/CloudAuditPersistenceImpl.java +++ b/cloud/flamingock-cloud/src/main/java/io/flamingock/cloud/CloudAuditPersistenceImpl.java @@ -94,7 +94,7 @@ public List getAuditHistory() { } @Override - public List getSnapshotList() { + public List getAuditSnapshot() { throw new UnsupportedOperationException("getSnapshotList still not implemented for cloud edition"); } diff --git a/core/flamingock-core/src/main/java/io/flamingock/internal/core/builder/ops/AuditHistoryReader.java b/core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/audit/AuditHistoryReader.java similarity index 88% rename from core/flamingock-core/src/main/java/io/flamingock/internal/core/builder/ops/AuditHistoryReader.java rename to core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/audit/AuditHistoryReader.java index 8ec8db52d..bd06e6ed8 100644 --- a/core/flamingock-core/src/main/java/io/flamingock/internal/core/builder/ops/AuditHistoryReader.java +++ b/core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/audit/AuditHistoryReader.java @@ -13,9 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.flamingock.internal.core.builder.ops; - -import io.flamingock.internal.common.core.audit.AuditEntry; +package io.flamingock.internal.common.core.audit; import java.util.List; diff --git a/core/flamingock-core/src/main/java/io/flamingock/internal/core/builder/ops/AuditIssueManager.java b/core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/audit/AuditIssueReader.java similarity index 64% rename from core/flamingock-core/src/main/java/io/flamingock/internal/core/builder/ops/AuditIssueManager.java rename to core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/audit/AuditIssueReader.java index 826195d57..84294bd7c 100644 --- a/core/flamingock-core/src/main/java/io/flamingock/internal/core/builder/ops/AuditIssueManager.java +++ b/core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/audit/AuditIssueReader.java @@ -13,25 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.flamingock.internal.core.builder.ops; +package io.flamingock.internal.common.core.audit; import io.flamingock.internal.common.core.audit.issue.AuditEntryIssue; -import io.flamingock.internal.common.core.recovery.FixResult; -import io.flamingock.internal.common.core.recovery.Resolution; import java.util.List; import java.util.Optional; -public interface AuditIssueManager { - /** - * Get detailed information about a specific change that has issues. - * This includes full audit history, error messages, and execution attempts. - * - * @param changeId the change ID to inspect - * @return detailed issue information including all audit entries, error details, etc. - */ - Optional getAuditIssueByChange(String changeId); - +public interface AuditIssueReader { /** * Get only entries with issues * @return List of audit entries with problems/issues @@ -39,12 +28,12 @@ public interface AuditIssueManager { List getAuditIssues(); /** - * Resolves an audit issue for the given change by marking it as - * either {@link Resolution#APPLIED} or {@link Resolution#ROLLED_BACK}. + * Get detailed information about a specific change that has issues. + * This includes full audit history, error messages, and execution attempts. * - * @param changeId the change identifier - * @param resolution how the issue should be resolved - * @return result of the fix operation + * @param changeId the change ID to inspect + * @return detailed issue information including all audit entries, error details, etc. */ - FixResult fixAuditIssue(String changeId, Resolution resolution); + Optional getAuditIssueByChangeId(String changeId); + } diff --git a/core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/audit/AuditIssueResolver.java b/core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/audit/AuditIssueResolver.java new file mode 100644 index 000000000..f07f62343 --- /dev/null +++ b/core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/audit/AuditIssueResolver.java @@ -0,0 +1,33 @@ +/* + * Copyright 2025 Flamingock (https://www.flamingock.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://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. + */ +package io.flamingock.internal.common.core.audit; + +import io.flamingock.internal.common.core.recovery.FixResult; +import io.flamingock.internal.common.core.recovery.Resolution; + +public interface AuditIssueResolver extends AuditIssueReader { + + + /** + * Resolves an audit issue for the given change by marking it as + * either {@link Resolution#APPLIED} or {@link Resolution#ROLLED_BACK}. + * + * @param changeId the change identifier + * @param resolution how the issue should be resolved + * @return result of the fix operation + */ + FixResult fixAuditIssue(String changeId, Resolution resolution); +} diff --git a/core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/audit/AuditReader.java b/core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/audit/AuditReader.java index ede0e2360..f404a7f96 100644 --- a/core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/audit/AuditReader.java +++ b/core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/audit/AuditReader.java @@ -19,23 +19,20 @@ import io.flamingock.internal.common.core.audit.issue.AuditEntryIssueFactory; import io.flamingock.internal.common.core.audit.issue.NonIssue; -import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; -public interface AuditReader { +public interface AuditReader extends AuditHistoryReader, AuditIssueReader { - List getAuditHistory(); - - default List getSnapshotList() { + default List getAuditSnapshot() { AuditSnapshotBuilder builder = new AuditSnapshotBuilder(); getAuditHistory().forEach(builder::addEntry); return builder.buildList(); } default List getAuditIssues() { - return getSnapshotList() + return getAuditSnapshot() .stream() .map(AuditEntryIssueFactory::getIssue) .filter(issue -> !(issue instanceof NonIssue)) diff --git a/core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/audit/AuditReaderType.java b/core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/audit/AuditReaderType.java new file mode 100644 index 000000000..37347df25 --- /dev/null +++ b/core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/audit/AuditReaderType.java @@ -0,0 +1,20 @@ +/* + * Copyright 2025 Flamingock (https://www.flamingock.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://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. + */ +package io.flamingock.internal.common.core.audit; + +public enum AuditReaderType { + MONGOCK +} diff --git a/core/flamingock-core/src/main/java/io/flamingock/internal/core/builder/ops/AuditSnapshotReader.java b/core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/audit/AuditSnapshotReader.java similarity index 91% rename from core/flamingock-core/src/main/java/io/flamingock/internal/core/builder/ops/AuditSnapshotReader.java rename to core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/audit/AuditSnapshotReader.java index da87ba093..3f7776297 100644 --- a/core/flamingock-core/src/main/java/io/flamingock/internal/core/builder/ops/AuditSnapshotReader.java +++ b/core/flamingock-core-commons/src/main/java/io/flamingock/internal/common/core/audit/AuditSnapshotReader.java @@ -13,9 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.flamingock.internal.core.builder.ops; - -import io.flamingock.internal.common.core.audit.AuditEntry; +package io.flamingock.internal.common.core.audit; import java.time.LocalDateTime; import java.util.List; diff --git a/core/flamingock-core/src/main/java/io/flamingock/internal/core/builder/ops/OpsClient.java b/core/flamingock-core/src/main/java/io/flamingock/internal/core/builder/ops/OpsClient.java index 69561deea..42d6c2a1f 100644 --- a/core/flamingock-core/src/main/java/io/flamingock/internal/core/builder/ops/OpsClient.java +++ b/core/flamingock-core/src/main/java/io/flamingock/internal/core/builder/ops/OpsClient.java @@ -16,6 +16,9 @@ package io.flamingock.internal.core.builder.ops; import io.flamingock.internal.common.core.audit.AuditEntry; +import io.flamingock.internal.common.core.audit.AuditHistoryReader; +import io.flamingock.internal.common.core.audit.AuditIssueResolver; +import io.flamingock.internal.common.core.audit.AuditSnapshotReader; import io.flamingock.internal.common.core.audit.issue.AuditEntryIssue; import io.flamingock.internal.common.core.recovery.FixResult; import io.flamingock.internal.common.core.recovery.Resolution; @@ -31,7 +34,7 @@ import java.util.Optional; import java.util.stream.Collectors; -public class OpsClient implements AuditSnapshotReader, AuditHistoryReader, AuditIssueManager { +public class OpsClient implements AuditSnapshotReader, AuditHistoryReader, AuditIssueResolver { private final Logger logger = FlamingockLoggerFactory.getLogger("OpsClient"); private final AuditPersistence auditPersistence; @@ -48,20 +51,20 @@ public List getAuditHistory() { @Override public List getAuditSnapshot() { logger.debug("Getting audit entries snapshot (latest per change)"); - return auditPersistence.getSnapshotList(); + return auditPersistence.getAuditSnapshot(); } @Override public List getAuditSnapshotSince(LocalDateTime since) { logger.debug("Getting audit entries since: {}", since); - return auditPersistence.getSnapshotList() + return auditPersistence.getAuditSnapshot() .stream() .filter(auditEntry -> !auditEntry.getCreatedAt().isBefore(since)) .collect(Collectors.toList()); } @Override - public Optional getAuditIssueByChange(String changeId) { + public Optional getAuditIssueByChangeId(String changeId) { logger.debug("Getting issue details for changeId: {}", changeId); return auditPersistence.getAuditIssueByChangeId(changeId); } @@ -77,7 +80,7 @@ public List getAuditIssues() { public FixResult fixAuditIssue(String changeId, Resolution resolution) { logger.debug("Change[{}] marked as {}", changeId, resolution); - Optional auditIssue = getAuditIssueByChange(changeId); + Optional auditIssue = getAuditIssueByChangeId(changeId); if (!auditIssue.isPresent()) { return FixResult.NO_ISSUE_FOUND; } diff --git a/core/flamingock-core/src/main/java/io/flamingock/internal/core/targets/TransactionalTargetSystem.java b/core/flamingock-core/src/main/java/io/flamingock/internal/core/targets/TransactionalTargetSystem.java index 87ec0391c..409ac220f 100644 --- a/core/flamingock-core/src/main/java/io/flamingock/internal/core/targets/TransactionalTargetSystem.java +++ b/core/flamingock-core/src/main/java/io/flamingock/internal/core/targets/TransactionalTargetSystem.java @@ -15,6 +15,8 @@ */ package io.flamingock.internal.core.targets; +import io.flamingock.internal.common.core.audit.AuditHistoryReader; +import io.flamingock.internal.common.core.audit.AuditReaderType; import io.flamingock.internal.common.core.context.ContextInitializable; import io.flamingock.internal.core.runtime.ExecutionRuntime; import io.flamingock.internal.core.targets.mark.NoOpTargetSystemAuditMarker; @@ -22,6 +24,7 @@ import io.flamingock.internal.core.transaction.TransactionWrapper; import io.flamingock.internal.util.constants.CommunityPersistenceConstants; +import java.util.Optional; import java.util.function.Function; /** @@ -98,4 +101,33 @@ public TargetSystemAuditMarker getOnGoingTaskStatusRepository() { */ abstract public TransactionWrapper getTxWrapper(); + /** + * Returns an audit history reader for importing audit entries from external migration sources. + *

+ * This method enables Flamingock to import audit history from legacy migration tools or other + * Flamingock installations, preventing re-execution of already-applied changes. The returned + * reader provides access to historical audit entries that can be written to Flamingock's audit store. + *

+ * Common use cases include: + *

    + *
  • Mongock migration: Import Mongock change history when migrating from Mongock to Flamingock
  • + *
  • Community to Cloud migration: Import audit history from local database to Flamingock Cloud backend
  • + *
  • Future extensibility: Support for other migration tools (Liquibase, Flyway, etc.)
  • + *
+ *

+ * The default implementation returns {@code Optional.empty()}, indicating no audit reader is available. + * Target system implementations should override this method to provide database-specific readers when + * migration support is needed. + * + * @param type the type of audit reader to retrieve (e.g., {@link AuditReaderType#MONGOCK}) + * @return an {@link Optional} containing the audit history reader if supported for the given type, + * or {@link Optional#empty()} if this target system does not support audit reading for the specified type + * @see AuditHistoryReader + * @see AuditReaderType + * @see io.flamingock.importer.ImporterAdapter + */ + public Optional getAuditAuditReader(AuditReaderType type) { + return Optional.empty(); + } + }