+ * Quarkus CDI will choose the implementation based on profiles
+ */
+public interface MessageLogContentOperation {
+
+ MessageLogContentDTO saveMessage(@NonNull MessageLogContentDTO dto);
+
+ MessageLogContentDTO getMessage(@NonNull Long messageId);
+
+ MessageLogContentDTO updateMessage(@NonNull Long messageId, @NonNull MessageLogContentDTO dto);
+
+ void deleteMessage(@NonNull Long messageId);
+}
diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties
index d3abc27..fd9bcf6 100644
--- a/src/main/resources/application-dev.properties
+++ b/src/main/resources/application-dev.properties
@@ -1,24 +1,18 @@
# Database
-quarkus.datasource.db-kind=h2
-quarkus.datasource.username=sa
-quarkus.datasource.password=
+quarkus.datasource.db-kind=postgresql
+quarkus.datasource.devservices.image-name=postgres:18.2-alpine
-quarkus.datasource.jdbc.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1
-quarkus.datasource.jdbc.max-size=16
quarkus.hibernate-orm.database.default-schema=papertrailbot
-quarkus.hibernate-orm.schema-management.strategy=drop-and-create
+quarkus.hibernate-orm.schema-management.strategy=validate
+
# Flyway
quarkus.flyway.migrate-at-start=true
quarkus.flyway.create-schemas=true
quarkus.flyway.schemas=papertrailbot
quarkus.flyway.default-schema=papertrailbot
-
-# Global Redis Settings
-# (don't configure in dev mode so that dev tools can automatically spin up a container having redis if ur docker is running)
-# quarkus.redis.hosts=redis://localhost:6379
-# quarkus.redis.password=
-
+# Redis
quarkus.cache.type=redis
+quarkus.redis.devservices.image-name=redis:8.6.1-alpine
# Redis Cache Settings
quarkus.cache.redis."auditLog".ttl=30D
@@ -31,6 +25,9 @@ quarkus.redisson.threads=16
quarkus.redisson.netty-threads=32
# Logging Level
-quarkus.log.level=DEBUG
+quarkus.log.level=INFO
+
# Analytics
quarkus.analytics.disabled=true
+# Custom
+message.locks.enabled=true
diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties
index 0d64d3b..cff424c 100644
--- a/src/main/resources/application-prod.properties
+++ b/src/main/resources/application-prod.properties
@@ -33,5 +33,8 @@ quarkus.http.port=${PORT:8080}
# Logging Level
quarkus.log.level=INFO
+
# Analytics
-quarkus.analytics.disabled=true
\ No newline at end of file
+quarkus.analytics.disabled=true
+# Custom
+message.locks.enabled=true
\ No newline at end of file
diff --git a/src/test/java/integration/AuditLogRegistrationServiceIntegrationTest.java b/src/test/java/integration/AuditLogRegistrationServiceIntegrationTest.java
new file mode 100644
index 0000000..f2cd158
--- /dev/null
+++ b/src/test/java/integration/AuditLogRegistrationServiceIntegrationTest.java
@@ -0,0 +1,289 @@
+package integration;
+
+import io.github.eggy03.papertrail.api.dto.AuditLogRegistrationDTO;
+import io.github.eggy03.papertrail.api.entity.AuditLogRegistration;
+import io.github.eggy03.papertrail.api.repository.AuditLogRegistrationRepository;
+import io.quarkus.narayana.jta.QuarkusTransaction;
+import io.quarkus.redis.datasource.RedisDataSource;
+import io.quarkus.test.junit.QuarkusTest;
+import jakarta.inject.Inject;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import static io.restassured.RestAssured.given;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.Matchers.is;
+
+@QuarkusTest
+class AuditLogRegistrationServiceIntegrationTest {
+
+ private static final String BASE_PATH = "/api/v1/log/audit";
+
+ @Inject
+ AuditLogRegistrationRepository repository;
+
+ // RedisDataSource while not annotated for CDI, does get injected because Quarkus handles this synthetic bean
+ // Or IntelliJ does not see the dependencies
+ // see https://github.com/quarkiverse/quarkus-minio/issues/413 and https://github.com/quarkusio/quarkus/discussions/25120
+ @Inject
+ RedisDataSource redisDataSource;
+
+ static final Long TEST_GUILD_ID = 1302148573926148096L;
+ static final Long TEST_CHANNEL_ID = 1302148573926148097L;
+
+ static final Long NEGATIVE_TEST_GUILD_ID = -1302148573926148096L;
+ static final Long NEGATIVE_TEST_CHANNEL_ID = -1302148573926148097L;
+
+ // prep a valid Entity
+ final AuditLogRegistration validEntity = new AuditLogRegistration(TEST_GUILD_ID, TEST_CHANNEL_ID);
+ // prep a valid DTO
+ final AuditLogRegistrationDTO validDTO = new AuditLogRegistrationDTO(TEST_GUILD_ID, TEST_CHANNEL_ID);
+
+ // prep a stream of invalid DTOs
+ public static Stream