Grails 异步事件处理程序无法从持久性中检索域实例

Grails async Event handler fails to retrieve domain instance from persistence

我正在尝试在事务服务中创建并保留一个 Foo 实例,然后一旦 Foo 实例被保留,触发一个事件以启动对其的一些异步处理。

我遇到的问题是,当我尝试从事件处理程序中的持久性中检索 Foo 实例时,找不到该实例。

我保留 Foo 实例的服务方法如下所示:

Foo makeFoo() {
  def foo = new Foo(...).save(flush: true, failOnError: true)
  notify("FOO_CREATED_EVT", foo.id)
  return foo
}

我的事件处理程序存在于单独的事务服务中,如下所示:

@Selector("FOO_CREATED_EVT")
void onFooCreated(Long fooId) {
  def foo = Foo.get(fooId) // also tried findById, with the same outcome
  assert foo != null // fails
}

我已经在启用 sql 日志记录的情况下逐步检查了两侧的代码,并验证了 Foo 实例成功地保留在 makeFoo() 中,但是当 onFooCreated() 尝试时检索它,它总是失败。据我所知,在触发事件之前刷新保存应该会导致 Foo 实例立即保留,但是如果我在 onFooCreated:

中添加延迟
Thread.sleep(1000)
def foo = Foo.get(fooId)
assert foo != null // succeeds

然后操作成功,所以我只能假设存在竞争条件,因为 flush 实际上并没有同步持久化实例。

我的项目将 Grails 3.2 与 Hibernate 5 和 PostgreSQL 9.6 结合使用。

我显然做错了什么,但是关于异步事件的文档非常少,并且在解决这种情况时遇到了困难:(

flush() 可能已执行,但事务尚未提交或关闭,因此数据对另一个线程不可见,因为事务是隔离的,另一个线程将使用单独的连接。

您需要确保在触发事件之前事务已提交。