dosubot[bot] commented on issue #2667:
URL: 
https://github.com/apache/incubator-hugegraph/issues/2667#issuecomment-2365739451

   <!-- Answer -->
   The legacy master-worker role code design in Apache HugeGraph is implemented 
using an enumeration called `NodeRole`. This enum defines three roles: 
`MASTER`, `WORKER`, and `COMPUTER`. Each role is associated with a unique byte 
code and a name. The `NodeRole` enum also includes methods to check the role 
type and retrieve the role's code and name.
   
   Here is the relevant code:
   
   ```java
   public enum NodeRole implements SerialEnum {
   
       MASTER(1, "master"),
   
       WORKER(2, "worker"),
   
       COMPUTER(3, "computer");
   
       private final byte code;
       private final String name;
   
       NodeRole(int code, String name) {
           assert code < 256;
           this.code = (byte) code;
           this.name = name;
       }
   
       static {
           SerialEnum.register(NodeRole.class);
       }
   
       @Override
       public byte code() {
           return this.code;
       }
   
       public String string() {
           return this.name;
       }
   
       public boolean master() {
           return this == MASTER;
       }
   
       public boolean worker() {
           return this == WORKER;
       }
   
       public boolean computer() {
           return this == COMPUTER;
       }
   }
   ```
   
   - **Roles Defined**:
     - `MASTER`: Represents the master node with code `1` and name `"master"`.
     - `WORKER`: Represents the worker node with code `2` and name `"worker"`.
     - `COMPUTER`: Represents the computer node with code `3` and name 
`"computer"`.
   
   - **Methods**:
     - `code()`: Returns the byte code of the role.
     - `string()`: Returns the name of the role.
     - `master()`: Checks if the role is `MASTER`.
     - `worker()`: Checks if the role is `WORKER`.
     - `computer()`: Checks if the role is `COMPUTER`.
   
   Additionally, the `RoleListener` interface in the 
`org.apache.hugegraph.masterelection` package defines methods for handling role 
changes and errors within the system. This interface includes methods such as 
`onAsRoleMaster`, `onAsRoleWorker`, `onAsRoleCandidate`, `unknown`, 
`onAsRoleAbdication`, and `error`, each taking a `StateMachineContext` 
parameter to manage the state transitions and handle errors.
   
   Here is the relevant code for the `RoleListener` interface:
   
   ```java
   package org.apache.hugegraph.masterelection;
   
   public interface RoleListener {
   
       void onAsRoleMaster(StateMachineContext context);
   
       void onAsRoleWorker(StateMachineContext context);
   
       void onAsRoleCandidate(StateMachineContext context);
   
       void unknown(StateMachineContext context);
   
       void onAsRoleAbdication(StateMachineContext context);
   
       void error(StateMachineContext context, Throwable e);
   }
   ```
   
   The `RoleElectionStateMachineTest` class provides a test implementation for 
the role election state machine, demonstrating how roles transition and how the 
system logs these transitions. The `LogEntry` class within this test captures 
the epoch, node, and role for each state change, and the `TestConfig` class 
provides configuration details for the state machine.
   
   Here is an excerpt from the `RoleElectionStateMachineTest` class:
   
   ```java
   public class RoleElectionStateMachineTest {
   
       private static class LogEntry {
   
           private final Integer epoch;
           private final String node;
           private final Role role;
   
           enum Role {
               master,
               worker,
               candidate,
               abdication,
               unknown
           }
   
           public LogEntry(Integer epoch, String node, Role role) {
               this.epoch = epoch;
               this.node = node;
               this.role = role;
           }
   
           @Override
           public boolean equals(Object obj) {
               if (this == obj) {
                   return true;
               }
               if (!(obj instanceof LogEntry)) {
                   return false;
               }
               LogEntry logEntry = (LogEntry) obj;
               return Objects.equals(this.epoch, logEntry.epoch) &&
                      Objects.equals(this.node, logEntry.node) &&
                      this.role == logEntry.role;
           }
   
           @Override
           public int hashCode() {
               return Objects.hash(this.epoch, this.node, this.role);
           }
   
           @Override
           public String toString() {
               return "LogEntry{" +
                      "epoch=" + this.epoch +
                      ", node='" + this.node + '\'' +
                      ", role=" + this.role +
                      '}';
           }
       }
   
       private static class TestConfig implements Config {
   
           private final String node;
   
           public TestConfig(String node) {
               this.node = node;
           }
   
           @Override
           public String node() {
               return this.node;
           }
   
           @Override
           public String url() {
               return "http://127.0.0.1:8080";;
           }
   
           @Override
           public int exceedsFailCount() {
               return 2;
           }
   
           @Override
           public long randomTimeoutMillisecond() {
               return 400;
           }
   
           @Override
           public long heartBeatIntervalSecond() {
               return 1;
           }
   
           @Override
           public int masterDeadTimes() {
               return 5;
           }
   
           @Override
           public long baseTimeoutMillisecond() {
               return 100;
           }
       }
   
       @Test
       public void testStateMachine() throws InterruptedException {
           final int MAX_COUNT = 200;
           CountDownLatch stop = new CountDownLatch(4);
           List<LogEntry> logRecords = Collections.synchronizedList(new 
ArrayList<>(MAX_COUNT));
           List<String> masterNodes = Collections.synchronizedList(new 
ArrayList<>(MAX_COUNT));
           RoleListener callback = new RoleListener() {
   
               @Override
               public void onAsRoleMaster(StateMachineContext context) {
                   Integer epochId = context.epoch();
                   String node = context.node();
                   logRecords.add(new LogEntry(epochId, node, 
LogEntry.Role.master));
                   if (logRecords.size() > MAX_COUNT) {
                       context.stateMachine().shutdown();
                   }
                   Utils.println("master node: " + node);
                   masterNodes.add(node);
               }
   
               @Override
               public void onAsRoleWorker(StateMachineContext context) {
                   Integer epochId = context.epoch();
                   String node = context.node();
                   logRecords.add(new LogEntry(epochId, node, 
LogEntry.Role.worker));
                   if (logRecords.size() > MAX_COUNT) {
                       context.stateMachine().shutdown();
                   }
               }
   
               @Override
               public void onAsRoleCandidate(StateMachineContext context) {
                   Integer epochId = context.epoch();
                   String node = context.node();
                   logRecords.add(new LogEntry(epochId, node, 
LogEntry.Role.candidate));
                   if (logRecords.size() > MAX_COUNT) {
                       context.stateMachine().shutdown();
                   }
               }
           };
       }
   }
   ```
   
   This design allows for easy role identification, role-specific logic 
implementation, and handling of role transitions and errors within the 
HugeGraph system 
<sup>[[1]](https://github.com/apache/incubator-hugegraph/blob/master/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/NodeRole.java)</sup><sup>[[2]](https://github.com/apache/incubator-hugegraph/blob/master/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/masterelection/RoleListener.java)</sup><sup>[[3]](https://github.com/apache/incubator-hugegraph/blob/master/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/RoleElectionStateMachineTest.java)</sup>.
   
   
   <!-- Dosu Comment Footer -->
   *To continue talking to [Dosu](https://dosu.dev), mention @dosu.*
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to