@@ -25,6 +25,8 @@ defmodule NervesHubWeb.Live.Devices.Index do
2525 alias NervesHubWeb.LayoutView.DateTimeFormat
2626
2727 @ list_refresh_time 10_000
28+ # Delay frequent refresh triggers to this interval
29+ @ refresh_delay 1000
2830
2931 @ default_filters % {
3032 connection: "" ,
@@ -107,6 +109,10 @@ defmodule NervesHubWeb.Live.Devices.Index do
107109 |> assign ( :valid_tags , true )
108110 |> assign ( :device_tags , "" )
109111 |> assign ( :total_entries , 0 )
112+ |> assign ( :visible? , true )
113+ |> assign ( :live_refresh_timer , nil )
114+ |> assign ( :live_refresh_pending? , false )
115+ |> assign ( :received_connection_change_identifiers , [ ] )
110116 |> assign ( :current_alarms , [ ] )
111117 |> assign ( :metrics_keys , [ ] )
112118 |> assign ( :deployment_groups , [ ] )
@@ -415,42 +421,83 @@ defmodule NervesHubWeb.Live.Devices.Index do
415421 |> noreply ( )
416422 end
417423
424+ def handle_event ( "page_visibility_change" , % { "visible" => visible? } , socket ) do
425+ socket
426+ |> then ( fn socket ->
427+ # refresh if switching to visible from non-visible
428+ if not socket . assigns . visible? and visible? do
429+ safe_refresh ( socket )
430+ else
431+ socket
432+ end
433+ end )
434+ |> assign ( visible?: visible? )
435+ |> noreply ( )
436+ end
437+
418438 def handle_info ( % Broadcast { event: "connection:status" , payload: payload } , socket ) do
419- update_device_statuses ( socket , payload )
439+ socket
440+ |> assign ( :received_connection_change_identifiers , [ payload | socket . assigns . received_connection_change_identifiers ] )
441+ |> safe_refresh ( )
442+ |> update_device_statuses ( payload )
420443 end
421444
422445 def handle_info ( % Broadcast { event: "connection:change" , payload: payload } , socket ) do
423- update_device_statuses ( socket , payload )
446+ socket
447+ |> assign ( :received_connection_change_identifiers , [ payload | socket . assigns . received_connection_change_identifiers ] )
448+ |> safe_refresh ( )
449+ |> update_device_statuses ( payload )
424450 end
425451
426452 def handle_info ( % Broadcast { event: "fwup_progress" , payload: % { device_id: device_id , percent: percent } } , socket )
427453 when percent > 99 do
428454 socket
429455 |> assign ( :progress , Map . delete ( socket . assigns . progress , device_id ) )
456+ |> safe_refresh ( )
430457 |> noreply ( )
431458 end
432459
433460 def handle_info ( % Broadcast { event: "fwup_progress" , payload: % { device_id: device_id , percent: percent } } , socket ) do
434461 socket
435462 |> assign ( :progress , Map . put ( socket . assigns . progress , device_id , percent ) )
463+ |> safe_refresh ( )
436464 |> noreply ( )
437465 end
438466
439467 # Unknown broadcasts get ignored, likely from the device:id:internal channel
440468 def handle_info ( % Broadcast { } , socket ) do
441- { :noreply , socket }
469+ socket
470+ |> safe_refresh ( )
471+ |> noreply ( )
442472 end
443473
444474 def handle_info ( :refresh_device_list , socket ) do
445- Tracer . with_span "NervesHubWeb.Live.Devices.Index.refresh_device_list" do
446- Process . send_after ( self ( ) , :refresh_device_list , @ list_refresh_time )
475+ if socket . assigns . visible? do
476+ Tracer . with_span "NervesHubWeb.Live.Devices.Index.refresh_device_list" do
477+ Process . send_after ( self ( ) , :refresh_device_list , @ list_refresh_time )
447478
448- if socket . assigns . paginate_opts . total_pages == 1 do
449- { :noreply , assign_display_devices ( socket ) }
450- else
451- { :noreply , socket }
479+ socket
480+ |> safe_refresh ( )
481+ |> noreply ( )
482+ end
483+
484+ socket
485+ |> noreply ( )
486+ end
487+ end
488+
489+ def handle_info ( :live_refresh , socket ) do
490+ if socket . assigns . visible? and socket . assigns . live_refresh_pending? do
491+ Tracer . with_span "NervesHubWeb.Live.Devices.Index.live_refresh_device_list" do
492+ socket
493+ |> assign_display_devices ( )
452494 end
495+ else
496+ socket
453497 end
498+ |> assign ( :live_refresh_timer , nil )
499+ |> assign ( :live_refresh_pending? , false )
500+ |> noreply ( )
454501 end
455502
456503 defp assign_filter_data ( % { assigns: % { product: product } } = socket ) do
@@ -490,12 +537,22 @@ defmodule NervesHubWeb.Live.Devices.Index do
490537 Map . new ( updated_devices , fn device ->
491538 socket . endpoint . subscribe ( "device:#{ device . identifier } :internal" )
492539
493- { device . identifier , Tracker . connection_status ( device ) }
540+ payload =
541+ Enum . find ( socket . assigns . received_connection_change_identifiers , fn % { device_id: identifier } ->
542+ identifier == device . identifier
543+ end )
544+
545+ if payload do
546+ { payload . device_id , payload . status }
547+ else
548+ { device . identifier , Tracker . connection_status ( device ) }
549+ end
494550 end )
495551
496552 socket
497553 |> assign ( :devices , AsyncResult . ok ( old_devices , updated_devices ) )
498554 |> assign ( :device_statuses , AsyncResult . ok ( old_device_statuses , updated_device_statuses ) )
555+ |> assign ( :received_connection_change_identifiers , [ ] )
499556 |> device_pagination_assigns ( paginate_opts , pager )
500557 |> noreply ( )
501558 end
@@ -724,4 +781,17 @@ defmodule NervesHubWeb.Live.Devices.Index do
724781 defp has_results? ( % AsyncResult { } = device_async , currently_filtering? ) do
725782 device_async . ok? && ( Enum . any? ( device_async . result ) || currently_filtering? )
726783 end
784+
785+ defp safe_refresh ( socket ) do
786+ if is_nil ( socket . assigns . live_refresh_timer ) and socket . assigns . visible? do
787+ # Nothing pending, we perform a refresh
788+ socket
789+ |> assign_display_devices ( )
790+ |> assign ( :live_refresh_timer , Process . send_after ( self ( ) , :live_refresh , @ refresh_delay ) )
791+ else
792+ # a timer is already pending, we flag the pending request
793+ socket
794+ |> assign ( :live_refresh_pending? , true )
795+ end
796+ end
727797end
0 commit comments