Search in sources :

Example 26 with AssignmentInfo

use of org.apache.kafka.streams.processor.internals.assignment.AssignmentInfo in project kafka by apache.

the class StreamPartitionAssignorTest method testAssignWithPartialTopology.

@Test
public void testAssignWithPartialTopology() throws Exception {
    Properties props = configProps();
    props.put(StreamsConfig.PARTITION_GROUPER_CLASS_CONFIG, SingleGroupPartitionGrouperStub.class);
    StreamsConfig config = new StreamsConfig(props);
    builder.addSource("source1", "topic1");
    builder.addProcessor("processor1", new MockProcessorSupplier(), "source1");
    builder.addStateStore(new MockStateStoreSupplier("store1", false), "processor1");
    builder.addSource("source2", "topic2");
    builder.addProcessor("processor2", new MockProcessorSupplier(), "source2");
    builder.addStateStore(new MockStateStoreSupplier("store2", false), "processor2");
    List<String> topics = Utils.mkList("topic1", "topic2");
    Set<TaskId> allTasks = Utils.mkSet(task0, task1, task2);
    UUID uuid1 = UUID.randomUUID();
    String client1 = "client1";
    StreamThread thread10 = new StreamThread(builder, config, mockClientSupplier, "test", client1, uuid1, new Metrics(), Time.SYSTEM, new StreamsMetadataState(builder, StreamsMetadataState.UNKNOWN_HOST), 0);
    partitionAssignor.configure(config.getConsumerConfigs(thread10, "test", client1));
    partitionAssignor.setInternalTopicManager(new MockInternalTopicManager(thread10.config, mockClientSupplier.restoreConsumer));
    Map<String, PartitionAssignor.Subscription> subscriptions = new HashMap<>();
    subscriptions.put("consumer10", new PartitionAssignor.Subscription(topics, new SubscriptionInfo(uuid1, Collections.<TaskId>emptySet(), Collections.<TaskId>emptySet(), userEndPoint).encode()));
    // will throw exception if it fails
    Map<String, PartitionAssignor.Assignment> assignments = partitionAssignor.assign(metadata, subscriptions);
    // check assignment info
    Set<TaskId> allActiveTasks = new HashSet<>();
    AssignmentInfo info10 = checkAssignment(Utils.mkSet("topic1"), assignments.get("consumer10"));
    allActiveTasks.addAll(info10.activeTasks);
    assertEquals(3, allActiveTasks.size());
    assertEquals(allTasks, new HashSet<>(allActiveTasks));
}
Also used : TaskId(org.apache.kafka.streams.processor.TaskId) HashMap(java.util.HashMap) MockInternalTopicManager(org.apache.kafka.test.MockInternalTopicManager) SubscriptionInfo(org.apache.kafka.streams.processor.internals.assignment.SubscriptionInfo) Properties(java.util.Properties) AssignmentInfo(org.apache.kafka.streams.processor.internals.assignment.AssignmentInfo) Metrics(org.apache.kafka.common.metrics.Metrics) MockProcessorSupplier(org.apache.kafka.test.MockProcessorSupplier) MockStateStoreSupplier(org.apache.kafka.test.MockStateStoreSupplier) PartitionAssignor(org.apache.kafka.clients.consumer.internals.PartitionAssignor) UUID(java.util.UUID) StreamsConfig(org.apache.kafka.streams.StreamsConfig) HashSet(java.util.HashSet) Test(org.junit.Test)

Example 27 with AssignmentInfo

use of org.apache.kafka.streams.processor.internals.assignment.AssignmentInfo in project apache-kafka-on-k8s by banzaicloud.

the class StreamsPartitionAssignor method assign.

/*
     * This assigns tasks to consumer clients in the following steps.
     *
     * 0. check all repartition source topics and use internal topic manager to make sure
     *    they have been created with the right number of partitions.
     *
     * 1. using user customized partition grouper to generate tasks along with their
     *    assigned partitions; also make sure that the task's corresponding changelog topics
     *    have been created with the right number of partitions.
     *
     * 2. using TaskAssignor to assign tasks to consumer clients.
     *    - Assign a task to a client which was running it previously.
     *      If there is no such client, assign a task to a client which has its valid local state.
     *    - A client may have more than one stream threads.
     *      The assignor tries to assign tasks to a client proportionally to the number of threads.
     *    - We try not to assign the same set of tasks to two different clients
     *    We do the assignment in one-pass. The result may not satisfy above all.
     *
     * 3. within each client, tasks are assigned to consumer clients in round-robin manner.
     */
