/** * 获取当前作业服务器运行时分片上下文. * * @return 当前作业服务器运行时分片上下文 */ public JobExecutionMultipleShardingContext getJobExecutionShardingContext() { JobExecutionMultipleShardingContext result = new JobExecutionMultipleShardingContext(); result.setJobName(jobConfiguration.getJobName()); result.setShardingTotalCount(configService.getShardingTotalCount()); List<Integer> shardingItems = shardingService.getLocalHostShardingItems(); if (configService.isFailover()) { List<Integer> failoverItems = failoverService.getLocalHostFailoverItems(); if (!failoverItems.isEmpty()) { result.setShardingItems(failoverItems); } else { shardingItems.removeAll(failoverService.getLocalHostTakeOffItems()); result.setShardingItems(shardingItems); } } else { result.setShardingItems(shardingItems); } boolean isMonitorExecution = configService.isMonitorExecution(); if (isMonitorExecution) { removeRunningItems(shardingItems); } result.setJobParameter(configService.getJobParameter()); result.setMonitorExecution(isMonitorExecution); result.setFetchDataCount(configService.getFetchDataCount()); if (result.getShardingItems().isEmpty()) { return result; } Map<Integer, String> shardingItemParameters = configService.getShardingItemParameters(); for (int each : result.getShardingItems()) { if (shardingItemParameters.containsKey(each)) { result.getShardingItemParameters().put(each, shardingItemParameters.get(each)); } } result.setOffsets(offsetService.getOffsets(result.getShardingItems())); return result; }
@Override public final void execute(final JobExecutionContext context) throws JobExecutionException { log.debug("Elastic job: job execute begin, job execution context:{}.", context); shardingService.shardingIfNecessary(); JobExecutionMultipleShardingContext shardingContext = executionContextService.getJobExecutionShardingContext(); if (executionService.misfireIfNecessary(shardingContext.getShardingItems())) { log.info( "Previous job is still running, new job will start after previous job completed. Misfired job had recorded."); return; } executionService.cleanPreviousExecutionInfo(); executeJobInternal(shardingContext); log.debug("Elastic job: execute normal completed, sharding context:{}.", shardingContext); while (!executionService.getMisfiredJobItems(shardingContext.getShardingItems()).isEmpty() && !stoped && !shardingService.isNeedSharding()) { log.debug("Elastic job: execute misfired job, sharding context:{}.", shardingContext); executionService.clearMisfire(shardingContext.getShardingItems()); executeJobInternal(shardingContext); log.debug("Elastic job: misfired job completed, sharding context:{}.", shardingContext); } if (configService.isFailover() && !stoped) { failoverService.failoverIfNecessary(); } log.debug("Elastic job: execute all completed, job execution context:{}.", context); }
@Test public void assertSetCrashedFailoverFlagWhenItemIsAssigned() { when(jobNodeStorage.isJobNodeExisted("execution/0/failover")).thenReturn(false); failoverService.setCrashedFailoverFlag(0); verify(jobNodeStorage).isJobNodeExisted("execution/0/failover"); verify(jobNodeStorage).createJobNodeIfNeeded("leader/failover/items/0"); }
@Test public void assertFailoverIfUnnecessaryWhenItemsRootNodeNotExisted() { when(jobNodeStorage.isJobNodeExisted("leader/failover/items")).thenReturn(false); failoverService.failoverIfNecessary(); verify(jobNodeStorage).isJobNodeExisted("leader/failover/items"); verify(jobNodeStorage, times(0)) .executeInLeader( eq("leader/failover/latch"), Matchers.<FailoverLeaderExecutionCallback>any()); }
@Test public void assertRemoveFailoverInfo() { when(jobNodeStorage.getJobNodeChildrenKeys("execution")) .thenReturn(Arrays.asList("0", "1", "2")); failoverService.removeFailoverInfo(); verify(jobNodeStorage).getJobNodeChildrenKeys("execution"); verify(jobNodeStorage).removeJobNodeIfExisted("execution/0/failover"); verify(jobNodeStorage).removeJobNodeIfExisted("execution/1/failover"); verify(jobNodeStorage).removeJobNodeIfExisted("execution/2/failover"); }
private void executeJobInternal(final JobExecutionMultipleShardingContext shardingContext) { if (shardingContext.getShardingItems().isEmpty()) { log.debug("Elastic job: sharding item is empty, job execution context:{}.", shardingContext); return; } executionService.registerJobBegin(shardingContext); executeJob(shardingContext); executionService.registerJobCompleted(shardingContext); if (configService.isFailover()) { failoverService.updateFailoverComplete(shardingContext.getShardingItems()); } }
@Test public void assertGetLocalHostTakeOffItems() { when(shardingService.getLocalHostShardingItems()).thenReturn(Arrays.asList(0, 1, 2)); when(jobNodeStorage.isJobNodeExisted("execution/0/failover")).thenReturn(true); when(jobNodeStorage.isJobNodeExisted("execution/1/failover")).thenReturn(true); when(jobNodeStorage.isJobNodeExisted("execution/2/failover")).thenReturn(false); assertThat(failoverService.getLocalHostTakeOffItems(), is(Arrays.asList(0, 1))); verify(shardingService).getLocalHostShardingItems(); verify(jobNodeStorage).isJobNodeExisted("execution/0/failover"); verify(jobNodeStorage).isJobNodeExisted("execution/1/failover"); verify(jobNodeStorage).isJobNodeExisted("execution/2/failover"); }
@Test public void assertFailoverIfUnnecessaryWhenItemsRootNodeIsEmpty() { when(jobNodeStorage.isJobNodeExisted("leader/failover/items")).thenReturn(true); when(jobNodeStorage.getJobNodeChildrenKeys("leader/failover/items")) .thenReturn(Collections.<String>emptyList()); failoverService.failoverIfNecessary(); verify(jobNodeStorage).isJobNodeExisted("leader/failover/items"); verify(jobNodeStorage).getJobNodeChildrenKeys("leader/failover/items"); verify(jobNodeStorage, times(0)) .executeInLeader( eq("leader/failover/latch"), Matchers.<FailoverLeaderExecutionCallback>any()); }
@Test public void assertFailoverIfNecessary() { when(jobNodeStorage.isJobNodeExisted("leader/failover/items")).thenReturn(true); when(jobNodeStorage.getJobNodeChildrenKeys("leader/failover/items")) .thenReturn(Arrays.asList("0", "1", "2")); when(serverService.isLocalhostServerReady()).thenReturn(true); failoverService.failoverIfNecessary(); verify(jobNodeStorage).isJobNodeExisted("leader/failover/items"); verify(jobNodeStorage).getJobNodeChildrenKeys("leader/failover/items"); verify(serverService).isLocalhostServerReady(); verify(jobNodeStorage) .executeInLeader( eq("leader/failover/latch"), Matchers.<FailoverLeaderExecutionCallback>any()); }
@Test public void assertGetLocalHostFailoverItems() { when(jobNodeStorage.getJobNodeChildrenKeys("execution")) .thenReturn(Arrays.asList("0", "1", "2")); when(jobNodeStorage.isJobNodeExisted("execution/0/failover")).thenReturn(true); when(jobNodeStorage.isJobNodeExisted("execution/1/failover")).thenReturn(true); when(jobNodeStorage.isJobNodeExisted("execution/2/failover")).thenReturn(false); when(jobNodeStorage.getJobNodeDataDirectly("execution/0/failover")).thenReturn("mockedIP"); when(jobNodeStorage.getJobNodeDataDirectly("execution/1/failover")).thenReturn("otherIP"); assertThat(failoverService.getLocalHostFailoverItems(), is(Collections.singletonList(0))); verify(jobNodeStorage).getJobNodeChildrenKeys("execution"); verify(localHostService).getIp(); verify(jobNodeStorage).isJobNodeExisted("execution/0/failover"); verify(jobNodeStorage).isJobNodeExisted("execution/1/failover"); verify(jobNodeStorage).getJobNodeDataDirectly("execution/0/failover"); verify(jobNodeStorage).getJobNodeDataDirectly("execution/1/failover"); }
@Test public void assertUpdateFailoverComplete() { failoverService.updateFailoverComplete(Arrays.asList(0, 1)); verify(jobNodeStorage).removeJobNodeIfExisted("execution/0/failover"); verify(jobNodeStorage).removeJobNodeIfExisted("execution/1/failover"); }