void maybeReconcile() {
        if (targetAssignmentReconciled()) {
            log.trace("Ignoring reconciliation attempt. Target assignment is equal to the " +
                    "current assignment.");
            return;
        }
        if (reconciliationInProgress) {
            log.trace("Ignoring reconciliation attempt. Another reconciliation is already in progress. Assignment {}" +
                    " will be handled in the next reconciliation loop.", currentTargetAssignment);
            return;
        }

        // Find the subset of the target assignment that can be resolved to topic names, and trigger a metadata update
        // if some topic IDs are not resolvable.
        SortedSet<TopicIdPartition> assignedTopicIdPartitions = findResolvableAssignmentAndTriggerMetadataUpdate();

        SortedSet<TopicPartition> ownedPartitions = new TreeSet<>(TOPIC_PARTITION_COMPARATOR);
        ownedPartitions.addAll(subscriptions.assignedPartitions());

        // Keep copy of assigned TopicPartitions created from the TopicIdPartitions that are
        // being reconciled. Needed for interactions with the centralized subscription state that
        // does not support topic IDs yet.
        SortedSet<TopicPartition> assignedTopicPartitions = toTopicPartitionSet(assignedTopicIdPartitions);

        // Check same assignment. Based on topic names for now, until topic IDs are properly
        // supported in the centralized subscription state object. Note that this check is
        // required to make sure that reconciliation is not triggered if the assignment ready to
        // be reconciled is the same as the current one (even though the member may remain
        // in RECONCILING state if it has some unresolved assignments).
        boolean sameAssignmentReceived = assignedTopicPartitions.equals(ownedPartitions);
        if (sameAssignmentReceived) {
            log.debug("Ignoring reconciliation attempt. Target assignment ready to reconcile {} " +
                    "is equal to the member current assignment {}.", assignedTopicPartitions, ownedPartitions);
            return;
        }

        markReconciliationInProgress();

        // Partitions to assign (not previously owned)
        SortedSet<TopicPartition> addedPartitions = new TreeSet<>(TOPIC_PARTITION_COMPARATOR);
        addedPartitions.addAll(assignedTopicPartitions);
        addedPartitions.removeAll(ownedPartitions);

        // Partitions to revoke
        SortedSet<TopicPartition> revokedPartitions = new TreeSet<>(TOPIC_PARTITION_COMPARATOR);
        revokedPartitions.addAll(ownedPartitions);
        revokedPartitions.removeAll(assignedTopicPartitions);

        log.info("Updating assignment with\n" +
                        "\tAssigned partitions:                       {}\n" +
                        "\tCurrent owned partitions:                  {}\n" +
                        "\tAdded partitions (assigned - owned):       {}\n" +
                        "\tRevoked partitions (owned - assigned):     {}\n",
                assignedTopicIdPartitions,
                ownedPartitions,
                addedPartitions,
                revokedPartitions
        );

        if (!maybeAbortReconciliation()) {
            revokeAndAssign(assignedTopicIdPartitions, revokedPartitions);
        }
    }
Reconcile the assignment that has been received from the server. If for some topics, the
topic ID cannot be matched to a topic name, a metadata update will be triggered and only
the subset of topics that are resolvable will be reconciled. Reconciliation will update
the subscription state.

<p>There are three conditions under which no reconciliation will be triggered:
 - We have already reconciled the assignment (the target assignment is the same as the current assignment).
 - Another reconciliation is already in progress.
 - There are topics that haven't been added to the current assignment yet, but all their topic IDs
   are missing from the target assignment.
clients/src/main/java/org/apache/kafka/clients/consumer/internals/ShareMembershipManager.java