– host_heartbeat: sends a heartbeat ——————————————

– This method is called regularily by workers to pass in a hosts heartbeat – metrics. The database also uses this to regularily run a zombie check.

CREATE OR REPLACE FUNCTION {SCHEMA_NAME}.host_heartbeat(

p_host_id UUID,
p_metrics JSONB,
p_fast_mode BOOLEAN)

RETURNS VOID AS $$ DECLARE

p_latest_zombie_event_id bigint;
p_zombie_count int;

BEGIN

-- RAISE NOTICE '*** heartbeat % %', p_host_id, p_metrics;

-- We perform the zombie_check before we insert the heartbeats event. This
-- should not make any difference functionality-wise, but helps us building
-- tests for this feature..
--
-- Note: The zombie_check function throttles itself.
PERFORM {SCHEMA_NAME}.zombie_check(p_fast_mode);

IF NOT EXISTS (
    SELECT 1 FROM {SCHEMA_NAME}.events
    WHERE (name,host_id)=('heartbeat', p_host_id)
      AND created_at > (now() at time zone 'utc') - interval '1 minute'
  )
THEN
  -- The code below is throttled to run only once per host and minute. 
  INSERT INTO {SCHEMA_NAME}.events(name, host_id, attributes)
    VALUES ('heartbeat', p_host_id, p_metrics);

  -- This host is set to 'running' if it currently was stopped. This would
  -- only happen if a host was manually stopped and then restarted again.
  -- Note: we do not touch the status of a host during 'shutdown', since
  -- even in this mode the is expected to send in heartbeats.
  UPDATE {SCHEMA_NAME}.hosts
    SET status='running' WHERE status='stopped' AND id=p_host_id;

  -- Find hosts that are not stopped that don't have a heartbeat in the
  -- last 5 minutes, and set those to 'stopped'.
  UPDATE {SCHEMA_NAME}.hosts
    SET status='stopped'
    WHERE
    id IN (
      SELECT hosts.id
      FROM {SCHEMA_NAME}.hosts hosts
      LEFT JOIN (
        SELECT id, host_id
        FROM {SCHEMA_NAME}.events events
        WHERE name='heartbeat'
          AND created_at > now() at time zone 'utc' - interval '5 minutes'
      ) heartbeats ON hosts.id=heartbeats.host_id
      WHERE status IN ('running', 'shutdown')
        AND heartbeats.id IS NULL
    );

END IF;

END; $$ LANGUAGE plpgsql;