diff --git a/.forge/ACM-FW-001-attempt-3-run-cf9312821cb6.md b/.forge/ACM-FW-001-attempt-3-run-cf9312821cb6.md deleted file mode 100644 index 4a5f0c4..0000000 --- a/.forge/ACM-FW-001-attempt-3-run-cf9312821cb6.md +++ /dev/null @@ -1,3 +0,0 @@ -# ACM-FW-001-attempt-3-run-cf9312821cb6 - -Forge 이슈 작업 브랜치 `forge/ACM-FW-001-attempt-3-run-cf9312821cb6`. diff --git a/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxContext.java b/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxContext.java index 35e5443..1a56634 100644 --- a/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxContext.java +++ b/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxContext.java @@ -1,90 +1,31 @@ package com.klaro.acquirecore.framework; -import java.io.Serializable; -import java.time.Instant; +import java.util.HashMap; import java.util.Map; -import java.util.UUID; /** - * Transaction context DTO carrying runtime state across service calls. - * Mirrors the C tx_context struct fields. + * 레거시 TxCore {@code TXBUF} (고정 슬롯 키/값 버퍼) 의 Spring 대체 자리표시자. + * + *

실 전환에서는 요청/응답 DTO(record) 가 정형 필드를 담고, 이 컨텍스트는 + * 서비스 체인({@code tx_call}) 간 전달되는 느슨한 키/값 상태만 보관한다. */ -public class TxContext implements Serializable { +public final class TxContext { - private static final long serialVersionUID = 1L; + private final Map slots = new HashMap<>(); - private String transactionId; - private String serviceName; - private TxStatus status; - private Instant startedAt; - private Instant committedAt; - private Map metadata; - - public TxContext() { - this.transactionId = UUID.randomUUID().toString(); - this.status = TxStatus.INITIAL; - this.startedAt = Instant.now(); + /** TXBUF 필드 설정 (레거시 {@code Fchg} 상당). */ + public TxContext put(String key, Object value) { + slots.put(key, value); + return this; } - public TxContext(String serviceName) { - this(); - this.serviceName = serviceName; + /** TXBUF 필드 조회 (레거시 {@code Fget} 상당). */ + public Object get(String key) { + return slots.get(key); } - public String getTransactionId() { - return transactionId; - } - - public void setTransactionId(String transactionId) { - this.transactionId = transactionId; - } - - public String getServiceName() { - return serviceName; - } - - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - public TxStatus getStatus() { - return status; - } - - public void setStatus(TxStatus status) { - this.status = status; - } - - public Instant getStartedAt() { - return startedAt; - } - - public void setStartedAt(Instant startedAt) { - this.startedAt = startedAt; - } - - public Instant getCommittedAt() { - return committedAt; - } - - public void setCommittedAt(Instant committedAt) { - this.committedAt = committedAt; - } - - public Map getMetadata() { - return metadata; - } - - public void setMetadata(Map metadata) { - this.metadata = metadata; - } - - public void markCommitted() { - this.status = TxStatus.COMMITTED; - this.committedAt = Instant.now(); - } - - public void markRolledBack() { - this.status = TxStatus.ROLLED_BACK; + /** 적재된 슬롯 개수. */ + public int size() { + return slots.size(); } } diff --git a/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxContextTest.java b/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxContextTest.java deleted file mode 100644 index 429b994..0000000 --- a/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxContextTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.klaro.acquirecore.framework; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -class TxContextTest { - - @Test - void defaultConstructorSetsInitialState() { - TxContext ctx = new TxContext(); - assertNotNull(ctx.getTransactionId()); - assertEquals(TxStatus.INITIAL, ctx.getStatus()); - assertNotNull(ctx.getStartedAt()); - } - - @Test - void constructorWithServiceName() { - TxContext ctx = new TxContext("myService"); - assertEquals("myService", ctx.getServiceName()); - assertEquals(TxStatus.INITIAL, ctx.getStatus()); - } - - @Test - void markCommittedUpdatesStatusAndTimestamp() { - TxContext ctx = new TxContext(); - assertNull(ctx.getCommittedAt()); - ctx.markCommitted(); - assertEquals(TxStatus.COMMITTED, ctx.getStatus()); - assertNotNull(ctx.getCommittedAt()); - } - - @Test - void markRolledBackUpdatesStatus() { - TxContext ctx = new TxContext(); - ctx.markRolledBack(); - assertEquals(TxStatus.ROLLED_BACK, ctx.getStatus()); - } - - @Test - void settersAndGetters() { - TxContext ctx = new TxContext(); - ctx.setTransactionId("tx-123"); - ctx.setServiceName("testService"); - ctx.setStatus(TxStatus.ACTIVE); - assertEquals("tx-123", ctx.getTransactionId()); - assertEquals("testService", ctx.getServiceName()); - assertEquals(TxStatus.ACTIVE, ctx.getStatus()); - } -} diff --git a/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxResult.java b/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxResult.java deleted file mode 100644 index b8a0099..0000000 --- a/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxResult.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.klaro.acquirecore.framework; - -import java.io.Serializable; - -/** - * Generic result wrapper for transactional operations. - * Mirrors C tx_result struct semantics. - */ -public class TxResult implements Serializable { - - private static final long serialVersionUID = 1L; - - private boolean success; - private T data; - private String errorCode; - private String errorMessage; - - public TxResult() { - } - - public static TxResult ok(T data) { - TxResult result = new TxResult<>(); - result.success = true; - result.data = data; - return result; - } - - public static TxResult error(String errorCode, String errorMessage) { - TxResult result = new TxResult<>(); - result.success = false; - result.errorCode = errorCode; - result.errorMessage = errorMessage; - return result; - } - - public boolean isSuccess() { - return success; - } - - public void setSuccess(boolean success) { - this.success = success; - } - - public T getData() { - return data; - } - - public void setData(T data) { - this.data = data; - } - - public String getErrorCode() { - return errorCode; - } - - public void setErrorCode(String errorCode) { - this.errorCode = errorCode; - } - - public String getErrorMessage() { - return errorMessage; - } - - public void setErrorMessage(String errorMessage) { - this.errorMessage = errorMessage; - } -} diff --git a/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxService.java b/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxService.java deleted file mode 100644 index 27cfd16..0000000 --- a/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxService.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.klaro.acquirecore.framework; - -/** - * Functional interface for transactional service operations. - * Represents a single unit of work within a transaction context. - */ -@FunctionalInterface -public interface TxService { - - /** - * Execute the service operation within the given transaction context. - * - * @param ctx the transaction context - * @param input the input data for the operation - * @return the result of the operation - */ - Object execute(TxContext ctx, Object input); -} diff --git a/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxServiceRegistry.java b/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxServiceRegistry.java deleted file mode 100644 index 7c43a3f..0000000 --- a/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxServiceRegistry.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.klaro.acquirecore.framework; - -import org.springframework.stereotype.Service; - -import jakarta.annotation.PostConstruct; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Service registry replacing C TX_SERVICE/registry pattern. - * Acts as a central dispatcher for transactional services. - * Annotated with @Service for Spring component scanning. - */ -@Service -public class TxServiceRegistry { - - private final Map services = new ConcurrentHashMap<>(); - - @PostConstruct - public void init() { - // Registry initialized and ready for service lookups - } - - /** - * Register a transactional service by name. - * Mirrors C tx_registry_add(). - */ - public void registerService(String name, TxService service) { - services.put(name, service); - } - - /** - * Unregister a service by name. - */ - public void unregisterService(String name) { - services.remove(name); - } - - /** - * Lookup a registered service by name. - * Mirrors C tx_registry_lookup(). - */ - public TxService lookupService(String name) { - return services.get(name); - } - - /** - * Execute a transactional operation on a named service. - * Mirrors C tx_service_dispatch(). - */ - public TxResult dispatch(String serviceName, TxContext ctx, Object input) { - TxService service = lookupService(serviceName); - if (service == null) { - return TxResult.error("SERVICE_NOT_FOUND", "Service not registered: " + serviceName); - } - try { - Object result = service.execute(ctx, input); - return TxResult.ok(result); - } catch (Exception e) { - return TxResult.error("EXECUTION_FAILED", e.getMessage()); - } - } - - /** - * Check if a service is registered. - */ - public boolean isRegistered(String name) { - return services.containsKey(name); - } - - /** - * Get count of registered services. - */ - public int getServiceCount() { - return services.size(); - } -} diff --git a/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxServiceRegistryTest.java b/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxServiceRegistryTest.java deleted file mode 100644 index 28b362a..0000000 --- a/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxServiceRegistryTest.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.klaro.acquirecore.framework; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -class TxServiceRegistryTest { - - private TxServiceRegistry registry; - - @BeforeEach - void setUp() { - registry = new TxServiceRegistry(); - registry.init(); - } - - @Test - void registerAndLookupService() { - TxService service = (ctx, input) -> "result"; - registry.registerService("testService", service); - assertTrue(registry.isRegistered("testService")); - assertEquals(service, registry.lookupService("testService")); - } - - @Test - void lookupUnregisteredServiceReturnsNull() { - assertNull(registry.lookupService("nonExistent")); - assertFalse(registry.isRegistered("nonExistent")); - } - - @Test - void unregisterService() { - TxService service = (ctx, input) -> "result"; - registry.registerService("toRemove", service); - registry.unregisterService("toRemove"); - assertFalse(registry.isRegistered("toRemove")); - } - - @Test - void dispatchExecutesRegisteredService() { - TxService service = (ctx, input) -> "processed: " + input; - registry.registerService("echo", service); - TxContext ctx = new TxContext("echo"); - TxResult result = registry.dispatch("echo", ctx, "hello"); - assertTrue(result.isSuccess()); - assertEquals("processed: hello", result.getData()); - } - - @Test - void dispatchFailsForUnregisteredService() { - TxContext ctx = new TxContext("unknown"); - TxResult result = registry.dispatch("unknown", ctx, null); - assertFalse(result.isSuccess()); - assertEquals("SERVICE_NOT_FOUND", result.getErrorCode()); - } - - @Test - void dispatchHandlesServiceException() { - TxService failingService = (ctx, input) -> { throw new RuntimeException("Service error"); }; - registry.registerService("failing", failingService); - TxContext ctx = new TxContext("failing"); - TxResult result = registry.dispatch("failing", ctx, null); - assertFalse(result.isSuccess()); - assertEquals("EXECUTION_FAILED", result.getErrorCode()); - } - - @Test - void getServiceCount() { - assertEquals(0, registry.getServiceCount()); - registry.registerService("s1", (ctx, input) -> null); - registry.registerService("s2", (ctx, input) -> null); - assertEquals(2, registry.getServiceCount()); - } -} diff --git a/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxStatus.java b/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxStatus.java deleted file mode 100644 index 91cf88a..0000000 --- a/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxStatus.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.klaro.acquirecore.framework; - -/** - * Transaction lifecycle states mirroring C tx_status enum. - */ -public enum TxStatus { - INITIAL, - ACTIVE, - COMMITTED, - ROLLED_BACK, - FAILED -} diff --git a/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxTemplate.java b/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxTemplate.java deleted file mode 100644 index a831ed2..0000000 --- a/boot/common-framework/src/main/java/com/klaro/acquirecore/framework/TxTemplate.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.klaro.acquirecore.framework; - -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; - -/** - * Transaction template replacing C tx_begin/tx_commit pattern. - * Provides @Transactional-backed execution with context management. - * Mirrors C tx_begin(), tx_commit(), tx_rollback() lifecycle. - */ -@Component -public class TxTemplate { - - /** - * Execute a transactional operation with automatic commit on success, - * rollback on exception. Mirrors C tx_begin + tx_commit pattern. - * - * @param serviceName the name of the registered service - * @param input the input data - * @param the result type - * @return TxResult containing the outcome - */ - @Transactional(rollbackFor = Exception.class) - public TxResult execute(String serviceName, Object input) { - return executeWithContext(serviceName, new TxContext(serviceName), input); - } - - /** - * Execute with an existing transaction context. - * - * @param serviceName the name of the registered service - * @param ctx the existing transaction context - * @param input the input data - * @param the result type - * @return TxResult containing the outcome - */ - @Transactional(rollbackFor = Exception.class) - public TxResult executeWithContext(String serviceName, TxContext ctx, Object input) { - ctx.setStatus(TxStatus.ACTIVE); - try { - Object result = doExecute(serviceName, ctx, input); - ctx.markCommitted(); - return TxResult.ok(result); - } catch (Exception e) { - ctx.markRolledBack(); - return TxResult.error("TX_FAILED", e.getMessage()); - } - } - - /** - * Execute without transaction boundary (read-only operations). - * - * @param serviceName the name of the registered service - * @param input the input data - * @param the result type - * @return TxResult containing the outcome - */ - @Transactional(readOnly = true) - public TxResult query(String serviceName, Object input) { - try { - TxContext ctx = new TxContext(serviceName); - Object result = doExecute(serviceName, ctx, input); - return TxResult.ok(result); - } catch (Exception e) { - return TxResult.error("QUERY_FAILED", e.getMessage()); - } - } - - private Object doExecute(String serviceName, TxContext ctx, Object input) { - throw new UnsupportedOperationException( - "Direct execution not supported. Use TxServiceRegistry.dispatch() or inject TxService directly." - ); - } -}