Hey there,
Context
I’ve been trying to move some turbo_frame_tags
from standard show pages to turbo_streams
via background workers due to “expensive” calculations. Here’s the summary of what I’m doing
# index page (slim)
= turbo_stream_from current_user, :campaign_list_items
- @campaigns.each do |campaign|
= turbo_frame_tag dom_id(campaign), src: campaign_list_items_path(campaign), data: {turbo: true} do
.grid.grid-cols-7.p-3.bt
.left.w-6.word-wrap = link_to campaign.name, campaign_path(campaign), data: {"turbo-frame": "_top"}
.right -
.right -
.right -
.right -
.right -
.right -
# Controller
module Dashboard
module Campaigns
class ListItemsController < DashboardController
def show
::Campaigns::ListItemStatsWorker.perform_async(params[:campaign_id])
render status: :ok
end
end
end
end
# worker
module Campaigns
class ListItemStatsWorker
include Sidekiq::Worker
def perform(campaign_id)
return unless (campaign = Campaign.find_by(campaign_id))
campaign.user.broadcast_update_to(
campaign.user,
:campaign_list_items,
target: "campaign_#{campaign.id}",
partial: "dashboard/campaigns/list_items/list_item",
locals: {
campaign: campaign,
stats: CampaignStatsPresenter.new(campaign, nil, nil)
}
)
end
end
end
#partial
= turbo_frame_tag dom_id(campaign) do
.grid.grid-cols-7.p-3.bt
.left.w-6.word-wrap
= link_to stats.campaign.name,
campaign_path(id: stats.campaign.id),
class: "primary hover-dark",
data: {"turbo-frame": "_top"}
The problem
It looks like the background worker is finishing prior to the page being able to subscribe fully to the channel. Thus the broadcast has nothing that is “listening” and the UI does not get updated.
Moving forward
I tried to add a delay on the worker invocation - but that’s sort of a bandaid and doesn’t work all the time. At this point I’m not sure if I’m just not doing something “the right way”.
Is there a way to fire off the the turbo_frame_tag src request after the turbo_stream_from finishes it’s connection?
Does anyone have any ideas?