diff --git a/src/main/java/com/github/sttk/sabi/AsyncGroup.java b/src/main/java/com/github/sttk/sabi/AsyncGroup.java index 1c699a2..490a0cb 100644 --- a/src/main/java/com/github/sttk/sabi/AsyncGroup.java +++ b/src/main/java/com/github/sttk/sabi/AsyncGroup.java @@ -4,10 +4,35 @@ */ package com.github.sttk.sabi; +/** + * An interface for asynchronously executing multiple {@link Runner} instances and waiting for their + * completion. + * + *
Implementations of this interface allow adding multiple {@link Runner} objects, which are then + * executed concurrently. The group waits until all added runners have finished their execution. Any + * errors occurring during the execution of a {@link Runner} are stored and can be retrieved by + * their names in a map. + */ public interface AsyncGroup { + + /** + * Represents the reason for a new {@link com.github.sttk.errs.Exc} exception object when an + * exception occurred during the execution of a {@link Runner} and the exception class was not the + * {@link com.github.sttk.errs.Exc}. + */ record RunnerFailed() {} + /** + * Represents the reason for an {@link com.github.sttk.errs.Exc} exception object when the + * creation of a thread for asynchronous execution of a {@link Runner} fails. + */ record RunnerInterrupted() {} + /** + * Adds a {@link Runner} to this group for asynchronous execution. The added runner will be + * executed in a separate thread. + * + * @param runner The {@link Runner} to be added and executed asynchronously. + */ void add(final Runner runner); } diff --git a/src/main/java/com/github/sttk/sabi/DataAcc.java b/src/main/java/com/github/sttk/sabi/DataAcc.java index a2817ea..64294e3 100644 --- a/src/main/java/com/github/sttk/sabi/DataAcc.java +++ b/src/main/java/com/github/sttk/sabi/DataAcc.java @@ -6,6 +6,26 @@ import com.github.sttk.errs.Exc; +/** + * An interface designed for implementing data access operations through default methods in its + * sub-interfaces. + * + *
Sub-interfaces of {@code DataAcc} are expected to define and implement data access methods as
+ * default methods. Within these default methods, the connection to the underlying data store should
+ * be obtained using the {@link #getDataConn(String, Class)} method provided by this interface. This
+ * design promotes a clear separation of concerns, allowing data access logic to be encapsulated
+ * within the interface itself.
+ */
public interface DataAcc {
+ /**
+ * Retrieves a connection to a data store. This method is intended to be used by default methods
+ * in sub-interfaces to obtain the necessary connection for performing data access operations.
+ *
+ * @param Its primary purpose is to enable cohesive transaction operations across multiple external data
+ * services within a single transaction context. Implementations of this interface provide the
+ * concrete input/output operations for their respective data services.
+ *
+ * Methods declared within this interface are designed to handle transactional logic. The
+ * AsyncGroup parameter in various methods allows for asynchronous processing when commit or
+ * rollback operations are time-consuming.
+ */
public interface DataConn {
+ /**
+ * Commits the changes made within the current session to the external data service. This method
+ * is responsible for finalizing all operations performed since the last commit or rollback.
+ *
+ * @param ag An {@link AsyncGroup} that can be used to perform asynchronous operations if the
+ * commit process is time-consuming.
+ * @throws Exc if an error occurs during the commit operation.
+ */
void commit(AsyncGroup ag) throws Exc;
+ /**
+ * Performs any necessary pre-commit operations. This method is called before the {@link
+ * #commit(AsyncGroup)} method.
+ *
+ * @param ag An {@link AsyncGroup} that can be used for asynchronous pre-commit tasks.
+ * @throws Exc if an error occurs during the pre-commit operation.
+ */
default void preCommit(AsyncGroup ag) throws Exc {}
+ /**
+ * Performs any necessary post-commit operations. This method is called after the {@link
+ * #commit(AsyncGroup)} method has successfully completed.
+ *
+ * @param ag An {@link AsyncGroup} that can be used for asynchronous post-commit tasks.
+ */
default void postCommit(AsyncGroup ag) {}
+ /**
+ * Indicates whether a force-back operation should be performed. A force-back is a mechanism to
+ * revert the committed changes when this connection had been already committed but the other
+ * connection had failed.
+ *
+ * @return {@code true} if a force-back is required, {@code false} otherwise.
+ */
default boolean shouldForceBack() {
return false;
}
+ /**
+ * Rolls back the changes made within the current session, discarding all operations performed
+ * since the last commit or rollback.
+ *
+ * @param ag An {@link AsyncGroup} that can be used to perform asynchronous operations if the
+ * rollback process is time-consuming.
+ */
void rollback(AsyncGroup ag);
+ /**
+ * Performs a force-back operation to revert the committed changes when this connection had been
+ * already committed but the other connection had failed.
+ *
+ * @param ag An {@link AsyncGroup} that can be used for asynchronous force-back tasks.
+ */
default void forceBack(AsyncGroup ag) {}
+ /**
+ * Closes the connection to the external data service, releasing any associated resources. This
+ * method should be called to ensure proper resource management.
+ */
void close();
}
diff --git a/src/main/java/com/github/sttk/sabi/DataHub.java b/src/main/java/com/github/sttk/sabi/DataHub.java
index fc42637..24684ce 100644
--- a/src/main/java/com/github/sttk/sabi/DataHub.java
+++ b/src/main/java/com/github/sttk/sabi/DataHub.java
@@ -8,39 +8,137 @@
import com.github.sttk.sabi.internal.DataHubInner;
import java.util.Map;
+/**
+ * {@code DataHub} is a central component in the Sabi framework that manages {@link DataSrc} and
+ * {@link DataConn} instances, facilitating data access and transaction management. It implements
+ * both {@link DataAcc} for data access operations and {@link AutoCloseable} for resource
+ * management.
+ *
+ * This class allows for the registration and unregistration of local {@link DataSrc} objects,
+ * and provides methods to execute application logic with or without transactional boundaries.
+ */
public class DataHub implements DataAcc, AutoCloseable {
+ /**
+ * Represents an error reason that occurred when failing to set up global {@link DataSrc}
+ * instances.
+ *
+ * @param errors A map containing the names of the data sources and the corresponding exceptions
+ * that occurred during their setup.
+ */
public record FailToSetupGlobalDataSrcs(Map It receives configuration for connecting to an external data service and then creates and
+ * supplies a {@link DataConn} instance, representing a single session connection.
+ */
public interface DataSrc {
+ /**
+ * Sets up the data source, performing any necessary initialization or configuration to establish
+ * connectivity to the external data service. This method is typically called once at the
+ * application startup.
+ *
+ * @param ag An {@link AsyncGroup} that can be used for asynchronous setup operations, especially
+ * if initialization is time-consuming.
+ * @throws Exc if an error occurs during the setup process.
+ */
void setup(AsyncGroup ag) throws Exc;
+ /**
+ * Closes the data source, releasing all resources and shutting down connections managed by this
+ * source. This method should be called when the application is shutting down to ensure proper
+ * resource cleanup.
+ */
void close();
+ /**
+ * Creates and returns a new {@link DataConn} instance, representing a single session connection
+ * to the external data service. Each call to this method should yield a new, independent
+ * connection.
+ *
+ * @return A new {@link DataConn} instance for a session.
+ * @throws Exc if an error occurs while creating the data connection.
+ */
DataConn createDataConn() throws Exc;
}
diff --git a/src/main/java/com/github/sttk/sabi/Logic.java b/src/main/java/com/github/sttk/sabi/Logic.java
index 46b0908..faf94d9 100644
--- a/src/main/java/com/github/sttk/sabi/Logic.java
+++ b/src/main/java/com/github/sttk/sabi/Logic.java
@@ -6,7 +6,28 @@
import com.github.sttk.errs.Exc;
+/**
+ * Represents the application's business logic, designed to separate data access concerns from the
+ * core logic.
+ *
+ * Implementations of this functional interface should focus solely on the business logic,
+ * utilizing the provided {@code data} object of type {@code D} for all data access operations. The
+ * {@link #run(Object)} method should not contain any direct data access code; instead, it should
+ * delegate such operations to methods of the {@code D} object.
+ *
+ * If an exceptional condition occurs during the execution of the logic, an {@link Exc} object
+ * should be thrown.
+ *
+ * @param This class declares {@link #uses uses} method to register a {@link DataSrc} object used
+ * globally with its name. And this class also declares {@link #setup setup} methods, which is the
+ * static method to setup all global registered {@link DataSrc} objects.
+ *
+ * The usages of these static methods is as follows:
+ *
+ * The returned {@link AutoCloseable} object can be used in a try-with-resources statement to
+ * automatically invoke the close operations upon exiting the try block.
+ *
+ * @return An {@link AutoCloseable} object that, when closed, will trigger the global close
+ * operation.
+ * @throws Exc if an error occurs during the setup of any {@link DataSrc}.
+ */
public static AutoCloseable setup() throws Exc {
return DataHubInner.setupGlobals();
}
diff --git a/src/main/java/com/github/sttk/sabi/internal/DataHubInner.java b/src/main/java/com/github/sttk/sabi/internal/DataHubInner.java
index 2ae4be6..720eacb 100644
--- a/src/main/java/com/github/sttk/sabi/internal/DataHubInner.java
+++ b/src/main/java/com/github/sttk/sabi/internal/DataHubInner.java
@@ -107,7 +107,7 @@ public void commit() throws Exc {
excMap.put(ptr.name, e);
break;
} catch (RuntimeException e) {
- excMap.put(ptr.name, new Exc(new DataHub.RuntimeExceptionOccured(), e));
+ excMap.put(ptr.name, new Exc(new DataHub.RuntimeExceptionOccurred(), e));
break;
}
ptr = ptr.next;
@@ -128,7 +128,7 @@ public void commit() throws Exc {
excMap.put(ptr.name, e);
break;
} catch (RuntimeException e) {
- excMap.put(ptr.name, new Exc(new DataHub.RuntimeExceptionOccured(), e));
+ excMap.put(ptr.name, new Exc(new DataHub.RuntimeExceptionOccurred(), e));
break;
}
ptr = ptr.next;
+ */
public final class Sabi {
private Sabi() {}
+ /**
+ * Registers a {@link DataSrc} object with a unique name for global use within the Sabi framework.
+ * This method should typically be called in a static initializer block of your application's main
+ * class.
+ *
+ * @param name The unique name to associate with the {@link DataSrc}.
+ * @param ds The {@link DataSrc} instance to be registered.
+ */
public static void uses(String name, DataSrc ds) {
DataHubInner.usesGlobal(name, ds);
}
+ /**
+ * Sets up all globally registered {@link DataSrc} objects. This involves calling the {@link
+ * DataSrc#setup(AsyncGroup) setup} method on each registered data source. This method should be
+ * called once at the application startup.
+ *
+ * public class Application {
+ * static {
+ * Sabi.uses("foo", new FooDataSrc());
+ * Sabi.uses("bar", new BarDataSrc());
+ * }
+ * public static void main(String ...args) {
+ * int exitCode = 0;
+ * try (var ac = Sabi.setup()) {
+ * ...
+ * } catch (Exception e) {
+ * exitCode = 1;
+ * }
+ * System.exit(exitCode);
+ * }
+ * }