运行 一项长期的 运行 工作,在 Reactor 和 r2dbc 中使用 Thymeleaf 的即发即弃策略
Run a long running job using the fire and forget strategy with Thymeleaf in Reactor and r2dbc
我正在尝试使用 webflux、thymeleaf 和 r2dbc 来实现一劳永逸的效果。我有两个端点,一个用于添加员工,另一个用于列出所有员工。我想模拟一个缓慢的数据库访问,所以在我调用数据库之前我有几秒钟的线程休眠。
现在,我希望在调用 /add
时看到的效果是我的控制器立即 return 并且页面 add
立即呈现。但是,我不确定如何实现这一目标。使用当前代码 nap()
发生在我可以 return 一个 Mono
之前。换句话说,我正在尝试 运行 在后台进行长时间的 运行ning 作业而不阻塞控制器。
我有以下型号:
@Data
public class Employee {
@Id
private Long id;
private String name;
}
带注释的控制器有以下方法:
@GetMapping(value = "/")
public String home(Model model) {
model.addAttribute("employees", repo.findAll());
return "home";
}
@GetMapping(value = "/add")
public Mono<String> add() {
return Mono
.defer(this::getEmployee)
.doOnNext(e -> repo.save(e).subscribe())
.thenReturn("add");
}
private Mono<Employee> getEmployee() {
final var e = new Employee();
e.setName("John");
nap(); // calls thread sleep for a few sec
return Mono.just(e);
}
我的问题是如何包装冗长的 运行ning 作业,同时保留基于控制器的符号(而不是功能性符号)并立即呈现 add
页面?我知道一些类似的问题,例如 and ,但我似乎无法实现我需要的行为。
编辑:
lkatiforis 的建议和 this SO 问题是朝着正确方向的推动。我不得不稍微调整他们的例子,因为员工没有坚持。更改在 add()
:
public String add() {
Mono.just(employee)
.delayElement(Duration.ofSeconds(5))
.doOnNext(e -> repo.save(e).subscribe())
.subscribe();
return "add";
}
employee
只是具有填充名称的 Employee
的一个实例。 delayElement
运算符暂停 5 秒而不阻塞。最后,我不得不在 repo.save()
上调用 subscribe()
并在最后调用它才能正常工作。我假设如果 subscribe()
只在 doOnNext()
上被调用,那么以 Mono.just()
开头的主链永远不会被执行。
我猜 nap()
方法执行 Thread.sleep
或类似的东西,对吧? Thread.sleep
正在阻塞主线程,使应用程序无响应。您可以使用 delayElements
运算符来模拟长 - 运行 操作:
private Mono<Employee> getEmployee() {
final var e = new Employee();
e.setName("John");
return Mono.just(e).delayElement(Duration.ofSeconds(5));
}
我正在尝试使用 webflux、thymeleaf 和 r2dbc 来实现一劳永逸的效果。我有两个端点,一个用于添加员工,另一个用于列出所有员工。我想模拟一个缓慢的数据库访问,所以在我调用数据库之前我有几秒钟的线程休眠。
现在,我希望在调用 /add
时看到的效果是我的控制器立即 return 并且页面 add
立即呈现。但是,我不确定如何实现这一目标。使用当前代码 nap()
发生在我可以 return 一个 Mono
之前。换句话说,我正在尝试 运行 在后台进行长时间的 运行ning 作业而不阻塞控制器。
我有以下型号:
@Data
public class Employee {
@Id
private Long id;
private String name;
}
带注释的控制器有以下方法:
@GetMapping(value = "/")
public String home(Model model) {
model.addAttribute("employees", repo.findAll());
return "home";
}
@GetMapping(value = "/add")
public Mono<String> add() {
return Mono
.defer(this::getEmployee)
.doOnNext(e -> repo.save(e).subscribe())
.thenReturn("add");
}
private Mono<Employee> getEmployee() {
final var e = new Employee();
e.setName("John");
nap(); // calls thread sleep for a few sec
return Mono.just(e);
}
我的问题是如何包装冗长的 运行ning 作业,同时保留基于控制器的符号(而不是功能性符号)并立即呈现 add
页面?我知道一些类似的问题,例如
编辑:
lkatiforis 的建议和 this SO 问题是朝着正确方向的推动。我不得不稍微调整他们的例子,因为员工没有坚持。更改在 add()
:
public String add() {
Mono.just(employee)
.delayElement(Duration.ofSeconds(5))
.doOnNext(e -> repo.save(e).subscribe())
.subscribe();
return "add";
}
employee
只是具有填充名称的 Employee
的一个实例。 delayElement
运算符暂停 5 秒而不阻塞。最后,我不得不在 repo.save()
上调用 subscribe()
并在最后调用它才能正常工作。我假设如果 subscribe()
只在 doOnNext()
上被调用,那么以 Mono.just()
开头的主链永远不会被执行。
我猜 nap()
方法执行 Thread.sleep
或类似的东西,对吧? Thread.sleep
正在阻塞主线程,使应用程序无响应。您可以使用 delayElements
运算符来模拟长 - 运行 操作:
private Mono<Employee> getEmployee() {
final var e = new Employee();
e.setName("John");
return Mono.just(e).delayElement(Duration.ofSeconds(5));
}