@Override
public Map<String, Assignment> assign(final Cluster metadata, final Map<String, Subscription> subscriptions) {
    // construct the client metadata from the decoded subscription info
    final Map<UUID, ClientMetadata> clientsMetadata = new HashMap<>();
    int minUserMetadataVersion = SubscriptionInfo.LATEST_SUPPORTED_VERSION;
    for (final Map.Entry<String, Subscription> entry : subscriptions.entrySet()) {
        final String consumerId = entry.getKey();
        final Subscription subscription = entry.getValue();
        final SubscriptionInfo info = SubscriptionInfo.decode(subscription.userData());
        final int usedVersion = info.version();
        if (usedVersion > SubscriptionInfo.LATEST_SUPPORTED_VERSION) {
            throw new IllegalStateException("Unknown metadata version: " + usedVersion + "; latest supported version: " + SubscriptionInfo.LATEST_SUPPORTED_VERSION);
        }
        if (usedVersion < minUserMetadataVersion) {
            minUserMetadataVersion = usedVersion;
        }
        // create the new client metadata if necessary
        ClientMetadata clientMetadata = clientsMetadata.get(info.processId());
        if (clientMetadata == null) {
            clientMetadata = new ClientMetadata(info.userEndPoint());
            clientsMetadata.put(info.processId(), clientMetadata);
        }
        // add the consumer to the client
        clientMetadata.addConsumer(consumerId, info);
    }
    log.debug("Constructed client metadata {} from the member subscriptions.", clientsMetadata);
    // ---------------- Step Zero ---------------- //
    // parse the topology to determine the repartition source topics,
    // making sure they are created with the number of partitions as
    // the maximum of the depending sub-topologies source topics' number of partitions
    final Map<Integer, InternalTopologyBuilder.TopicsInfo> topicGroups = taskManager.builder().topicGroups();
    final Map<String, InternalTopicMetadata> repartitionTopicMetadata = new HashMap<>();
    for (final InternalTopologyBuilder.TopicsInfo topicsInfo : topicGroups.values()) {
        for (final InternalTopicConfig topic : topicsInfo.repartitionSourceTopics.values()) {
            repartitionTopicMetadata.put(topic.name(), new InternalTopicMetadata(topic));
        }
    }
    boolean numPartitionsNeeded;
    do {
        numPartitionsNeeded = false;
        for (final InternalTopologyBuilder.TopicsInfo topicsInfo : topicGroups.values()) {
            for (final String topicName : topicsInfo.repartitionSourceTopics.keySet()) {
                int numPartitions = repartitionTopicMetadata.get(topicName).numPartitions;
                // try set the number of partitions for this repartition topic if it is not set yet
                if (numPartitions == UNKNOWN) {
                    for (final InternalTopologyBuilder.TopicsInfo otherTopicsInfo : topicGroups.values()) {
                        final Set<String> otherSinkTopics = otherTopicsInfo.sinkTopics;
                        if (otherSinkTopics.contains(topicName)) {
                            // use the maximum of all its source topic partitions as the number of partitions
                            for (final String sourceTopicName : otherTopicsInfo.sourceTopics) {
                                final Integer numPartitionsCandidate;
                                // map().join().join(map())
                                if (repartitionTopicMetadata.containsKey(sourceTopicName)) {
                                    numPartitionsCandidate = repartitionTopicMetadata.get(sourceTopicName).numPartitions;
                                } else {
                                    numPartitionsCandidate = metadata.partitionCountForTopic(sourceTopicName);
                                    if (numPartitionsCandidate == null) {
                                        repartitionTopicMetadata.get(topicName).numPartitions = NOT_AVAILABLE;
                                    }
                                }
                                if (numPartitionsCandidate != null && numPartitionsCandidate > numPartitions) {
                                    numPartitions = numPartitionsCandidate;
                                }
                            }
                        }
                    }
                    // another iteration is needed
                    if (numPartitions == UNKNOWN) {
                        numPartitionsNeeded = true;
                    } else {
                        repartitionTopicMetadata.get(topicName).numPartitions = numPartitions;
                    }
                }
            }
        }
    } while (numPartitionsNeeded);
    // ensure the co-partitioning topics within the group have the same number of partitions,
    // and enforce the number of partitions for those repartition topics to be the same if they
    // are co-partitioned as well.
    ensureCopartitioning(taskManager.builder().copartitionGroups(), repartitionTopicMetadata, metadata);
    // make sure the repartition source topics exist with the right number of partitions,
    // create these topics if necessary
    prepareTopic(repartitionTopicMetadata);
    // augment the metadata with the newly computed number of partitions for all the
    // repartition source topics
    final Map<TopicPartition, PartitionInfo> allRepartitionTopicPartitions = new HashMap<>();
    for (final Map.Entry<String, InternalTopicMetadata> entry : repartitionTopicMetadata.entrySet()) {
        final String topic = entry.getKey();
        final int numPartitions = entry.getValue().numPartitions;
        for (int partition = 0; partition < numPartitions; partition++) {
            allRepartitionTopicPartitions.put(new TopicPartition(topic, partition), new PartitionInfo(topic, partition, null, new Node[0], new Node[0]));
        }
    }
    final Cluster fullMetadata = metadata.withPartitions(allRepartitionTopicPartitions);
    taskManager.setClusterMetadata(fullMetadata);
    log.debug("Created repartition topics {} from the parsed topology.", allRepartitionTopicPartitions.values());
    // ---------------- Step One ---------------- //
    // get the tasks as partition groups from the partition grouper
    final Set<String> allSourceTopics = new HashSet<>();
    final Map<Integer, Set<String>> sourceTopicsByGroup = new HashMap<>();
    for (final Map.Entry<Integer, InternalTopologyBuilder.TopicsInfo> entry : topicGroups.entrySet()) {
        allSourceTopics.addAll(entry.getValue().sourceTopics);
        sourceTopicsByGroup.put(entry.getKey(), entry.getValue().sourceTopics);
    }
    final Map<TaskId, Set<TopicPartition>> partitionsForTask = partitionGrouper.partitionGroups(sourceTopicsByGroup, fullMetadata);
    // check if all partitions are assigned, and there are no duplicates of partitions in multiple tasks
    final Set<TopicPartition> allAssignedPartitions = new HashSet<>();
    final Map<Integer, Set<TaskId>> tasksByTopicGroup = new HashMap<>();
    for (final Map.Entry<TaskId, Set<TopicPartition>> entry : partitionsForTask.entrySet()) {
        final Set<TopicPartition> partitions = entry.getValue();
        for (final TopicPartition partition : partitions) {
            if (allAssignedPartitions.contains(partition)) {
                log.warn("Partition {} is assigned to more than one tasks: {}", partition, partitionsForTask);
            }
        }
        allAssignedPartitions.addAll(partitions);
        final TaskId id = entry.getKey();
        Set<TaskId> ids = tasksByTopicGroup.get(id.topicGroupId);
        if (ids == null) {
            ids = new HashSet<>();
            tasksByTopicGroup.put(id.topicGroupId, ids);
        }
        ids.add(id);
    }
    for (final String topic : allSourceTopics) {
        final List<PartitionInfo> partitionInfoList = fullMetadata.partitionsForTopic(topic);
        if (!partitionInfoList.isEmpty()) {
            for (final PartitionInfo partitionInfo : partitionInfoList) {
                final TopicPartition partition = new TopicPartition(partitionInfo.topic(), partitionInfo.partition());
                if (!allAssignedPartitions.contains(partition)) {
                    log.warn("Partition {} is not assigned to any tasks: {}", partition, partitionsForTask);
                }
            }
        } else {
            log.warn("No partitions found for topic {}", topic);
        }
    }
    // add tasks to state change log topic subscribers
    final Map<String, InternalTopicMetadata> changelogTopicMetadata = new HashMap<>();
    for (final Map.Entry<Integer, InternalTopologyBuilder.TopicsInfo> entry : topicGroups.entrySet()) {
        final int topicGroupId = entry.getKey();
        final Map<String, InternalTopicConfig> stateChangelogTopics = entry.getValue().stateChangelogTopics;
        for (final InternalTopicConfig topicConfig : stateChangelogTopics.values()) {
            // the expected number of partitions is the max value of TaskId.partition + 1
            int numPartitions = UNKNOWN;
            if (tasksByTopicGroup.get(topicGroupId) != null) {
                for (final TaskId task : tasksByTopicGroup.get(topicGroupId)) {
                    if (numPartitions < task.partition + 1)
                        numPartitions = task.partition + 1;
                }
                final InternalTopicMetadata topicMetadata = new InternalTopicMetadata(topicConfig);
                topicMetadata.numPartitions = numPartitions;
                changelogTopicMetadata.put(topicConfig.name(), topicMetadata);
            } else {
                log.debug("No tasks found for topic group {}", topicGroupId);
            }
        }
    }
    prepareTopic(changelogTopicMetadata);
    log.debug("Created state changelog topics {} from the parsed topology.", changelogTopicMetadata.values());
    // ---------------- Step Two ---------------- //
    // assign tasks to clients
    final Map<UUID, ClientState> states = new HashMap<>();
    for (final Map.Entry<UUID, ClientMetadata> entry : clientsMetadata.entrySet()) {
        states.put(entry.getKey(), entry.getValue().state);
    }
    log.debug("Assigning tasks {} to clients {} with number of replicas {}", partitionsForTask.keySet(), states, numStandbyReplicas);
    final StickyTaskAssignor<UUID> taskAssignor = new StickyTaskAssignor<>(states, partitionsForTask.keySet());
    taskAssignor.assign(numStandbyReplicas);
    log.info("Assigned tasks to clients as {}.", states);
    // ---------------- Step Three ---------------- //
    // construct the global partition assignment per host map
    final Map<HostInfo, Set<TopicPartition>> partitionsByHostState = new HashMap<>();
    if (minUserMetadataVersion == 2) {
        for (final Map.Entry<UUID, ClientMetadata> entry : clientsMetadata.entrySet()) {
            final HostInfo hostInfo = entry.getValue().hostInfo;
            if (hostInfo != null) {
                final Set<TopicPartition> topicPartitions = new HashSet<>();
                final ClientState state = entry.getValue().state;
                for (final TaskId id : state.activeTasks()) {
                    topicPartitions.addAll(partitionsForTask.get(id));
                }
                partitionsByHostState.put(hostInfo, topicPartitions);
            }
        }
    }
    taskManager.setPartitionsByHostState(partitionsByHostState);
    // within the client, distribute tasks to its owned consumers
    final Map<String, Assignment> assignment = new HashMap<>();
    for (final Map.Entry<UUID, ClientMetadata> entry : clientsMetadata.entrySet()) {
        final Set<String> consumers = entry.getValue().consumers;
        final ClientState state = entry.getValue().state;
        final List<List<TaskId>> interleavedActive = interleaveTasksByGroupId(state.activeTasks(), consumers.size());
        final List<List<TaskId>> interleavedStandby = interleaveTasksByGroupId(state.standbyTasks(), consumers.size());
        int consumerTaskIndex = 0;
        for (final String consumer : consumers) {
            final Map<TaskId, Set<TopicPartition>> standby = new HashMap<>();
            final ArrayList<AssignedPartition> assignedPartitions = new ArrayList<>();
            final List<TaskId> assignedActiveList = interleavedActive.get(consumerTaskIndex);
            for (final TaskId taskId : assignedActiveList) {
                for (final TopicPartition partition : partitionsForTask.get(taskId)) {
                    assignedPartitions.add(new AssignedPartition(taskId, partition));
                }
            }
            if (!state.standbyTasks().isEmpty()) {
                final List<TaskId> assignedStandbyList = interleavedStandby.get(consumerTaskIndex);
                for (final TaskId taskId : assignedStandbyList) {
                    Set<TopicPartition> standbyPartitions = standby.get(taskId);
                    if (standbyPartitions == null) {
                        standbyPartitions = new HashSet<>();
                        standby.put(taskId, standbyPartitions);
                    }
                    standbyPartitions.addAll(partitionsForTask.get(taskId));
                }
            }
            consumerTaskIndex++;
            Collections.sort(assignedPartitions);
            final List<TaskId> active = new ArrayList<>();
            final List<TopicPartition> activePartitions = new ArrayList<>();
            for (final AssignedPartition partition : assignedPartitions) {
                active.add(partition.taskId);
                activePartitions.add(partition.partition);
            }
            // finally, encode the assignment before sending back to coordinator
            assignment.put(consumer, new Assignment(activePartitions, new AssignmentInfo(minUserMetadataVersion, active, standby, partitionsByHostState).encode()));
        }
    }
    return assignment;
}
Also used : ClientState(org.apache.kafka.streams.processor.internals.assignment.ClientState) HashMap(java.util.HashMap) Node(org.apache.kafka.common.Node) ArrayList(java.util.ArrayList) SubscriptionInfo(org.apache.kafka.streams.processor.internals.assignment.SubscriptionInfo) StickyTaskAssignor(org.apache.kafka.streams.processor.internals.assignment.StickyTaskAssignor) AssignmentInfo(org.apache.kafka.streams.processor.internals.assignment.AssignmentInfo) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) List(java.util.List) PartitionInfo(org.apache.kafka.common.PartitionInfo) UUID(java.util.UUID) HashSet(java.util.HashSet) TopicPartition(org.apache.kafka.common.TopicPartition) HashMap(java.util.HashMap) Map(java.util.Map) HashSet(java.util.HashSet) Set(java.util.Set) TaskId(org.apache.kafka.streams.processor.TaskId) Cluster(org.apache.kafka.common.Cluster) HostInfo(org.apache.kafka.streams.state.HostInfo)

