Vert.x检查Future状态时succeeded与isComplete均返回false问题求助
问题根因
核心原因是异步操作的时序问题:
- Vert.x的数据库操作是完全异步非阻塞的,你调用
executeBatch方法时,仅仅是将数据库操作请求提交到了内部队列,方法会立即返回,不会等待数据库实际执行完毕。你返回的promise.future()在方法返回时还处于未完成状态,只有数据库操作执行结束触发回调时,才会调用promise.complete()修改Future状态。 - 从你贴的日志也能验证时序:打印Future状态的时间是
11:42:41.709,而数据库插入成功的日志打印时间是11:42:41.914,检查状态的操作比数据库实际执行完成早了200ms,此时Future自然是未完成、未成功的状态。
注意事项
不要用同步的方式直接检查刚返回的异步Future的状态,异步操作的结果必须通过Future的回调函数、或者链式组合操作来获取。
改造方案
如果你需要在generateChildSerial执行完成后做后续处理/日志打印,可以给Future绑定onComplete回调,回调会在异步操作结束后自动触发:
createJob(context) .compose(jobID -> { LOG.debug("jobID "+jobID); Future<Void> generateChildSerial = generateChildSerial(context, jobID); // 绑定回调,等异步操作完成后再打印状态 generateChildSerial.onComplete(ar -> { LOG.debug("generateChildSerial.succeeded() "+ar.succeeded()+" "+ar.result()); LOG.debug("generateChildSerial.isComplete() "+ar.isComplete()); }); return generateChildSerial; });
隐藏Bug修复
你现有generateChildSerial方法里的回调,不管数据库操作成功还是失败,都调用了promise.complete(),这会导致上层永远拿到成功状态的Future,无法感知到数据库插入失败的异常,需要修改为失败时传递异常:
db .preparedQuery(sql) .executeBatch(batch, res -> { if (res.succeeded()) { RowSet<Row> rows = res.result(); LOG.info("rows.rowCount():"+ rows.rowCount()); promise.complete(); // 成功才complete } else { System.out.println("Batch failed " + res.cause()); promise.fail(res.cause()); // 失败时调用fail传递异常 } }); return promise.future();
内容的提问来源于stack exchange,提问作者ZAJ
相关产品推荐
相关产品推荐

