private synchronized void recomputeTerm(PartitionGroupMembership membership) {
    if (membership == null) {
      return;
    }

    // Create a list of candidates based on the availability of members in the group.
    List<GroupMember> candidates = new ArrayList<>();
    for (MemberId memberId : membership.members()) {
      Member member = clusterMembershipService.getMember(memberId);
      if (member != null && member.isReachable()) {
        candidates.add(new GroupMember(memberId, MemberGroupId.from(memberId.id())));
      }
    }

    // Sort the candidates by a hash of their member ID.
    candidates.sort((a, b) -> {
      int aoffset = Hashing.murmur3_32().hashString(a.memberId().id(), StandardCharsets.UTF_8).asInt() % partitionId.id();
      int boffset = Hashing.murmur3_32().hashString(b.memberId().id(), StandardCharsets.UTF_8).asInt() % partitionId.id();
      return aoffset - boffset;
    });

    // Store the current term in a local variable avoid repeated volatile reads.
    PrimaryTerm currentTerm = this.currentTerm;

    // Compute the primary from the sorted candidates list.
    GroupMember primary = candidates.isEmpty() ? null : candidates.get(0);

    // Remove the primary from the candidates list.
    candidates = candidates.isEmpty() ? Collections.emptyList() : candidates.subList(1, candidates.size());

    // If the primary has changed, increment the term. Otherwise, use the current term from the replicated counter.
    long term = currentTerm != null
        && Objects.equals(currentTerm.primary(), primary)
        && Objects.equals(currentTerm.candidates(), candidates)
        ? currentTerm() : incrementTerm();

    // Create the new primary term. If the term has changed update the term and trigger an event.
    PrimaryTerm newTerm = new PrimaryTerm(term, primary, candidates);
    if (!Objects.equals(currentTerm, newTerm)) {
      this.currentTerm = newTerm;
      LOGGER.debug("{} - Recomputed term for partition {}: {}", clusterMembershipService.getLocalMember().id(), partitionId, newTerm);
      post(new PrimaryElectionEvent(PrimaryElectionEvent.Type.CHANGED, partitionId, newTerm));
      broadcastCounters();
    }
  }
private synchronized void recomputeTerm ( PartitionGroupMembership membership ) { if ( membership == null ) { return ; } List < GroupMember > candidates = new ArrayList < > ( ) ; for ( MemberId memberId : membership . members ( ) ) { Member member = clusterMembershipService . getMember ( memberId ) ; if ( member != null && member . isReachable ( ) ) { candidates . add ( new GroupMember ( memberId , MemberGroupId . from ( memberId . id ( ) ) ) ) ; } } candidates . sort ( ( a , b ) -> { int aoffset = Hashing . murmur3_32 ( ) . hashString ( a . memberId ( ) . id ( ) , StandardCharsets . UTF_8 ) . asInt ( ) % partitionId . id ( ) ; int boffset = Hashing . murmur3_32 ( ) . hashString ( b . memberId ( ) . id ( ) , StandardCharsets . UTF_8 ) . asInt ( ) % partitionId . id ( ) ; return aoffset - boffset ; } ) ; PrimaryTerm currentTerm = this . currentTerm ; GroupMember primary = candidates . isEmpty ( ) ? null : candidates . get ( 0 ) ; candidates = candidates . isEmpty ( ) ? Collections . emptyList ( ) : candidates . subList ( 1 , candidates . size ( ) ) ; long term = currentTerm != null && Objects . equals ( currentTerm . primary ( ) , primary ) && Objects . equals ( currentTerm . candidates ( ) , candidates ) ? currentTerm ( ) : incrementTerm ( ) ; PrimaryTerm newTerm = new PrimaryTerm ( term , primary , candidates ) ; if ( ! Objects . equals ( currentTerm , newTerm ) ) { this . currentTerm = newTerm ; LOGGER . debug ( "{} - Recomputed term for partition {}: {}" , clusterMembershipService . getLocalMember ( ) . id ( ) , partitionId , newTerm ) ; post ( new PrimaryElectionEvent ( PrimaryElectionEvent . Type . CHANGED , partitionId , newTerm ) ) ; broadcastCounters ( ) ; } }
Recomputes the current term.