Example 28 with AssignmentInfo

use of org.apache.kafka.streams.processor.internals.assignment.AssignmentInfo in project apache-kafka-on-k8s by banzaicloud.

the class StreamsPartitionAssignor method onAssignment.

/**
 * @throws TaskAssignmentException if there is no task id for one of the partitions specified
 */
@Override
public void onAssignment(final Assignment assignment) {
    final List<TopicPartition> partitions = new ArrayList<>(assignment.partitions());
    Collections.sort(partitions, PARTITION_COMPARATOR);
    final AssignmentInfo info = AssignmentInfo.decode(assignment.userData());
    final int usedVersion = info.version();
    // version 1 field
    final Map<TaskId, Set<TopicPartition>> activeTasks = new HashMap<>();
    // version 2 fields
    final Map<TopicPartition, PartitionInfo> topicToPartitionInfo = new HashMap<>();
    final Map<HostInfo, Set<TopicPartition>> partitionsByHost;
    switch(usedVersion) {
        case 1:
            processVersionOneAssignment(info, partitions, activeTasks);
            partitionsByHost = Collections.emptyMap();
            break;
        case 2:
            processVersionTwoAssignment(info, partitions, activeTasks, topicToPartitionInfo);
            partitionsByHost = info.partitionsByHost();
            break;
        default:
            throw new IllegalStateException("Unknown metadata version: " + usedVersion + "; latest supported version: " + AssignmentInfo.LATEST_SUPPORTED_VERSION);
    }
    taskManager.setClusterMetadata(Cluster.empty().withPartitions(topicToPartitionInfo));
    taskManager.setPartitionsByHostState(partitionsByHost);
    taskManager.setAssignmentMetadata(activeTasks, info.standbyTasks());
    taskManager.updateSubscriptionsFromAssignment(partitions);
}
Also used : TaskId(org.apache.kafka.streams.processor.TaskId) HashSet(java.util.HashSet) Set(java.util.Set) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) AssignmentInfo(org.apache.kafka.streams.processor.internals.assignment.AssignmentInfo) TopicPartition(org.apache.kafka.common.TopicPartition) PartitionInfo(org.apache.kafka.common.PartitionInfo) HostInfo(org.apache.kafka.streams.state.HostInfo)

