@Override
    public void addNewBlockedNodes(Collection<BlockedNode> newNodes) {
        assertRunningInMainThread();

        if (newNodes.isEmpty()) {
            return;
        }

        BlockedNodeAdditionResult result = blocklistTracker.addNewBlockedNodes(newNodes);
        Collection<BlockedNode> newlyAddedNodes = result.getNewlyAddedNodes();
        Collection<BlockedNode> allNodes =
                Stream.concat(newlyAddedNodes.stream(), result.getMergedNodes().stream())
                        .collect(Collectors.toList());

        if (!newlyAddedNodes.isEmpty()) {
            if (log.isDebugEnabled()) {
                log.debug(
                        "Newly added {} blocked nodes, details: {}."
                                + " Total {} blocked nodes currently, details: {}.",
                        newlyAddedNodes.size(),
                        newlyAddedNodes,
                        blocklistTracker.getAllBlockedNodes().size(),
                        blocklistTracker.getAllBlockedNodes());
            } else {
                log.info(
                        "Newly added {} blocked nodes. Total {} blocked nodes currently.",
                        newlyAddedNodes.size(),
                        blocklistTracker.getAllBlockedNodes().size());
            }

            blocklistListeners.forEach(listener -> listener.notifyNewBlockedNodes(allNodes));
            blocklistContext.blockResources(newlyAddedNodes);
        } else if (!allNodes.isEmpty()) {
            blocklistListeners.forEach(listener -> listener.notifyNewBlockedNodes(allNodes));
        }
    }
@Test
    void testAddNewBlockedNodes() throws Exception {
        BlockedNode node1 = new BlockedNode("node1", "cause", 1L);
        BlockedNode node2 = new BlockedNode("node2", "cause", 1L);
        BlockedNode node2Update = new BlockedNode("node2", "cause", 2L);

        List<List<BlockedNode>> contextReceivedNodes = new ArrayList<>();

        TestBlocklistContext context =
                TestBlocklistContext.newBuilder()
                        .setBlockResourcesConsumer(
                                blockedNodes ->
                                        contextReceivedNodes.add(new ArrayList<>(blockedNodes)))
                        .build();
        TestBlocklistListener listener = new TestBlocklistListener();

        try (DefaultBlocklistHandler handler = createDefaultBlocklistHandler(context)) {
            handler.registerBlocklistListener(listener);
            assertThat(listener.listenerReceivedNodes).isEmpty();
            assertThat(contextReceivedNodes).isEmpty();

            // add node1, node2
            handler.addNewBlockedNodes(Arrays.asList(node1, node2));
            // check listener and context
            assertThat(listener.listenerReceivedNodes).hasSize(1);
            assertThat(listener.listenerReceivedNodes.get(0))
                    .containsExactlyInAnyOrder(node1, node2);
            assertThat(contextReceivedNodes).hasSize(1);
            assertThat(contextReceivedNodes.get(0)).containsExactlyInAnyOrder(node1, node2);

            // add node1, node2 again, should not notify context and listener
            assertThat(contextReceivedNodes).hasSize(1);
            assertThat(listener.listenerReceivedNodes).hasSize(1);

            // update node2, should notify listener, not notify context
            handler.addNewBlockedNodes(Collections.singleton(node2Update));
            assertThat(listener.listenerReceivedNodes).hasSize(2);
            assertThat(listener.listenerReceivedNodes.get(1)).containsExactly(node2Update);
            assertThat(contextReceivedNodes).hasSize(1);

            // register a new listener, will notify all items
            TestBlocklistListener listener2 = new TestBlocklistListener();
            handler.registerBlocklistListener(listener2);
            assertThat(listener2.listenerReceivedNodes).hasSize(1);
            assertThat(listener2.listenerReceivedNodes.get(0))
                    .containsExactlyInAnyOrder(node1, node2Update);
        }
    }