docs: public RaftClusterContext configure(Configuration configuration) {
      checkNotNull(configuration, "configuration cannot be null");
  
      // If the configuration index is less than the currently configured index, ignore it.
      // Configurations can be persisted and applying old configurations can revert newer configurations.
      if (this.configuration != null && configuration.index() <= this.configuration.index()) {
        return this;
      }
  
      Instant time = Instant.ofEpochMilli(configuration.time());
  
      // Iterate through members in the new configuration, add any missing members, and update existing members.
      boolean transition = false;
      for (RaftMember member : configuration.members()) {
        if (member.equals(this.member)) {
          transition = this.member.getType().ordinal() < member.getType().ordinal();
          this.member.update(member.getType(), time);
          members.add(this.member);
        } else {
          // If the member state doesn't already exist, create it.
          RaftMemberContext state = membersMap.get(member.memberId());
          if (state == null) {
            DefaultRaftMember defaultMember = new DefaultRaftMember(member.memberId(), member.getType(), time);
            state = new RaftMemberContext(defaultMember, this);
            state.resetState(raft.getLog());
            this.members.add(state.getMember());
            this.remoteMembers.add(state);
            membersMap.put(member.memberId(), state);
            listeners.forEach(l -> l.event(new RaftClusterEvent(RaftClusterEvent.Type.JOIN, defaultMember, time.toEpochMilli())));
          }
  
          // If the member type has changed, update the member type and reset its state.
          if (state.getMember().getType() != member.getType()) {
            state.getMember().update(member.getType(), time);
            state.resetState(raft.getLog());
          }
  
          // Update the optimized member collections according to the member type.
          for (List<RaftMemberContext> memberType : memberTypes.values()) {
            memberType.remove(state);
          }
  
          List<RaftMemberContext> memberType = memberTypes.get(member.getType());
          if (memberType == null) {
            memberType = new CopyOnWriteArrayList<>();
            memberTypes.put(member.getType(), memberType);
          }
          memberType.add(state);
        }
      }
  
      // Transition the local member only if the member is being promoted and not demoted.
      // Configuration changes that demote the local member are only applied to the local server
      // upon commitment. This ensures that e.g. a leader that's removing itself from the quorum
      // can commit the configuration change prior to shutting down.
      if (transition) {
        raft.transition(this.member.getType());
      }
  
      // Iterate through configured members and remove any that no longer exist in the configuration.
      int i = 0;
      while (i < this.remoteMembers.size()) {
        RaftMemberContext member = this.remoteMembers.get(i);
        if (!configuration.members().contains(member.getMember())) {
          this.members.remove(member.getMember());
          this.remoteMembers.remove(i);
          for (List<RaftMemberContext> memberType : memberTypes.values()) {
            memberType.remove(member);
          }
          membersMap.remove(member.getMember().memberId());
          listeners.forEach(l -> l.event(new RaftClusterEvent(RaftClusterEvent.Type.LEAVE, member.getMember(), time.toEpochMilli())));
        } else {
          i++;
        }
      }
  
      // If the local member was removed from the cluster, remove it from the members list.
      if (!configuration.members().contains(member)) {
        members.remove(member);
      }
  
      this.configuration = configuration;
  
      // Store the configuration if it's already committed.
      if (raft.getCommitIndex() >= configuration.index()) {
        raft.getMetaStore().storeConfiguration(configuration);
      }
  
      return this;
    }