Example 29 with AssignmentInfo

use of org.apache.kafka.streams.processor.internals.assignment.AssignmentInfo in project apache-kafka-on-k8s by banzaicloud.

the class StreamsPartitionAssignorTest method testAssignBasic.

@Test
public void testAssignBasic() throws Exception {
    builder.addSource(null, "source1", null, null, null, "topic1");
    builder.addSource(null, "source2", null, null, null, "topic2");
    builder.addProcessor("processor", new MockProcessorSupplier(), "source1", "source2");
    List<String> topics = Utils.mkList("topic1", "topic2");
    Set<TaskId> allTasks = Utils.mkSet(task0, task1, task2);
    final Set<TaskId> prevTasks10 = Utils.mkSet(task0);
    final Set<TaskId> prevTasks11 = Utils.mkSet(task1);
    final Set<TaskId> prevTasks20 = Utils.mkSet(task2);
    final Set<TaskId> standbyTasks10 = Utils.mkSet(task1);
    final Set<TaskId> standbyTasks11 = Utils.mkSet(task2);
    final Set<TaskId> standbyTasks20 = Utils.mkSet(task0);
    UUID uuid1 = UUID.randomUUID();
    UUID uuid2 = UUID.randomUUID();
    mockTaskManager(prevTasks10, standbyTasks10, uuid1, builder);
    configurePartitionAssignor(Collections.<String, Object>emptyMap());
    partitionAssignor.setInternalTopicManager(new MockInternalTopicManager(streamsConfig, mockClientSupplier.restoreConsumer));
    Map<String, PartitionAssignor.Subscription> subscriptions = new HashMap<>();
    subscriptions.put("consumer10", new PartitionAssignor.Subscription(topics, new SubscriptionInfo(uuid1, prevTasks10, standbyTasks10, userEndPoint).encode()));
    subscriptions.put("consumer11", new PartitionAssignor.Subscription(topics, new SubscriptionInfo(uuid1, prevTasks11, standbyTasks11, userEndPoint).encode()));
    subscriptions.put("consumer20", new PartitionAssignor.Subscription(topics, new SubscriptionInfo(uuid2, prevTasks20, standbyTasks20, userEndPoint).encode()));
    Map<String, PartitionAssignor.Assignment> assignments = partitionAssignor.assign(metadata, subscriptions);
    // check assigned partitions
    assertEquals(Utils.mkSet(Utils.mkSet(t1p0, t2p0), Utils.mkSet(t1p1, t2p1)), Utils.mkSet(new HashSet<>(assignments.get("consumer10").partitions()), new HashSet<>(assignments.get("consumer11").partitions())));
    assertEquals(Utils.mkSet(t1p2, t2p2), new HashSet<>(assignments.get("consumer20").partitions()));
    // check assignment info
    Set<TaskId> allActiveTasks = new HashSet<>();
    // the first consumer
    AssignmentInfo info10 = checkAssignment(allTopics, assignments.get("consumer10"));
    allActiveTasks.addAll(info10.activeTasks());
    // the second consumer
    AssignmentInfo info11 = checkAssignment(allTopics, assignments.get("consumer11"));
    allActiveTasks.addAll(info11.activeTasks());
    assertEquals(Utils.mkSet(task0, task1), allActiveTasks);
    // the third consumer
    AssignmentInfo info20 = checkAssignment(allTopics, assignments.get("consumer20"));
    allActiveTasks.addAll(info20.activeTasks());
    assertEquals(3, allActiveTasks.size());
    assertEquals(allTasks, new HashSet<>(allActiveTasks));
    assertEquals(3, allActiveTasks.size());
    assertEquals(allTasks, allActiveTasks);
}
Also used : TaskId(org.apache.kafka.streams.processor.TaskId) HashMap(java.util.HashMap) MockInternalTopicManager(org.apache.kafka.test.MockInternalTopicManager) SubscriptionInfo(org.apache.kafka.streams.processor.internals.assignment.SubscriptionInfo) AssignmentInfo(org.apache.kafka.streams.processor.internals.assignment.AssignmentInfo) MockProcessorSupplier(org.apache.kafka.test.MockProcessorSupplier) PartitionAssignor(org.apache.kafka.clients.consumer.internals.PartitionAssignor) UUID(java.util.UUID) HashSet(java.util.HashSet) StreamsBuilderTest(org.apache.kafka.streams.StreamsBuilderTest) Test(org.junit.Test)

