Wenjun Ruan
5 months ago
committed by
GitHub
44 changed files with 672 additions and 849 deletions
@ -1,52 +0,0 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF 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. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.server.master.runner; |
||||
|
||||
import org.apache.dolphinscheduler.server.master.runner.execute.MasterTaskExecutor; |
||||
|
||||
import java.util.concurrent.BlockingQueue; |
||||
import java.util.concurrent.LinkedBlockingQueue; |
||||
|
||||
import org.springframework.stereotype.Component; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
@Component |
||||
public class GlobalMasterTaskExecuteRunnableQueue { |
||||
|
||||
private final BlockingQueue<MasterTaskExecutor> masterTaskExecutorBlockingQueue = |
||||
new LinkedBlockingQueue<>(); |
||||
|
||||
public boolean submitMasterTaskExecuteRunnable(MasterTaskExecutor masterTaskExecutor) { |
||||
return masterTaskExecutorBlockingQueue.offer(masterTaskExecutor); |
||||
} |
||||
|
||||
public MasterTaskExecutor takeMasterTaskExecuteRunnable() throws InterruptedException { |
||||
return masterTaskExecutorBlockingQueue.take(); |
||||
} |
||||
|
||||
public boolean removeMasterTaskExecuteRunnable(MasterTaskExecutor masterTaskExecutor) { |
||||
return masterTaskExecutorBlockingQueue.remove(masterTaskExecutor); |
||||
} |
||||
|
||||
public int size() { |
||||
return masterTaskExecutorBlockingQueue.size(); |
||||
} |
||||
|
||||
} |
@ -1,84 +0,0 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF 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. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.server.master.runner; |
||||
|
||||
import org.apache.dolphinscheduler.common.thread.BaseDaemonThread; |
||||
import org.apache.dolphinscheduler.server.master.runner.execute.MasterTaskExecutor; |
||||
import org.apache.dolphinscheduler.server.master.runner.execute.MasterTaskExecutorHolder; |
||||
import org.apache.dolphinscheduler.server.master.runner.execute.MasterTaskExecutorThreadPool; |
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean; |
||||
|
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
@Slf4j |
||||
@Component |
||||
public class GlobalMasterTaskExecuteRunnableQueueLooper extends BaseDaemonThread implements AutoCloseable { |
||||
|
||||
@Autowired |
||||
private GlobalMasterTaskExecuteRunnableQueue globalMasterTaskExecuteRunnableQueue; |
||||
|
||||
@Autowired |
||||
private MasterTaskExecutorThreadPool masterTaskExecutorThreadPool; |
||||
|
||||
private final AtomicBoolean RUNNING_FLAG = new AtomicBoolean(false); |
||||
|
||||
public GlobalMasterTaskExecuteRunnableQueueLooper() { |
||||
super("MasterDelayTaskExecuteRunnableDelayQueueLooper"); |
||||
} |
||||
|
||||
@Override |
||||
public synchronized void start() { |
||||
if (!RUNNING_FLAG.compareAndSet(false, true)) { |
||||
log.error("The MasterDelayTaskExecuteRunnableDelayQueueLooper already started, will not start again"); |
||||
return; |
||||
} |
||||
log.info("MasterDelayTaskExecuteRunnableDelayQueueLooper starting..."); |
||||
super.start(); |
||||
masterTaskExecutorThreadPool.start(); |
||||
log.info("MasterDelayTaskExecuteRunnableDelayQueueLooper started..."); |
||||
} |
||||
|
||||
@Override |
||||
public void run() { |
||||
while (RUNNING_FLAG.get()) { |
||||
try { |
||||
final MasterTaskExecutor masterTaskExecutor = |
||||
globalMasterTaskExecuteRunnableQueue.takeMasterTaskExecuteRunnable(); |
||||
masterTaskExecutorThreadPool.submitMasterTaskExecutor(masterTaskExecutor); |
||||
MasterTaskExecutorHolder.putMasterTaskExecuteRunnable(masterTaskExecutor); |
||||
} catch (InterruptedException ex) { |
||||
Thread.currentThread().interrupt(); |
||||
log.warn("MasterDelayTaskExecuteRunnableDelayQueueLooper has been interrupted, will stop loop"); |
||||
break; |
||||
} |
||||
} |
||||
log.info("MasterDelayTaskExecuteRunnableDelayQueueLooper stop loop..."); |
||||
} |
||||
|
||||
@Override |
||||
public void close() throws Exception { |
||||
if (RUNNING_FLAG.compareAndSet(true, false)) { |
||||
log.info("MasterDelayTaskExecuteRunnableDelayQueueLooper stopping..."); |
||||
log.info("MasterDelayTaskExecuteRunnableDelayQueueLooper stopped..."); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,25 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF 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. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.server.master.runner.execute; |
||||
|
||||
public interface IMasterTaskExecutorThreadPool<T extends MasterTaskExecutor> { |
||||
|
||||
boolean submitMasterTaskExecutor(T masterTaskExecutor); |
||||
|
||||
boolean removeMasterTaskExecutor(T masterTaskExecutor); |
||||
} |
@ -0,0 +1,58 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF 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. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.server.master.runner.execute; |
||||
|
||||
import org.apache.dolphinscheduler.common.thread.ThreadUtils; |
||||
import org.apache.dolphinscheduler.server.master.config.MasterConfig; |
||||
|
||||
import java.util.concurrent.ThreadPoolExecutor; |
||||
|
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
import org.springframework.stereotype.Component; |
||||
|
||||
@Slf4j |
||||
@Component |
||||
public class MasterAsyncTaskExecutorThreadPool implements IMasterTaskExecutorThreadPool<AsyncMasterTaskExecutor> { |
||||
|
||||
private final ThreadPoolExecutor threadPoolExecutor; |
||||
|
||||
public MasterAsyncTaskExecutorThreadPool(MasterConfig masterConfig) { |
||||
this.threadPoolExecutor = ThreadUtils.newDaemonFixedThreadExecutor("MasterAsyncTaskExecutorThreadPool", |
||||
masterConfig.getMasterSyncTaskExecutorThreadPoolSize()); |
||||
} |
||||
|
||||
@Override |
||||
public boolean submitMasterTaskExecutor(AsyncMasterTaskExecutor asyncMasterTaskExecutor) { |
||||
synchronized (MasterAsyncTaskExecutorThreadPool.class) { |
||||
// todo: check if the thread pool is overload
|
||||
threadPoolExecutor.submit(asyncMasterTaskExecutor); |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public boolean removeMasterTaskExecutor(AsyncMasterTaskExecutor asyncMasterTaskExecutor) { |
||||
return threadPoolExecutor.remove(asyncMasterTaskExecutor); |
||||
} |
||||
|
||||
// todo: remove this method, it's not a good idea to expose the ThreadPoolExecutor to out side.
|
||||
ThreadPoolExecutor getThreadPool() { |
||||
return threadPoolExecutor; |
||||
} |
||||
} |
@ -0,0 +1,59 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF 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. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.server.master.runner.execute; |
||||
|
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
@Slf4j |
||||
@Component |
||||
public class MasterTaskExecutorThreadPoolManager { |
||||
|
||||
@Autowired |
||||
private MasterSyncTaskExecutorThreadPool masterSyncTaskExecutorThreadPool; |
||||
|
||||
@Autowired |
||||
private MasterAsyncTaskExecutorThreadPool masterAsyncTaskExecutorThreadPool; |
||||
|
||||
public boolean submitMasterTaskExecutor(MasterTaskExecutor masterTaskExecutor) { |
||||
if (masterTaskExecutor instanceof SyncMasterTaskExecutor) { |
||||
return masterSyncTaskExecutorThreadPool |
||||
.submitMasterTaskExecutor((SyncMasterTaskExecutor) masterTaskExecutor); |
||||
} |
||||
if (masterTaskExecutor instanceof AsyncMasterTaskExecutor) { |
||||
return masterAsyncTaskExecutorThreadPool |
||||
.submitMasterTaskExecutor((AsyncMasterTaskExecutor) masterTaskExecutor); |
||||
} |
||||
throw new IllegalArgumentException("Unknown type of MasterTaskExecutor: " + masterTaskExecutor); |
||||
} |
||||
|
||||
public boolean removeMasterTaskExecutor(MasterTaskExecutor masterTaskExecutor) { |
||||
if (masterTaskExecutor instanceof SyncMasterTaskExecutor) { |
||||
return masterSyncTaskExecutorThreadPool |
||||
.removeMasterTaskExecutor((SyncMasterTaskExecutor) masterTaskExecutor); |
||||
} |
||||
if (masterTaskExecutor instanceof AsyncMasterTaskExecutor) { |
||||
return masterAsyncTaskExecutorThreadPool |
||||
.removeMasterTaskExecutor((AsyncMasterTaskExecutor) masterTaskExecutor); |
||||
} |
||||
throw new IllegalArgumentException("Unknown type of MasterTaskExecutor: " + masterTaskExecutor); |
||||
} |
||||
|
||||
} |
@ -1,72 +0,0 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF 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. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.plugin.task.api; |
||||
|
||||
import java.util.Collection; |
||||
import java.util.Map; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
public class TaskExecutionContextCacheManager { |
||||
|
||||
private TaskExecutionContextCacheManager() { |
||||
throw new IllegalStateException("Utility class"); |
||||
} |
||||
|
||||
/** |
||||
* taskInstance cache |
||||
*/ |
||||
private static final Map<Integer, TaskExecutionContext> taskRequestContextCache = new ConcurrentHashMap<>(); |
||||
|
||||
/** |
||||
* get taskInstance by taskInstance id |
||||
* |
||||
* @param taskInstanceId taskInstanceId |
||||
* @return taskInstance |
||||
*/ |
||||
|
||||
public static TaskExecutionContext getByTaskInstanceId(Integer taskInstanceId) { |
||||
return taskRequestContextCache.get(taskInstanceId); |
||||
} |
||||
|
||||
/** |
||||
* cache taskInstance |
||||
* |
||||
* @param request request |
||||
*/ |
||||
public static void cacheTaskExecutionContext(TaskExecutionContext request) { |
||||
taskRequestContextCache.put(request.getTaskInstanceId(), request); |
||||
} |
||||
|
||||
/** |
||||
* remove taskInstance by taskInstanceId |
||||
* |
||||
* @param taskInstanceId taskInstanceId |
||||
*/ |
||||
public static void removeByTaskInstanceId(Integer taskInstanceId) { |
||||
taskRequestContextCache.remove(taskInstanceId); |
||||
} |
||||
|
||||
public static boolean updateTaskExecutionContext(TaskExecutionContext request) { |
||||
taskRequestContextCache.computeIfPresent(request.getTaskInstanceId(), (k, v) -> request); |
||||
return taskRequestContextCache.containsKey(request.getTaskInstanceId()); |
||||
} |
||||
|
||||
public static Collection<TaskExecutionContext> getAllTaskRequestList() { |
||||
return taskRequestContextCache.values(); |
||||
} |
||||
} |
@ -1,70 +0,0 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF 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. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.server.worker.runner; |
||||
|
||||
import org.apache.dolphinscheduler.plugin.task.api.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.server.worker.config.TaskExecuteThreadsFullPolicy; |
||||
import org.apache.dolphinscheduler.server.worker.config.WorkerConfig; |
||||
import org.apache.dolphinscheduler.server.worker.metrics.WorkerServerMetrics; |
||||
|
||||
import java.util.concurrent.ArrayBlockingQueue; |
||||
import java.util.concurrent.BlockingQueue; |
||||
|
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
import org.springframework.stereotype.Component; |
||||
|
||||
@Slf4j |
||||
@Component |
||||
public class GlobalTaskInstanceWaitingQueue { |
||||
|
||||
private final WorkerConfig workerConfig; |
||||
|
||||
private final BlockingQueue<TaskExecutionContext> blockingQueue; |
||||
|
||||
public GlobalTaskInstanceWaitingQueue(WorkerConfig workerConfig) { |
||||
this.workerConfig = workerConfig; |
||||
this.blockingQueue = new ArrayBlockingQueue<>(workerConfig.getExecThreads()); |
||||
} |
||||
|
||||
public boolean addDispatchTask(TaskExecutionContext taskExecutionContext) { |
||||
if (workerConfig.getTaskExecuteThreadsFullPolicy() == TaskExecuteThreadsFullPolicy.CONTINUE) { |
||||
return blockingQueue.offer(taskExecutionContext); |
||||
} |
||||
|
||||
if (blockingQueue.size() > getQueueSize()) { |
||||
log.warn("Wait submit queue is full, will retry submit task later"); |
||||
WorkerServerMetrics.incWorkerSubmitQueueIsFullCount(); |
||||
return false; |
||||
} |
||||
return blockingQueue.offer(taskExecutionContext); |
||||
} |
||||
|
||||
public TaskExecutionContext take() throws InterruptedException { |
||||
return blockingQueue.take(); |
||||
} |
||||
|
||||
public void clearTask() { |
||||
blockingQueue.clear(); |
||||
} |
||||
|
||||
public int getQueueSize() { |
||||
return workerConfig.getExecThreads(); |
||||
} |
||||
|
||||
} |
@ -1,101 +0,0 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF 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. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.server.worker.runner; |
||||
|
||||
import org.apache.dolphinscheduler.common.thread.BaseDaemonThread; |
||||
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperate; |
||||
import org.apache.dolphinscheduler.plugin.task.api.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.plugin.task.api.TaskPluginManager; |
||||
import org.apache.dolphinscheduler.plugin.task.api.utils.LogUtils; |
||||
import org.apache.dolphinscheduler.server.worker.config.WorkerConfig; |
||||
import org.apache.dolphinscheduler.server.worker.registry.WorkerRegistryClient; |
||||
import org.apache.dolphinscheduler.server.worker.rpc.WorkerMessageSender; |
||||
|
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
@Slf4j |
||||
@Component |
||||
public class GlobalTaskInstanceWaitingQueueLooper extends BaseDaemonThread { |
||||
|
||||
@Autowired |
||||
private GlobalTaskInstanceWaitingQueue globalTaskInstanceWaitingQueue; |
||||
|
||||
@Autowired |
||||
private WorkerConfig workerConfig; |
||||
|
||||
@Autowired |
||||
private WorkerMessageSender workerMessageSender; |
||||
|
||||
@Autowired |
||||
private TaskPluginManager taskPluginManager; |
||||
|
||||
@Autowired |
||||
private WorkerManagerThread workerManager; |
||||
|
||||
@Autowired(required = false) |
||||
private StorageOperate storageOperate; |
||||
|
||||
@Autowired |
||||
private WorkerRegistryClient workerRegistryClient; |
||||
|
||||
protected GlobalTaskInstanceWaitingQueueLooper() { |
||||
super("GlobalTaskDispatchQueueLooper"); |
||||
} |
||||
|
||||
public synchronized void start() { |
||||
log.info("GlobalTaskDispatchQueueLooper starting"); |
||||
super.start(); |
||||
log.info("GlobalTaskDispatchQueueLooper started"); |
||||
} |
||||
|
||||
public void run() { |
||||
while (true) { |
||||
try { |
||||
TaskExecutionContext taskExecutionContext = globalTaskInstanceWaitingQueue.take(); |
||||
LogUtils.setTaskInstanceLogFullPathMDC(taskExecutionContext.getLogPath()); |
||||
LogUtils.setTaskInstanceIdMDC(taskExecutionContext.getTaskInstanceId()); |
||||
|
||||
WorkerTaskExecutor workerTaskExecutor = WorkerTaskExecutorFactoryBuilder |
||||
.createWorkerTaskExecutorFactory( |
||||
taskExecutionContext, |
||||
workerConfig, |
||||
workerMessageSender, |
||||
taskPluginManager, |
||||
storageOperate, |
||||
workerRegistryClient) |
||||
.createWorkerTaskExecutor(); |
||||
if (workerManager.offer(workerTaskExecutor)) { |
||||
log.info("Success submit WorkerDelayTaskExecuteRunnable to WorkerManagerThread's waiting queue"); |
||||
} |
||||
} catch (InterruptedException e) { |
||||
log.error("GlobalTaskDispatchQueueLooper interrupted"); |
||||
Thread.currentThread().interrupt(); |
||||
break; |
||||
} catch (Exception ex) { |
||||
log.error("GlobalTaskDispatchQueueLooper error", ex); |
||||
} finally { |
||||
LogUtils.removeTaskInstanceIdMDC(); |
||||
LogUtils.removeTaskInstanceLogFullPathMDC(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,91 +0,0 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF 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. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.server.worker.runner; |
||||
|
||||
import org.apache.dolphinscheduler.server.worker.metrics.WorkerServerMetrics; |
||||
|
||||
import java.util.Map; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
import java.util.concurrent.ExecutorService; |
||||
import java.util.concurrent.ThreadPoolExecutor; |
||||
|
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
import com.google.common.util.concurrent.FutureCallback; |
||||
import com.google.common.util.concurrent.Futures; |
||||
import com.google.common.util.concurrent.ListenableFuture; |
||||
import com.google.common.util.concurrent.ListeningExecutorService; |
||||
import com.google.common.util.concurrent.MoreExecutors; |
||||
|
||||
@Slf4j |
||||
public class WorkerExecService { |
||||
|
||||
private final ListeningExecutorService listeningExecutorService; |
||||
|
||||
private final ExecutorService execService; |
||||
|
||||
private final ConcurrentHashMap<Integer, WorkerTaskExecutor> taskExecuteThreadMap; |
||||
|
||||
public WorkerExecService(ExecutorService execService, |
||||
ConcurrentHashMap<Integer, WorkerTaskExecutor> taskExecuteThreadMap) { |
||||
this.execService = execService; |
||||
this.listeningExecutorService = MoreExecutors.listeningDecorator(this.execService); |
||||
this.taskExecuteThreadMap = taskExecuteThreadMap; |
||||
WorkerServerMetrics.registerWorkerTaskTotalGauge(taskExecuteThreadMap::size); |
||||
} |
||||
|
||||
public void submit(final WorkerTaskExecutor taskExecuteThread) { |
||||
taskExecuteThreadMap.put(taskExecuteThread.getTaskExecutionContext().getTaskInstanceId(), taskExecuteThread); |
||||
ListenableFuture future = this.listeningExecutorService.submit(taskExecuteThread); |
||||
FutureCallback futureCallback = new FutureCallback() { |
||||
|
||||
@Override |
||||
public void onSuccess(Object o) { |
||||
taskExecuteThreadMap.remove(taskExecuteThread.getTaskExecutionContext().getTaskInstanceId()); |
||||
} |
||||
|
||||
@Override |
||||
public void onFailure(Throwable throwable) { |
||||
log.error("task execute failed, processInstanceId:{}, taskInstanceId:{}", |
||||
taskExecuteThread.getTaskExecutionContext().getProcessInstanceId(), |
||||
taskExecuteThread.getTaskExecutionContext().getTaskInstanceId(), |
||||
throwable); |
||||
taskExecuteThreadMap.remove(taskExecuteThread.getTaskExecutionContext().getTaskInstanceId()); |
||||
} |
||||
}; |
||||
Futures.addCallback(future, futureCallback, this.listeningExecutorService); |
||||
} |
||||
|
||||
/** |
||||
* get thread pool queue size |
||||
* |
||||
* @return queue size |
||||
*/ |
||||
public int getThreadPoolQueueSize() { |
||||
return ((ThreadPoolExecutor) this.execService).getQueue().size(); |
||||
} |
||||
|
||||
public int getActiveExecThreadCount() { |
||||
return ((ThreadPoolExecutor) this.execService).getActiveCount(); |
||||
} |
||||
|
||||
public Map<Integer, WorkerTaskExecutor> getTaskExecuteThreadMap() { |
||||
return taskExecuteThreadMap; |
||||
} |
||||
|
||||
} |
@ -1,150 +0,0 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF 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. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.server.worker.runner; |
||||
|
||||
import org.apache.dolphinscheduler.common.constants.Constants; |
||||
import org.apache.dolphinscheduler.common.lifecycle.ServerLifeCycleManager; |
||||
import org.apache.dolphinscheduler.common.thread.ThreadUtils; |
||||
import org.apache.dolphinscheduler.common.utils.OSUtils; |
||||
import org.apache.dolphinscheduler.plugin.task.api.TaskExecutionContextCacheManager; |
||||
import org.apache.dolphinscheduler.server.worker.config.WorkerConfig; |
||||
import org.apache.dolphinscheduler.server.worker.metrics.WorkerServerMetrics; |
||||
|
||||
import java.util.concurrent.BlockingQueue; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
import java.util.concurrent.LinkedBlockingQueue; |
||||
|
||||
import javax.annotation.Nullable; |
||||
|
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
import org.springframework.stereotype.Component; |
||||
|
||||
/** |
||||
* Manage tasks |
||||
*/ |
||||
@Component |
||||
@Slf4j |
||||
public class WorkerManagerThread implements Runnable { |
||||
|
||||
private final BlockingQueue<WorkerTaskExecutor> waitSubmitQueue; |
||||
private final WorkerExecService workerExecService; |
||||
|
||||
private final int workerExecThreads; |
||||
|
||||
private final ConcurrentHashMap<Integer, WorkerTaskExecutor> taskExecuteThreadMap = new ConcurrentHashMap<>(); |
||||
|
||||
public WorkerManagerThread(WorkerConfig workerConfig) { |
||||
workerExecThreads = workerConfig.getExecThreads(); |
||||
this.waitSubmitQueue = new LinkedBlockingQueue<>(); |
||||
workerExecService = new WorkerExecService( |
||||
ThreadUtils.newDaemonFixedThreadExecutor("Worker-Execute-Thread", workerConfig.getExecThreads()), |
||||
taskExecuteThreadMap); |
||||
} |
||||
|
||||
public @Nullable WorkerTaskExecutor getTaskExecuteThread(Integer taskInstanceId) { |
||||
return taskExecuteThreadMap.get(taskInstanceId); |
||||
} |
||||
|
||||
/** |
||||
* get wait submit queue size |
||||
* |
||||
* @return queue size |
||||
*/ |
||||
public int getWaitSubmitQueueSize() { |
||||
return waitSubmitQueue.size(); |
||||
} |
||||
|
||||
/** |
||||
* get thread pool queue size |
||||
* |
||||
* @return queue size |
||||
*/ |
||||
public int getThreadPoolQueueSize() { |
||||
return workerExecService.getThreadPoolQueueSize(); |
||||
} |
||||
|
||||
/** |
||||
* Kill tasks that have not been executed, like delay task |
||||
* then send Response to Master, update the execution status of task instance |
||||
*/ |
||||
public void killTaskBeforeExecuteByInstanceId(Integer taskInstanceId) { |
||||
waitSubmitQueue.stream() |
||||
.filter(taskExecuteThread -> taskExecuteThread.getTaskExecutionContext() |
||||
.getTaskInstanceId() == taskInstanceId) |
||||
.forEach(waitSubmitQueue::remove); |
||||
} |
||||
|
||||
public boolean offer(WorkerTaskExecutor workerDelayTaskExecuteRunnable) { |
||||
return waitSubmitQueue.add(workerDelayTaskExecuteRunnable); |
||||
} |
||||
|
||||
public void start() { |
||||
log.info("Worker manager thread starting"); |
||||
Thread thread = new Thread(this, this.getClass().getName()); |
||||
thread.setDaemon(true); |
||||
thread.start(); |
||||
log.info("Worker manager thread started"); |
||||
} |
||||
|
||||
@Override |
||||
public void run() { |
||||
WorkerServerMetrics.registerWorkerCpuUsageGauge(OSUtils::cpuUsagePercentage); |
||||
WorkerServerMetrics.registerWorkerMemoryAvailableGauge(OSUtils::availablePhysicalMemorySize); |
||||
WorkerServerMetrics.registerWorkerMemoryUsageGauge(OSUtils::memoryUsagePercentage); |
||||
WorkerServerMetrics.registerWorkerExecuteQueueSizeGauge(workerExecService::getThreadPoolQueueSize); |
||||
WorkerServerMetrics.registerWorkerActiveExecuteThreadGauge(workerExecService::getActiveExecThreadCount); |
||||
|
||||
Thread.currentThread().setName("Worker-Execute-Manager-Thread"); |
||||
while (!ServerLifeCycleManager.isStopped()) { |
||||
try { |
||||
if (!ServerLifeCycleManager.isRunning()) { |
||||
Thread.sleep(Constants.SLEEP_TIME_MILLIS); |
||||
} |
||||
if (this.getThreadPoolQueueSize() <= workerExecThreads) { |
||||
WorkerTaskExecutor workerTaskExecutor = waitSubmitQueue.take(); |
||||
workerExecService.submit(workerTaskExecutor); |
||||
} else { |
||||
WorkerServerMetrics.incWorkerOverloadCount(); |
||||
log.info("Exec queue is full, waiting submit queue {}, waiting exec queue size {}", |
||||
this.getWaitSubmitQueueSize(), this.getThreadPoolQueueSize()); |
||||
ThreadUtils.sleep(Constants.SLEEP_TIME_MILLIS); |
||||
} |
||||
} catch (Exception e) { |
||||
log.error("An unexpected interrupt is happened, " |
||||
+ "the exception will be ignored and this thread will continue to run", e); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public void clearTask() { |
||||
waitSubmitQueue.clear(); |
||||
workerExecService.getTaskExecuteThreadMap().values().forEach(workerTaskExecuteRunnable -> { |
||||
int taskInstanceId = workerTaskExecuteRunnable.getTaskExecutionContext().getTaskInstanceId(); |
||||
try { |
||||
workerTaskExecuteRunnable.cancelTask(); |
||||
log.info("Cancel the taskInstance in worker {}", taskInstanceId); |
||||
} catch (Exception ex) { |
||||
log.error("Cancel the taskInstance error {}", taskInstanceId, ex); |
||||
} finally { |
||||
TaskExecutionContextCacheManager.removeByTaskInstanceId(taskInstanceId); |
||||
} |
||||
}); |
||||
workerExecService.getTaskExecuteThreadMap().clear(); |
||||
} |
||||
} |
@ -0,0 +1,54 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF 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. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.server.worker.runner; |
||||
|
||||
import java.util.Collection; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* Used to store all running and waiting {@link WorkerTaskExecutor}. If the task has been finished, it will be removed from the map. |
||||
*/ |
||||
public class WorkerTaskExecutorHolder { |
||||
|
||||
private static final Map<Integer, WorkerTaskExecutor> workerTaskExecutorMap = new HashMap<>(); |
||||
|
||||
public static void put(WorkerTaskExecutor workerTaskExecutor) { |
||||
int taskInstanceId = workerTaskExecutor.getTaskExecutionContext().getTaskInstanceId(); |
||||
if (workerTaskExecutorMap.containsKey(taskInstanceId)) { |
||||
throw new IllegalArgumentException("TaskInstance: " + taskInstanceId + " already exists"); |
||||
} |
||||
workerTaskExecutorMap.put(taskInstanceId, workerTaskExecutor); |
||||
} |
||||
|
||||
public static WorkerTaskExecutor get(int taskInstanceId) { |
||||
return workerTaskExecutorMap.get(taskInstanceId); |
||||
} |
||||
|
||||
public static WorkerTaskExecutor remove(int taskInstanceId) { |
||||
return workerTaskExecutorMap.remove(taskInstanceId); |
||||
} |
||||
|
||||
public static void clear() { |
||||
workerTaskExecutorMap.clear(); |
||||
} |
||||
|
||||
public static Collection<WorkerTaskExecutor> getAllTaskExecutor() { |
||||
return workerTaskExecutorMap.values(); |
||||
} |
||||
} |
@ -0,0 +1,96 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF 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. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.server.worker.runner; |
||||
|
||||
import org.apache.dolphinscheduler.common.thread.ThreadUtils; |
||||
import org.apache.dolphinscheduler.common.utils.OSUtils; |
||||
import org.apache.dolphinscheduler.server.worker.config.TaskExecuteThreadsFullPolicy; |
||||
import org.apache.dolphinscheduler.server.worker.config.WorkerConfig; |
||||
import org.apache.dolphinscheduler.server.worker.metrics.WorkerServerMetrics; |
||||
|
||||
import java.util.concurrent.ThreadPoolExecutor; |
||||
|
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
import org.springframework.stereotype.Component; |
||||
|
||||
@Component |
||||
@Slf4j |
||||
public class WorkerTaskExecutorThreadPool { |
||||
|
||||
private final ThreadPoolExecutor threadPoolExecutor; |
||||
|
||||
private final WorkerConfig workerConfig; |
||||
|
||||
public WorkerTaskExecutorThreadPool(WorkerConfig workerConfig) { |
||||
this.threadPoolExecutor = |
||||
ThreadUtils.newDaemonFixedThreadExecutor("WorkerTaskExecutorThreadPool", workerConfig.getExecThreads()); |
||||
this.workerConfig = workerConfig; |
||||
|
||||
WorkerServerMetrics.registerWorkerCpuUsageGauge(OSUtils::cpuUsagePercentage); |
||||
WorkerServerMetrics.registerWorkerMemoryAvailableGauge(OSUtils::availablePhysicalMemorySize); |
||||
WorkerServerMetrics.registerWorkerMemoryUsageGauge(OSUtils::memoryUsagePercentage); |
||||
WorkerServerMetrics.registerWorkerExecuteQueueSizeGauge( |
||||
() -> threadPoolExecutor.getQueue().size() - threadPoolExecutor.getActiveCount()); |
||||
WorkerServerMetrics.registerWorkerActiveExecuteThreadGauge(threadPoolExecutor::getActiveCount); |
||||
} |
||||
|
||||
public boolean submitWorkerTaskExecutor(WorkerTaskExecutor workerTaskExecutor) { |
||||
synchronized (WorkerTaskExecutorThreadPool.class) { |
||||
if (TaskExecuteThreadsFullPolicy.CONTINUE.equals(workerConfig.getTaskExecuteThreadsFullPolicy())) { |
||||
WorkerTaskExecutorHolder.put(workerTaskExecutor); |
||||
threadPoolExecutor.submit(workerTaskExecutor); |
||||
return true; |
||||
} |
||||
if (isOverload()) { |
||||
log.warn("WorkerTaskExecutorThreadPool is overload, cannot submit new WorkerTaskExecutor"); |
||||
WorkerServerMetrics.incWorkerSubmitQueueIsFullCount(); |
||||
return false; |
||||
} |
||||
WorkerTaskExecutorHolder.put(workerTaskExecutor); |
||||
threadPoolExecutor.submit(workerTaskExecutor); |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
public boolean isOverload() { |
||||
return threadPoolExecutor.getQueue().size() > 0; |
||||
} |
||||
|
||||
public int getWaitingTaskExecutorSize() { |
||||
return threadPoolExecutor.getQueue().size(); |
||||
} |
||||
|
||||
public int getRunningTaskExecutorSize() { |
||||
return threadPoolExecutor.getActiveCount(); |
||||
} |
||||
|
||||
/** |
||||
* Kill tasks that have not been executed, e.g. waiting in the queue |
||||
*/ |
||||
public void killTaskBeforeExecuteByInstanceId(Integer taskInstanceId) { |
||||
synchronized (WorkerTaskExecutorThreadPool.class) { |
||||
WorkerTaskExecutor workerTaskExecutor = WorkerTaskExecutorHolder.get(taskInstanceId); |
||||
threadPoolExecutor.remove(workerTaskExecutor); |
||||
} |
||||
} |
||||
|
||||
public void clearTask() { |
||||
threadPoolExecutor.getQueue().clear(); |
||||
} |
||||
} |
@ -0,0 +1,194 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF 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. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.server.worker.runner; |
||||
|
||||
import org.apache.dolphinscheduler.common.enums.ResUploadType; |
||||
import org.apache.dolphinscheduler.plugin.storage.api.StorageEntity; |
||||
import org.apache.dolphinscheduler.plugin.storage.api.StorageOperate; |
||||
import org.apache.dolphinscheduler.plugin.task.api.TaskCallBack; |
||||
import org.apache.dolphinscheduler.plugin.task.api.TaskExecutionContext; |
||||
import org.apache.dolphinscheduler.plugin.task.api.TaskPluginManager; |
||||
import org.apache.dolphinscheduler.server.worker.config.TaskExecuteThreadsFullPolicy; |
||||
import org.apache.dolphinscheduler.server.worker.config.WorkerConfig; |
||||
import org.apache.dolphinscheduler.server.worker.registry.WorkerRegistryClient; |
||||
import org.apache.dolphinscheduler.server.worker.rpc.WorkerMessageSender; |
||||
import org.apache.dolphinscheduler.spi.enums.ResourceType; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.List; |
||||
|
||||
import org.junit.jupiter.api.Assertions; |
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
class WorkerTaskExecutorThreadPoolTest { |
||||
|
||||
@Test |
||||
public void testIsOverload() { |
||||
WorkerConfig workerConfig = new WorkerConfig(); |
||||
workerConfig.setExecThreads(1); |
||||
workerConfig.setTaskExecuteThreadsFullPolicy(TaskExecuteThreadsFullPolicy.CONTINUE); |
||||
WorkerTaskExecutorThreadPool workerTaskExecutorThreadPool = new WorkerTaskExecutorThreadPool(workerConfig); |
||||
// submit 100 task, the thread pool size is 1
|
||||
// assert the overload should be true
|
||||
// assert the submitQueue should be 99
|
||||
for (int i = 0; i < 100; i++) { |
||||
boolean submitResult = |
||||
workerTaskExecutorThreadPool.submitWorkerTaskExecutor(new MockWorkerTaskExecutor(() -> { |
||||
try { |
||||
Thread.sleep(10_000L); |
||||
} catch (InterruptedException e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
})); |
||||
Assertions.assertTrue(submitResult); |
||||
} |
||||
Assertions.assertTrue(workerTaskExecutorThreadPool.isOverload()); |
||||
Assertions.assertEquals(99, workerTaskExecutorThreadPool.getWaitingTaskExecutorSize()); |
||||
Assertions.assertEquals(1, workerTaskExecutorThreadPool.getRunningTaskExecutorSize()); |
||||
} |
||||
|
||||
static class MockWorkerTaskExecutor extends WorkerTaskExecutor { |
||||
|
||||
private final Runnable runnable; |
||||
|
||||
protected MockWorkerTaskExecutor(Runnable runnable) { |
||||
super(TaskExecutionContext.builder().taskInstanceId((int) System.nanoTime()).build(), new WorkerConfig(), |
||||
new WorkerMessageSender(), new TaskPluginManager(), new StorageOperate() { |
||||
|
||||
@Override |
||||
public void createTenantDirIfNotExists(String tenantCode) { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public String getResDir(String tenantCode) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public String getUdfDir(String tenantCode) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public boolean mkdir(String tenantCode, String path) throws IOException { |
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public String getResourceFullName(String tenantCode, String fileName) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public String getResourceFileName(String tenantCode, String fullName) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public String getFileName(ResourceType resourceType, String tenantCode, String fileName) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public boolean exists(String fullName) { |
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public boolean delete(String filePath, boolean recursive) { |
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public boolean delete(String filePath, List<String> childrenPathArray, |
||||
boolean recursive) { |
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public boolean copy(String srcPath, String dstPath, boolean deleteSource, |
||||
boolean overwrite) { |
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public String getDir(ResourceType resourceType, String tenantCode) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public boolean upload(String tenantCode, String srcFile, String dstPath, boolean deleteSource, |
||||
boolean overwrite) { |
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public void download(String srcFilePath, String dstFile, boolean overwrite) { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public List<String> vimFile(String tenantCode, String filePath, int skipLineNums, |
||||
int limit) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public void deleteTenant(String tenantCode) { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public ResUploadType returnStorageType() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public List<StorageEntity> listFilesStatusRecursively(String path, String defaultPath, |
||||
String tenantCode, ResourceType type) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public List<StorageEntity> listFilesStatus(String path, String defaultPath, String tenantCode, |
||||
ResourceType type) throws Exception { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public StorageEntity getFileStatus(String path, String defaultPath, String tenantCode, |
||||
ResourceType type) throws Exception { |
||||
return null; |
||||
} |
||||
}, new WorkerRegistryClient()); |
||||
this.runnable = runnable; |
||||
} |
||||
|
||||
@Override |
||||
public void run() { |
||||
executeTask(new TaskCallbackImpl(null, null)); |
||||
} |
||||
|
||||
@Override |
||||
protected void executeTask(TaskCallBack taskCallBack) { |
||||
runnable.run(); |
||||
} |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue