com.github.edgar615.util.vertx.task.Task Maven / Gradle / Ivy
package com.github.edgar615.util.vertx.task;
import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* vert.x异步任务的工具类.
*
* taks大部分的设计都参考了linkedin的parseq实现.
*
* @author Edgar Date 2016/5/10
*/
public interface Task {
Logger LOGGER = LoggerFactory.getLogger(Task.class);
/**
* 返回任务的执行结果
*
* @return 结果
*/
T result();
/**
* 任务名称
*
* @return 名称
*/
String name();
/**
* 任务成功完成.
*
* @param result 任务的成功返回值
*/
void complete(T result);
/**
* 任务失败.
*
* @param throwable 任务的异常
*/
void fail(Throwable throwable);
/**
* 判断任务是否完成
*
* @return
*/
boolean isComplete();
/**
* 设置任务的回调函数
*
* @param handler
*/
void setHandler(Handler> handler);
/**
* 返回任务的回调函数
*
* @return hander
*/
Handler> completer();
// /**
// * 处理任务的日志.
// * 日志会一直在task中传播,所以通常只需要在task链的最后一个task上处理即可.
// *
// * @param traceHandler 日志的处理对象
// * @return task
// */
// Task onTrace(Consumer> traceHandler);
/**
* 创建一个异步任务.
* 该任务需要最后调用complete方法
*
* @param
* @return task
*/
public static Task create() {
return new BaseTask<>(Future.future());
}
/**
* 创建一个异步任务
*
* @param name 任务名称
* @param
* @return task
*/
public static Task create(String name) {
return new BaseTask<>(name, Future.future());
}
/**
* 基于Future创建一个异步任务.
*
* @param name 任务名称
* @param future Future
* @param
* @return task
*/
public static Task create(String name, Future future) {
return new BaseTask<>(name, future);
}
/**
* 基于Future创建一个异步任务.
*
* @param future Future
* @param
* @return task
*/
public static Task create(Future future) {
return new BaseTask<>(future);
}
/**
* 创建两个并行的任务.
*
* @param futureT1 任务1
* @param futureT2 任务2
* @param
* @param
* @return task
*/
public static Tuple2Task par(Future futureT1, Future futureT2) {
return new Tuple2TaskImpl<>(futureT1, futureT2);
}
/**
* 创建两个并行的任务.
*
* @param name 任务名
* @param futureT1 任务1
* @param futureT2 任务2
* @param
* @param
* @return task
*/
public static Tuple2Task par(String name, Future futureT1,
Future futureT2) {
return new Tuple2TaskImpl<>(name, futureT1, futureT2);
}
/**
* 创建三个并行的任务.
*
* @param futureT1 任务1
* @param futureT2 任务2
* @param futureT3 任务3
* @param
* @param
* @param
* @return task
*/
public static Tuple3Task par(Future futureT1, Future futureT2,
Future futureT3) {
return new Tuple3TaskImpl<>(futureT1, futureT2, futureT3);
}
/**
* 创建三个并行的任务.
*
* @param name 任务名
* @param futureT1 任务1
* @param futureT2 任务2
* @param futureT3 任务3
* @param
* @param
* @param
* @return task
*/
public static Tuple3Task par(String name, Future futureT1,
Future futureT2, Future futureT3) {
return new Tuple3TaskImpl<>(name, futureT1, futureT2, futureT3);
}
/**
* 创建四个并行的任务.
*
* @param futureT1 任务1
* @param futureT2 任务2
* @param futureT3 任务3
* @param futureT4 任务4
* @param
* @param
* @param
* @param
* @return task
*/
public static Tuple4Task par(Future futureT1, Future
futureT2, Future futureT3, Future futureT4) {
return new Tuple4TaskImpl<>(futureT1, futureT2, futureT3, futureT4);
}
/**
* 创建四个并行的任务.
*
* @param name 任务名
* @param futureT1 任务1
* @param futureT2 任务2
* @param futureT3 任务3
* @param futureT4 任务4
* @param
* @param
* @param
* @param
* @return task
*/
public static Tuple4Task par(String name, Future
futureT1, Future futureT2, Future futureT3, Future futureT4) {
return new Tuple4TaskImpl<>(name, futureT1, futureT2, futureT3, futureT4);
}
/**
* 创建五个并行的任务.
*
* @param futureT1 任务1
* @param futureT2 任务2
* @param futureT3 任务3
* @param futureT4 任务4
* @param futureT5 任务5
* @param
* @param
* @param
* @param
* @param
* @return task
*/
public static Tuple5Task par(Future futureT1,
Future futureT2,
Future futureT3,
Future futureT4,
Future futureT5) {
return new Tuple5TaskImpl<>(futureT1, futureT2, futureT3, futureT4, futureT5);
}
/**
* 创建五个并行的任务.
*
* @param name 任务名
* @param futureT1 任务1
* @param futureT2 任务2
* @param futureT3 任务3
* @param futureT4 任务4
* @param futureT5 任务5
* @param
* @param
* @param
* @param
* @param
* @return task
*/
public static Tuple5Task par(String name,
Future futureT1,
Future futureT2,
Future futureT3,
Future futureT4,
Future futureT5) {
return new Tuple5TaskImpl<>(name, futureT1, futureT2, futureT3, futureT4, futureT5);
}
/**
* 创建六个并行的任务.
*
* @param futureT1 任务1
* @param futureT2 任务2
* @param futureT3 任务3
* @param futureT4 任务4
* @param futureT5 任务5
* @param futureT6 任务6
* @param
* @param
* @param
* @param
* @param
* @param
* @return task
*/
public static Tuple6Task par(Future futureT1,
Future futureT2,
Future futureT3,
Future futureT4,
Future futureT5,
Future
futureT6) {
return new Tuple6TaskImpl<>(futureT1, futureT2, futureT3, futureT4, futureT5, futureT6);
}
/**
* 创建六个并行的任务.
*
* @param name 任务名
* @param futureT1 任务1
* @param futureT2 任务2
* @param futureT3 任务3
* @param futureT4 任务4
* @param futureT5 任务5
* @param futureT6 任务6
* @param
* @param
* @param
* @param
* @param
* @param
* @return task
*/
public static Tuple6Task par(String name,
Future futureT1,
Future futureT2,
Future futureT3,
Future futureT4,
Future futureT5,
Future
futureT6) {
return new Tuple6TaskImpl<>(name, futureT1, futureT2, futureT3, futureT4, futureT5,
futureT6);
}
/**
* 创建多个并行任务.
*
* @param futures 任务列表
* @param
* @return task
*/
public static Task> par(List> futures) {
return new ParTaskImpl<>(futures);
}
/**
* 创建多个并行任务.
*
* @param name 任务名
* @param futures 任务列表
* @param
* @return task
*/
public static Task> par(String name, List> futures) {
return new ParTaskImpl<>(name, futures);
}
/**
* 处理任务遇到的异常.
* 异常会一直在task中传播,所以通常只需要在task链的最后一个task上捕获即可。
*
* @param desc 任务描述
* @param consumer 异常处理对象
* @return task
*/
default Task onFailure(String desc, Consumer consumer) {
return new FusionTask<>(desc, this, (prev, next) -> {
prev.setHandler(ar -> {
Throwable throwable = ar.cause();
if (ar.succeeded()) {
next.complete(prev.result());
}
if (throwable != null) {
try {
consumer.accept(throwable);
LOGGER.debug("task->{} consumer throwable succeeded", prev.name());
} catch (Exception e) {
throwable = e;
LOGGER.debug("task->{} consumer throwable failed, error->{}", prev.name(),
throwable.getMessage());
}
next.fail(throwable);
}
});
});
}
/**
* 处理任务遇到的异常.
* 异常会一直在task中传播,所以通常只需要在task链的最后一个task上捕获即可。
*
* @param consumer 异常处理对象
* @return task
*/
default Task onFailure(Consumer consumer) {
return onFailure("onFailure: " + consumer.getClass().getName(), consumer);
}
/**
* 任务完成之后,将结果转换为其他对象.
*
* @param function function类
* @param 转换后的类型
* @return task
*/
default Task map(Function function) {
return mapWithFallback(function, null);
}
/**
* 任务完成之后,将结果转换为其他对象.
*
* @param function function类
* @param fallback 如果function出现异常,回退的操作
* @param 转换后的类型
* @return task
*/
default Task mapWithFallback(Function function,
BiFunction fallback) {
return mapWithFallback("map: " + function.getClass().getName(), function, fallback);
}
/**
* 任务完成之后,将结果转换为其他对象.
*
* @param desc 任务描述
* @param function function类
* @param 转换后的类型
* @return task
*/
default Task map(String desc, Function function) {
return mapWithFallback(desc, function, null);
}
/**
* 任务完成之后,将结果转换为其他对象.
*
* @param desc 任务描述
* @param function function类
* @param fallback 如果function出现异常,回退的操作
* @param 转换后的类型
* @return task
*/
default Task mapWithFallback(String desc, Function function,
BiFunction fallback) {
return new FusionTask<>(desc, this, (prev, next) -> {
prev.setHandler(ar -> {
if (ar.succeeded()) {
try {
next.complete(function.apply(ar.result()));
LOGGER.debug("task->{} map to task->{} succeeded", prev.name(), next.name());
} catch (Exception e) {
LOGGER.debug("task->{} map to task->{} failed, error->{}", prev.name(), next.name(),
e.getMessage());
if (fallback == null) {
next.fail(e);
} else {
try {
R apply = fallback.apply(e, ar.result());
next.complete(apply);
} catch (Exception e1) {
next.fail(e1);
}
}
}
} else {
next.fail(ar.cause());
}
});
});
}
/**
* 任务完成后,根据结果做一些额外操作.
*
* @param desc 任务描述
* @param consumer consumer类
* @param fallback 如果consumer出现异常,回退的操作
* @return task
*/
default Task andThenWithFallback(String desc, Consumer consumer,
BiConsumer fallback) {
BiFunction function = null;
if (fallback != null) {
function = (throwable, t) -> {
fallback.accept(throwable, t);
return t;
};
}
return mapWithFallback(desc, t -> {
consumer.accept(t);
return t;
}, function);
}
/**
* 任务完成后,根据结果做一些额外操作.
*
* @param desc 任务描述
* @param consumer consumer类
* @return task
*/
default Task andThen(String desc, Consumer consumer) {
return andThenWithFallback(desc, consumer, null);
}
/**
* 任务完成后,根据结果做一些额外操作.
*
* @param consumer consumer类
* @param fallback 如果consumer出现异常,回退的操作
* @return task
*/
default Task andThenWithFallback(Consumer consumer, BiConsumer fallback) {
return andThenWithFallback("andThen: " + consumer.getClass().getName(), consumer, fallback);
}
/**
* 任务完成后,根据结果做一些额外操作.
*
* @param consumer consumer类
* @return task
*/
default Task andThen(Consumer consumer) {
return andThenWithFallback(consumer, null);
}
/**
* 任务完成之后,让结果传递给另外一个任务执行,futureFunction用来使用结果创建一个新的任务.
*
* @param function function类,将结果转换为一个新的future
* @param 转换后的类型
* @return task
*/
default Task flatMap(Function> function) {
return flatMapWithFallback(function, null);
}
/**
* 任务完成之后,让结果传递给另外一个任务执行,futureFunction用来使用结果创建一个新的任务.
*
* @param function function类,将结果转换为一个新的future
* @param fallback 如果function出现异常,回退的操作. 这个回退操作,不再返回一个Future,而是直接返回一个特定的值
* @param 转换后的类型
* @return task
*/
default Task flatMapWithFallback(Function> function,
BiFunction fallback) {
return flatMapWithFallback("flatMap: " + function.getClass().getName(), function, fallback);
}
/**
* 任务完成之后,让结果传递给另外一个任务执行,futureFunction用来使用结果创建一个新的任务.
*
* @param desc 任务描述
* @param function function类,将结果转换为一个新的future
* @param
* @return
*/
default Task flatMap(String desc, Function> function) {
return flatMapWithFallback(desc, function, null);
}
/**
* 任务完成之后,让结果传递给另外一个任务执行,futureFunction用来使用结果创建一个新的任务.
*
* @param desc 任务描述
* @param function function类,将结果转换为一个新的future
* @param fallback 如果function出现异常,回退的操作. 这个回退操作,不再返回一个Future,而是直接返回一个特定的值
* @param
* @return
*/
default Task flatMapWithFallback(String desc, Function> function,
BiFunction fallback) {
return new FusionTask<>(desc, this, (prev, next) -> {
prev.setHandler(ar -> {
if (ar.succeeded()) {
try {
Future rFuture = function.apply(ar.result());
rFuture.setHandler(next.completer());
LOGGER.debug("task->{} flatMap to task->{} succeeded", prev.name(), next.name());
} catch (Exception e) {
LOGGER.debug("task->{} flatMap to task->{} failed, error->{}", prev.name(), next.name(),
e.getMessage());
if (fallback == null) {
next.fail(e);
} else {
try {
R apply = fallback.apply(e, ar.result());
next.complete(apply);
} catch (Exception e1) {
next.fail(e1);
}
}
}
} else {
next.fail(ar.cause());
}
});
});
}
/**
* 将task转换为一个Future
*
* @param
* @return future
*/
default Future toFutrue() {
Future future = Future.future();
andThen(t -> future.complete(t))
.onFailure(throwable -> future.fail(throwable));
return future;
}
}