Example 30 with AssignmentInfo

use of org.apache.kafka.streams.processor.internals.assignment.AssignmentInfo in project apache-kafka-on-k8s by banzaicloud.

the class StreamsPartitionAssignorTest method testOnAssignment.

@Test
public void testOnAssignment() throws Exception {
    configurePartitionAssignor(Collections.<String, Object>emptyMap());
    final List<TaskId> activeTaskList = Utils.mkList(task0, task3);
    final Map<TaskId, Set<TopicPartition>> activeTasks = new HashMap<>();
    final Map<TaskId, Set<TopicPartition>> standbyTasks = new HashMap<>();
    final Map<HostInfo, Set<TopicPartition>> hostState = Collections.singletonMap(new HostInfo("localhost", 9090), Utils.mkSet(t3p0, t3p3));
    activeTasks.put(task0, Utils.mkSet(t3p0));
    activeTasks.put(task3, Utils.mkSet(t3p3));
    standbyTasks.put(task1, Utils.mkSet(t3p1));
    standbyTasks.put(task2, Utils.mkSet(t3p2));
    final AssignmentInfo info = new AssignmentInfo(activeTaskList, standbyTasks, hostState);
    final PartitionAssignor.Assignment assignment = new PartitionAssignor.Assignment(Utils.mkList(t3p0, t3p3), info.encode());
    Capture<Cluster> capturedCluster = EasyMock.newCapture();
    taskManager.setPartitionsByHostState(hostState);
    EasyMock.expectLastCall();
    taskManager.setAssignmentMetadata(activeTasks, standbyTasks);
    EasyMock.expectLastCall();
    taskManager.setClusterMetadata(EasyMock.capture(capturedCluster));
    EasyMock.expectLastCall();
    EasyMock.replay(taskManager);
    partitionAssignor.onAssignment(assignment);
    EasyMock.verify(taskManager);
    assertEquals(Collections.singleton(t3p0.topic()), capturedCluster.getValue().topics());
    assertEquals(2, capturedCluster.getValue().partitionsForTopic(t3p0.topic()).size());
}
Also used : TaskId(org.apache.kafka.streams.processor.TaskId) HashSet(java.util.HashSet) Set(java.util.Set) HashMap(java.util.HashMap) Cluster(org.apache.kafka.common.Cluster) AssignmentInfo(org.apache.kafka.streams.processor.internals.assignment.AssignmentInfo) PartitionAssignor(org.apache.kafka.clients.consumer.internals.PartitionAssignor) HostInfo(org.apache.kafka.streams.state.HostInfo) StreamsBuilderTest(org.apache.kafka.streams.StreamsBuilderTest) Test(org.junit.Test)

