@@ -245,13 +245,51 @@ defmodule Hemdal.Host do
245245 @ spec update_host ( Hemdal.Config.Host . t ( ) ) :: { :ok , pid ( ) }
246246 def update_host ( host ) do
247247 if pid = get_pid ( host . id ) do
248- GenStateMachine . cast ( pid , { :update , host } )
248+ GenServer . cast ( pid , { :update , host } )
249249 { :ok , pid }
250250 else
251251 start ( host )
252252 end
253253 end
254254
255+ @ typedoc """
256+ Information about the status of the host. The host is limiting the number
257+ of running workers so we can get the information of the following data:
258+
259+ - `waiting_workers` the current number of requests awaiting in the queue.
260+ - `running_workers` the number of running workers.
261+ - `max_running_workers` the max number of workers that could be run at
262+ the same time.
263+ """
264+ @ type host_stats ( ) :: % {
265+ :status => :up | :down ,
266+ optional ( :waiting_workers ) => non_neg_integer ( ) ,
267+ optional ( :running_workers ) => non_neg_integer ( ) ,
268+ optional ( :max_running_workers ) => non_neg_integer ( )
269+ }
270+
271+ @ doc """
272+ Retrieve stats for a specific host.
273+ """
274+ @ spec get_stats ( host_id ( ) ) :: host_stats ( )
275+ def get_stats ( host_id ) do
276+ GenServer . call ( via ( host_id ) , :get_stats )
277+ catch
278+ :exit , { :noproc , _info } ->
279+ % { status: :down }
280+ end
281+
282+ @ doc """
283+ Retrieve stats for all of the hosts. See `get_stats/1`.
284+ """
285+ @ spec get_all_stats :: % { host_id ( ) => host_stats ( ) }
286+ def get_all_stats do
287+ @ registry_name
288+ |> Registry . select ( [ { { :"$1" , :_ , :_ } , [ ] , [ :"$1" ] } ] )
289+ |> Map . new ( & { & 1 , get_stats ( & 1 ) } )
290+ end
291+
292+ @ typedoc false
255293 @ type t ( ) :: % __MODULE__ {
256294 host: nil | Hemdal.Config.Host . t ( ) ,
257295 max_workers: :infinity | non_neg_integer ( ) ,
@@ -332,6 +370,17 @@ defmodule Hemdal.Host do
332370 { :noreply , % __MODULE__ { state | workers: workers } }
333371 end
334372
373+ def handle_call ( :get_stats , _from , % __MODULE__ { } = state ) do
374+ stats = % {
375+ status: :up ,
376+ waiting_workers: Queue . len ( state . queue ) ,
377+ running_workers: state . workers ,
378+ max_running_workers: state . max_workers
379+ }
380+
381+ { :reply , stats , state }
382+ end
383+
335384 @ impl GenServer
336385 @ doc false
337386 def handle_cast ( { :update , host } , state ) do
@@ -363,26 +412,38 @@ defmodule Hemdal.Host do
363412
364413 defp launch_extra ( state , false ) do
365414 { { :value , { info , from } } , queue } = Queue . out ( state . queue )
366- { :noreply , state } = handle_call ( info , from , % __MODULE__ { state | queue: queue } )
367- launch_extra ( state , Queue . is_empty ( state . queue ) )
415+
416+ case handle_call ( info , from , % __MODULE__ { state | queue: queue } ) do
417+ { :noreply , state } ->
418+ launch_extra ( state , Queue . is_empty ( state . queue ) )
419+
420+ { :reply , reply , state } ->
421+ GenServer . reply ( from , reply )
422+ launch_extra ( state , Queue . is_empty ( state . queue ) )
423+ end
368424 end
369425
370426 @ impl GenServer
371427 @ doc false
372428 def handle_info ( { :DOWN , _ref , :process , _pid , _reason } , state ) do
373- case Queue . out ( state . queue ) do
374- { :empty , queue } ->
375- workers = state . workers - 1
376- Logger . debug ( "host => workers: #{ workers } /#{ state . max_workers } ; queue length: 0" )
377- { :noreply , % __MODULE__ { state | workers: workers , queue: queue } }
378-
379- { { :value , { { :exec , caller , cmd , args } , from } } , queue } ->
380- state = % __MODULE__ { state | queue: queue }
381- send_result = & GenServer . reply ( from , & 1 )
382- spawn_monitor ( fn -> run_in_background ( caller , cmd , args , send_result , state ) end )
383- qlen = Queue . len ( queue )
384- Logger . debug ( "host => workers: #{ state . workers } /#{ state . max_workers } ; queue length: #{ qlen } " )
429+ { next , queue } = Queue . out ( state . queue )
430+ state = % __MODULE__ { state | queue: queue , workers: state . workers - 1 }
431+ len = Queue . len ( queue )
432+ Logger . debug ( "host => workers: #{ state . workers } /#{ state . max_workers } ; queue length: #{ len } " )
433+
434+ case next do
435+ :empty ->
385436 { :noreply , state }
437+
438+ { :value , { info , from } } ->
439+ case handle_call ( info , from , state ) do
440+ { :noreply , state } ->
441+ { :noreply , state }
442+
443+ { :reply , reply , state } ->
444+ GenServer . reply ( from , reply )
445+ { :noreply , state }
446+ end
386447 end
387448 end
388449
0 commit comments