在一个典型的Rails控制器中,我们创建一个Post
模型,然后重定向到posts_path
。index
动作使用Searchkick来列出Posts。
# In the model
class Post < ApplicationRecord
searchkick callbacks: :async
end
# In the controller
def index
@posts = Post.search("*")
end
def create
Post.create!(post_params)
redirect_to posts_path
end
然而,由于Elasticsearch最终是一致的,有时重定向会在之前出现。Searchkick/Elasticsearch索引该记录
Searchkick的文档说明可以使用Post.search_index.refresh
等待索引赶上新记录。可以这样写:
def create
Post.create!(post_params)
Post.search_index.refresh
redirect_to posts_path
end
然而,有时我们仍然重定向到/posts
而看不到新创建的记录;我认为这是因为我们正在使用callbacks: :async
,所以Searchkick(和Elasticsearch::API::Indices::IndicesClient
在幕后使用)没有办法知道排队的Searchkick::ReindexV2Job
。
如果是这种情况,如何解决这个用例,这是:在#create
或#destroy
的行动已经创建/销毁一个搜索索引记录,重定向到#index
的行动,以确保记录已经在索引上,当使用异步回调?
在后台使用的Elasticsearch::API::Indices::IndicesClient)没有办法知道排队的Searchkick::驯鹿xv2job。
你猜对了。有可能您的后台作业还没有执行,所以刷新search_index没有帮助。
要解决这个问题,我们需要同步地(在同一个线程中)重新索引。幸运的是,您可以在运行时更改Searchkick回调的重新排序策略。在您的场景中,我建议通过Searchkick.callbacks(:inline)
:
def create
# reindex synchonously
Searchkick.callbacks(:inline) do
Post.create!(post_params)
end
# ensure that all changes are reflected by the ES index
Post.search_index.refresh
redirect_to posts_path
end