从 Spring 引导资源执行和处理 Void @Async 操作
Executing and handling Void @Async operations from Spring Boot resources
Java 8 和 Spring 在此处引导 2.x。我有一个 RESTful 资源,它将启动一个长 运行ning 操作,在某些情况下可能需要 15 - 20 分钟才能完成。我 认为 我想在服务层中利用 @Async
注释,但我愿意接受任何好的、优雅的 Spring 精通引导的解决方案!
迄今为止我最好的尝试:
@RestController
@RequestMapping(path = "/v1/fizzbuzzes")
public class FizzbuzzResource {
@Autowired
private FizzbuzzService fizzbuzzService;
@Autowired
private FizzbuzzRepository fizzbuzzRepository;
@Autowired
@Qualifier("fizzbuzz.ids")
private List<String> fizzbuzzList;
@PostMapping("/{fizzbuzzId}")
public ResponseEntity<Void> runFizzbuzzOperations(@PathVariable String fizzbuzzId)
throws ExecutionException, InterruptedException {
ResponseEntity responseEntity;
// verify the fizzbuzzId is valid -- if it is, we process it
Optional<Fizzbuzz> fbOpt = fizzbuzzRepository.lookupMorph(fizzbuzzId);
if (fbOpt.isPresent()) {
fizzbuzzList.add(fizzbuzzId);
CompletableFuture<Void> future = fizzbuzzService.runAsync(fbOpt.get());
future.get();
// TODO: need help here
// TODO: decrement the list once the async has completed -- ONLY do once async has finished
fizzbuzzList.remove(fizzbuzzId);
// return success immediately (dont wait for the async processing)
responseEntity = ResponseEntity.ok().build();
} else {
responseEntity = ResponseEntity.notFound().build();
}
return responseEntity;
}
}
@Service
public class FizzbuzzService {
@Async
public CompletableFuture<Void> runAsync(Fizzbuzz fizzbuzz) {
// do something that can take 15 - 20 mins to complete
// it actually is writing a massive amount of data to the file system
// so there's nothing to really "return" so we just return null (?)
return CompletableFuture.completedFuture(null);
}
}
我认为我很接近,但我正在努力:
- 如何正确地 调用
fizzbuzzService.runAsync(...)
使其实际上 运行 是异步的,以便它下面的 ResponseEntity.ok().build()
运行s 立即,而不是像其他情况那样等待 ~15 分钟;和
- 如何在异步服务方法完成后立即运行
fizzbuzzList.remove(...)
(同样,大约 15 - 20 分钟后),但很快!;和
- 也许在异步操作上配置一些类型的超时,例如在 30 分钟后出现异常失败
谁能看出我哪里出错了?
- 删除对 CompletableFuture.get() 的调用。它等待未来完成。
- 将消费者传递给 thenAccept. You can find examples here。
- 超时,在Java 9,查看orTimeOut. Check this for example. If you check the article in previous link, in Java 8, there is no clean way of handling timeouts. You can set default timeout for entire application by providing custom async executor. Check this Whosebug问题解决。
Java 8 和 Spring 在此处引导 2.x。我有一个 RESTful 资源,它将启动一个长 运行ning 操作,在某些情况下可能需要 15 - 20 分钟才能完成。我 认为 我想在服务层中利用 @Async
注释,但我愿意接受任何好的、优雅的 Spring 精通引导的解决方案!
迄今为止我最好的尝试:
@RestController
@RequestMapping(path = "/v1/fizzbuzzes")
public class FizzbuzzResource {
@Autowired
private FizzbuzzService fizzbuzzService;
@Autowired
private FizzbuzzRepository fizzbuzzRepository;
@Autowired
@Qualifier("fizzbuzz.ids")
private List<String> fizzbuzzList;
@PostMapping("/{fizzbuzzId}")
public ResponseEntity<Void> runFizzbuzzOperations(@PathVariable String fizzbuzzId)
throws ExecutionException, InterruptedException {
ResponseEntity responseEntity;
// verify the fizzbuzzId is valid -- if it is, we process it
Optional<Fizzbuzz> fbOpt = fizzbuzzRepository.lookupMorph(fizzbuzzId);
if (fbOpt.isPresent()) {
fizzbuzzList.add(fizzbuzzId);
CompletableFuture<Void> future = fizzbuzzService.runAsync(fbOpt.get());
future.get();
// TODO: need help here
// TODO: decrement the list once the async has completed -- ONLY do once async has finished
fizzbuzzList.remove(fizzbuzzId);
// return success immediately (dont wait for the async processing)
responseEntity = ResponseEntity.ok().build();
} else {
responseEntity = ResponseEntity.notFound().build();
}
return responseEntity;
}
}
@Service
public class FizzbuzzService {
@Async
public CompletableFuture<Void> runAsync(Fizzbuzz fizzbuzz) {
// do something that can take 15 - 20 mins to complete
// it actually is writing a massive amount of data to the file system
// so there's nothing to really "return" so we just return null (?)
return CompletableFuture.completedFuture(null);
}
}
我认为我很接近,但我正在努力:
- 如何正确地 调用
fizzbuzzService.runAsync(...)
使其实际上 运行 是异步的,以便它下面的ResponseEntity.ok().build()
运行s 立即,而不是像其他情况那样等待 ~15 分钟;和 - 如何在异步服务方法完成后立即运行
fizzbuzzList.remove(...)
(同样,大约 15 - 20 分钟后),但很快!;和 - 也许在异步操作上配置一些类型的超时,例如在 30 分钟后出现异常失败
谁能看出我哪里出错了?
- 删除对 CompletableFuture.get() 的调用。它等待未来完成。
- 将消费者传递给 thenAccept. You can find examples here。
- 超时,在Java 9,查看orTimeOut. Check this for example. If you check the article in previous link, in Java 8, there is no clean way of handling timeouts. You can set default timeout for entire application by providing custom async executor. Check this Whosebug问题解决。