Aggregations

AssignmentInfo (org.apache.kafka.streams.processor.internals.assignment.AssignmentInfo)46 TaskId (org.apache.kafka.streams.processor.TaskId)41 HashSet (java.util.HashSet)38 Test (org.junit.Test)35 HashMap (java.util.HashMap)29 TopicPartition (org.apache.kafka.common.TopicPartition)24 UUID (java.util.UUID)21 PartitionAssignor (org.apache.kafka.clients.consumer.internals.PartitionAssignor)21 SubscriptionInfo (org.apache.kafka.streams.processor.internals.assignment.SubscriptionInfo)20 HostInfo (org.apache.kafka.streams.state.HostInfo)17 Set (java.util.Set)16 MockInternalTopicManager (org.apache.kafka.test.MockInternalTopicManager)16 MockProcessorSupplier (org.apache.kafka.test.MockProcessorSupplier)16 Assignment (org.apache.kafka.clients.consumer.ConsumerPartitionAssignor.Assignment)15 GroupSubscription (org.apache.kafka.clients.consumer.ConsumerPartitionAssignor.GroupSubscription)14 Subscription (org.apache.kafka.clients.consumer.ConsumerPartitionAssignor.Subscription)14 ArrayList (java.util.ArrayList)12 Cluster (org.apache.kafka.common.Cluster)12 PartitionInfo (org.apache.kafka.common.PartitionInfo)10 StreamsBuilderTest (org.apache.kafka.streams.StreamsBuilderTest)10