Skip to content

Commit

Permalink
✨ cron expression
Browse files Browse the repository at this point in the history
  • Loading branch information
hellokaton committed Apr 9, 2018
1 parent 6e50421 commit c35599d
Show file tree
Hide file tree
Showing 14 changed files with 1,926 additions and 3 deletions.
21 changes: 19 additions & 2 deletions src/main/java/com/blade/kit/BladeKit.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@
import com.blade.mvc.Const;
import com.blade.mvc.http.HttpMethod;
import com.blade.mvc.route.Route;
import com.blade.task.TaskStruct;
import com.blade.task.annotation.Cron;
import lombok.NoArgsConstructor;
import org.slf4j.Logger;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.net.URL;
import java.time.Duration;
import java.time.Instant;
Expand All @@ -27,6 +30,7 @@
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
* Blade kit
Expand Down Expand Up @@ -99,9 +103,22 @@ public static void injection(Ioc ioc, BeanDefine beanDefine) {

public static void injectionValue(Environment environment, BeanDefine beanDefine) {
ClassDefine classDefine = ClassDefine.create(beanDefine.getType());
List<ValueInjector> valueFileds = getValueInjectFields(environment, classDefine);
List<ValueInjector> valueFields = getValueInjectFields(environment, classDefine);
Object bean = beanDefine.getBean();
valueFileds.stream().forEach(fieldInjector -> fieldInjector.injection(bean));
valueFields.stream().forEach(fieldInjector -> fieldInjector.injection(bean));
}

public static List<TaskStruct> getTasks(Class<?> type) {
return Arrays.stream(type.getMethods())
.filter(m -> null != m.getAnnotation(Cron.class))
.map(m -> {
TaskStruct taskStruct = new TaskStruct();
taskStruct.setCron(m.getAnnotation(Cron.class));
taskStruct.setMethod(m);
taskStruct.setType(type);
return taskStruct;
})
.collect(Collectors.toList());
}

public static boolean isEmpty(Collection<?> c) {
Expand Down
45 changes: 44 additions & 1 deletion src/main/java/com/blade/server/netty/NettyServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
import com.blade.mvc.route.RouteMatcher;
import com.blade.mvc.ui.template.DefaultEngine;
import com.blade.server.Server;
import com.blade.task.TaskContext;
import com.blade.task.TaskStruct;
import com.blade.task.annotation.Cron;
import com.blade.task.cron.CronExecutorService;
import com.blade.task.cron.CronExpression;
import com.blade.task.cron.CronThreadPoolExecutor;
import com.blade.watcher.EnvironmentWatcher;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
Expand All @@ -39,7 +45,11 @@
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import java.util.stream.Stream;

import static com.blade.kit.BladeKit.getPrefixSymbol;
Expand All @@ -60,6 +70,7 @@ public class NettyServer implements Server {
private Channel channel;
private RouteBuilder routeBuilder;
private List<BeanProcessor> processors;
private List<TaskStruct> taskStructs = new ArrayList<>();

@Override
public void start(Blade blade, String[] args) throws Exception {
Expand Down Expand Up @@ -87,6 +98,7 @@ public void start(Blade blade, String[] args) throws Exception {

this.startServer(initStart);

this.startTask();
}

private void initIoc() {
Expand Down Expand Up @@ -115,9 +127,12 @@ private void initIoc() {
beanDefines.forEach(b -> {
BladeKit.injection(ioc, b);
BladeKit.injectionValue(environment, b);
List<TaskStruct> cronExpressions = BladeKit.getTasks(b.getType());
if (null != cronExpressions) {
taskStructs.addAll(cronExpressions);
}
});
}

this.processors.stream().sorted(new OrderComparator<>()).forEach(b -> b.processor(blade));
}

Expand Down Expand Up @@ -182,6 +197,34 @@ private void startServer(long startTime) throws Exception {
blade.eventManager().fireEvent(EventType.SERVER_STARTED, blade);
}

private void startTask() {
if (taskStructs.size() > 0) {
CronExecutorService cronExecutorService = new CronThreadPoolExecutor(taskStructs.size() / 2 + 1);
for (TaskStruct taskStruct : taskStructs) {
try {
Cron cron = taskStruct.getCron();
TaskContext taskContext = new TaskContext();
ScheduledFuture<?> future = cronExecutorService.schedule(() -> {
Object target = blade.ioc().getBean(taskStruct.getType());
Method method = taskStruct.getMethod();
try {
if (method.getParameterCount() == 1 && method.getParameterTypes()[0].equals(TaskContext.class)) {
taskStruct.getMethod().invoke(target, taskContext);
} else {
taskStruct.getMethod().invoke(target);
}
} catch (IllegalAccessException | InvocationTargetException e) {
log.error("Task method error", e);
}
}, new CronExpression(cron.value()), cron.delay());
taskContext.setFuture(future);
} catch (Exception e) {
log.error("", e);
}
}
Runtime.getRuntime().addShutdownHook(new Thread(cronExecutorService::shutdown));
}
}

private void parseCls(Class<?> clazz) {
if (null != clazz.getAnnotation(Bean.class) || null != clazz.getAnnotation(Value.class)) {
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/com/blade/task/TaskContext.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.blade.task;

import com.blade.task.cron.CronExpression;
import lombok.Setter;

import java.util.concurrent.ScheduledFuture;

/**
* @author biezhi
* @date 2018/4/9
*/
public class TaskContext {

@Setter
private ScheduledFuture<?> future;

public void stop() {
if (null != future) {
future.cancel(true);
}
}

}
14 changes: 14 additions & 0 deletions src/main/java/com/blade/task/TaskManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.blade.task;

import java.util.List;

/**
* @author biezhi
* @date 2018/4/9
*/
public final class TaskManager {

private List<TaskStruct> taskStructs;


}
20 changes: 20 additions & 0 deletions src/main/java/com/blade/task/TaskStruct.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.blade.task;

import com.blade.task.annotation.Cron;
import lombok.Data;

import java.lang.reflect.Method;

/**
* @author biezhi
* @date 2018/4/9
*/
@Data
public class TaskStruct {

private Cron cron;
private Method method;
private Class<?> type;
private boolean isRunning;

}
32 changes: 32 additions & 0 deletions src/main/java/com/blade/task/annotation/Cron.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.blade.task.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Cron expression
*
* @author biezhi
* @date 2018/4/9
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Cron {

/**
* cron expression
*
* @return
*/
String value();

/**
* Delay execution, unit millisecond, start the task by default.
*
* @return
*/
long delay() default 0;

}
29 changes: 29 additions & 0 deletions src/main/java/com/blade/task/cron/CronExecutorService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.blade.task.cron;

import com.blade.task.TaskContext;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledFuture;

/**
* Executor service that schedules a runnable task for execution via a cron expression.
*
* @author Paul Ferraro
*/
public interface CronExecutorService extends ExecutorService {

/**
* Schedules the specified task to execute according to the specified cron expression.
*
* @param task the Runnable task to schedule
* @param expression a cron expression
*/
ScheduledFuture<?> schedule(Runnable task, CronExpression expression, long delay);

// ScheduledFuture<?> schedule(Runnable task, TaskContext taskContext);

default ScheduledFuture<?> schedule(Runnable task, CronExpression expression) {
return this.schedule(task, expression, 0L);
}

}
Loading

0 comments on commit c35599d

Please sign in to comment.