/* * Licensed to Crate under one or more contributor license agreements. * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. Crate licenses this file * to you under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may * obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. * * However, if you have executed another commercial license agreement * with Crate these terms will supersede the license and you may use the * software solely pursuant to the terms of the relevant commercial * agreement. */ package io.crate.jobs.transport; import io.crate.exceptions.ContextMissingException; import io.crate.executor.transport.kill.KillJobsRequest; import io.crate.executor.transport.kill.TransportKillJobsNodeAction; import io.crate.jobs.DummySubContext; import io.crate.jobs.JobContextService; import io.crate.jobs.JobExecutionContext; import io.crate.operation.collect.stats.JobsLogs; import io.crate.test.integration.CrateDummyClusterServiceUnitTest; import org.elasticsearch.Version; import org.elasticsearch.action.ActionListener; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.LocalTransportAddress; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.TransportService; import org.junit.Test; import org.mockito.stubbing.Answer; import java.util.Arrays; import java.util.UUID; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.*; public class NodeDisconnectJobMonitorServiceTest extends CrateDummyClusterServiceUnitTest { private JobContextService jobContextService() throws Exception { return new JobContextService(Settings.EMPTY, clusterService, new JobsLogs(() -> true)); } @Test public void testOnNodeDisconnectedKillsJobOriginatingFromThatNode() throws Exception { JobContextService jobContextService = jobContextService(); JobExecutionContext.Builder builder = jobContextService.newBuilder(UUID.randomUUID()); builder.addSubContext(new DummySubContext()); JobExecutionContext context = jobContextService.createContext(builder); ThreadPool threadPool = mock(ThreadPool.class); when(threadPool.schedule(any(TimeValue.class), anyString(), any(Runnable.class))).thenAnswer((Answer<Object>) invocation -> { ((Runnable) invocation.getArguments()[2]).run(); return null; }); NodeDisconnectJobMonitorService monitorService = new NodeDisconnectJobMonitorService( Settings.EMPTY, threadPool, jobContextService, mock(TransportService.class), mock(TransportKillJobsNodeAction.class)); monitorService.onNodeDisconnected(new DiscoveryNode( "node", LocalTransportAddress.buildUnique(), Version.CURRENT)); expectedException.expect(ContextMissingException.class); jobContextService.getContext(context.jobId()); } @Test public void testOnParticipatingNodeDisconnectedKillsJob() throws Exception { JobContextService jobContextService = jobContextService(); DiscoveryNode coordinator_node = new DiscoveryNode( "coordinator_node_id", LocalTransportAddress.buildUnique(), Version.CURRENT); DiscoveryNode data_node = new DiscoveryNode( "data_node_id", LocalTransportAddress.buildUnique(), Version.CURRENT); DiscoveryNodes discoveryNodes = DiscoveryNodes.builder() .localNodeId("coordinator_node_id") .add(coordinator_node) .add(data_node) .build(); JobExecutionContext.Builder builder = jobContextService.newBuilder(UUID.randomUUID(), coordinator_node.getId(), Arrays.asList(coordinator_node.getId(), data_node.getId())); builder.addSubContext(new DummySubContext()); jobContextService.createContext(builder); TransportKillJobsNodeAction killAction = mock(TransportKillJobsNodeAction.class); NodeDisconnectJobMonitorService monitorService = new NodeDisconnectJobMonitorService( Settings.EMPTY, mock(ThreadPool.class), jobContextService, mock(TransportService.class), killAction); monitorService.onNodeDisconnected(discoveryNodes.get("data_node_id")); verify(killAction, times(1)).broadcast( any(KillJobsRequest.class), any(ActionListener.class), eq(Arrays.asList(discoveryNodes.get("data_node_id").getId()))); } }