[framework] TxCore → common-framework (TxContext·MessageCodec) (ACM-FW-001)
This commit is contained in:
parent
03c2999a26
commit
9b43defd7d
1 changed files with 280 additions and 0 deletions
|
|
@ -0,0 +1,280 @@
|
||||||
|
package com.klaro.acquirecore.framework;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TxCore - Spring Boot equivalent of C txcore.h/txcore.c
|
||||||
|
* Provides transaction context, buffer, request/response DTOs, and result codes.
|
||||||
|
*/
|
||||||
|
public final class TxCore {
|
||||||
|
|
||||||
|
private TxCore() {}
|
||||||
|
|
||||||
|
// ===== TxResult - equivalent to C tx_result_t enum =====
|
||||||
|
|
||||||
|
public enum TxResult {
|
||||||
|
OK(0), ERROR(-1), TIMEOUT(-2), ROLLBACK(-3), NESTED(-4);
|
||||||
|
|
||||||
|
private final int code;
|
||||||
|
|
||||||
|
TxResult(int code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TxResult fromCode(int code) {
|
||||||
|
for (TxResult r : values()) {
|
||||||
|
if (r.code == code) return r;
|
||||||
|
}
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSuccess() {
|
||||||
|
return this == OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toErrorString() {
|
||||||
|
return switch (this) {
|
||||||
|
case OK -> "OK";
|
||||||
|
case ERROR -> "Error";
|
||||||
|
case TIMEOUT -> "Timeout";
|
||||||
|
case ROLLBACK -> "Rollback";
|
||||||
|
case NESTED -> "Nested transaction not supported";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== TxBuffer - equivalent to C txbuf_t struct =====
|
||||||
|
|
||||||
|
public static final class TxBuffer {
|
||||||
|
private static final int MAX_BUFSIZE = 4096;
|
||||||
|
private final ByteBuffer buffer;
|
||||||
|
private final Map<String, Object> data;
|
||||||
|
|
||||||
|
public TxBuffer() {
|
||||||
|
this.buffer = ByteBuffer.allocate(MAX_BUFSIZE);
|
||||||
|
this.data = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TxBuffer(int capacity) {
|
||||||
|
this.buffer = ByteBuffer.allocate(Math.min(capacity, MAX_BUFSIZE));
|
||||||
|
this.data = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int write(byte[] src) {
|
||||||
|
if (src == null || buffer.remaining() < src.length) return -1;
|
||||||
|
buffer.put(src);
|
||||||
|
return src.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(byte[] dest) {
|
||||||
|
if (dest == null || buffer.remaining() < dest.length) return -1;
|
||||||
|
buffer.get(dest);
|
||||||
|
return dest.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] toByteArray() {
|
||||||
|
byte[] result = new byte[buffer.position()];
|
||||||
|
buffer.flip();
|
||||||
|
buffer.get(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(String key, Object value) {
|
||||||
|
data.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> T get(String key) {
|
||||||
|
return (T) data.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> getData() {
|
||||||
|
return new HashMap<>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
buffer.clear();
|
||||||
|
data.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rewind() {
|
||||||
|
buffer.rewind();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return buffer.position();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int remaining() {
|
||||||
|
return buffer.remaining();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== TxContext - equivalent to C tx_context_t struct =====
|
||||||
|
|
||||||
|
public static final class TxContext {
|
||||||
|
private static final AtomicLong txnCounter = new AtomicLong(0);
|
||||||
|
|
||||||
|
private final long txnId;
|
||||||
|
private final int flags;
|
||||||
|
private final TxBuffer buffer;
|
||||||
|
private final Map<String, Object> userData;
|
||||||
|
|
||||||
|
public TxContext() {
|
||||||
|
this(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TxContext(int flags) {
|
||||||
|
this.txnId = txnCounter.incrementAndGet();
|
||||||
|
this.flags = flags;
|
||||||
|
this.buffer = new TxBuffer();
|
||||||
|
this.userData = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTxnId() {
|
||||||
|
return txnId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFlags() {
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TxBuffer getBuffer() {
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserData(String key, Object value) {
|
||||||
|
userData.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> T getUserData(String key) {
|
||||||
|
return (T) userData.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearUserData() {
|
||||||
|
userData.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetBuffer() {
|
||||||
|
buffer.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "TxContext{txnId=" + txnId + ", flags=" + flags + ", bufferSize=" + buffer.size() + "}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== TxRequest - equivalent to C input void* parameter =====
|
||||||
|
|
||||||
|
public static final class TxRequest {
|
||||||
|
private final String serviceName;
|
||||||
|
private final Map<String, Object> payload;
|
||||||
|
private final TxContext context;
|
||||||
|
|
||||||
|
public TxRequest(String serviceName, Map<String, Object> payload, TxContext context) {
|
||||||
|
this.serviceName = Objects.requireNonNull(serviceName);
|
||||||
|
this.payload = payload != null ? Map.copyOf(payload) : Map.of();
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TxRequest of(String serviceName) {
|
||||||
|
return new TxRequest(serviceName, Map.of(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TxRequest of(String serviceName, Map<String, Object> payload) {
|
||||||
|
return new TxRequest(serviceName, payload, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getServiceName() {
|
||||||
|
return serviceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> getPayload() {
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TxContext getContext() {
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> T get(String key) {
|
||||||
|
return (T) payload.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean has(String key) {
|
||||||
|
return payload.containsKey(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== TxResponse - equivalent to C output void* parameter =====
|
||||||
|
|
||||||
|
public static final class TxResponse {
|
||||||
|
private final TxResult result;
|
||||||
|
private final Map<String, Object> data;
|
||||||
|
private final String errorMessage;
|
||||||
|
|
||||||
|
private TxResponse(TxResult result, Map<String, Object> data, String errorMessage) {
|
||||||
|
this.result = Objects.requireNonNull(result);
|
||||||
|
this.data = data != null ? Map.copyOf(data) : Map.of();
|
||||||
|
this.errorMessage = errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TxResponse success() {
|
||||||
|
return new TxResponse(TxResult.OK, Map.of(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TxResponse success(Map<String, Object> data) {
|
||||||
|
return new TxResponse(TxResult.OK, data, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TxResponse error(TxResult result) {
|
||||||
|
return new TxResponse(result, Map.of(), result.toErrorString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TxResponse error(TxResult result, String message) {
|
||||||
|
return new TxResponse(result, Map.of(), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TxResponse error(String message) {
|
||||||
|
return new TxResponse(TxResult.ERROR, Map.of(), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TxResult getResult() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getErrorMessage() {
|
||||||
|
return errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSuccess() {
|
||||||
|
return result.isSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> T get(String key) {
|
||||||
|
return (T) data.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TxResponse with(String key, Object value) {
|
||||||
|
Map<String, Object> newData = new HashMap<>(this.data);
|
||||||
|
newData.put(key, value);
|
||||||
|
return new TxResponse(this.result, newData, this.errorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in a new issue