require "eventmachine" require "em-websocket-client" module Adminix class Watcher def self.run!(options) watcher = Watcher.new(options) if options[:stop_daemon] watcher.stop else if options[:daemonize] watcher.start else watcher.run! end end end SYNC_PERIOD = 5.freeze WEBSOCKET_HOST = 'ws://api.adminix.io/websocket'.freeze SERVICE_CHANNEL = 'ServiceChannel'.freeze def initialize(opts) @socket_url = opts[:websocket_host] || ENV['ADMINIX_WEBSOCKET_HOST'] || WEBSOCKET_HOST @socket_url = "#{@socket_url}?secret_key=#{config.secret_key}" @service = Service.instance @client = nil @pid_full = '/tmp/adminix.pid' end def run! trap_signal EventMachine.run do @client = WebsocketClient.new(@socket_url) do on_disconnect(@client) end @client.connect do |message| on_message_receive(@client, message) end EventMachine.add_periodic_timer(SYNC_PERIOD) do publish_message(:sync, @service.to_cable) if @client.connected end end end def publish_message(action, data) identifier = { channel: SERVICE_CHANNEL, service_id: @service.id } data = { action: action, data: data } @client.publish(identifier, data) end def get_pid if File.exists?(@pid_full) file = File.new(@pid_full, "r") pid = file.read file.close pid else 0 end end def start pid = get_pid if pid != 0 warn "Daemon is already running" exit -1 end pid = fork { run! } begin file = File.new(@pid_full, "w") file.write(pid) file.close Process.detach(pid) rescue => exc Process.kill('TERM', pid) warn "Cannot start daemon: #{exc.message}" end end def stop pid = get_pid begin EM.stop rescue end if pid != 0 Process.kill('HUP', pid.to_i) File.delete(@pid_full) system.log "Stopped" else warn "Daemon is not running" exit -1 end end private def config Config.instance end def system System.instance end def on_message_receive(client, message) case message['type'] when 'welcome' system.log 'Connected to channel' on_success_connect(client) when 'ping' #system.log 'ping from server' # do something else # do something end end def on_disconnect(client) system.log 'Disconnected. Reconnecting...' client.connect do |message| system.log message on_message_receive(client, message) end #EventMachine.stop_event_loop end def on_success_connect(client) client.subscribe(channel: SERVICE_CHANNEL, service_id: @service.id) do |message| type = message['type'] || message['message']['type'] data = message['message']['data'] rescue {} on_service_message_receive(type, data) end end def on_service_message_receive(type, data) case type when 'confirm_subscription' when 'restart' @service.restart! when 'sync' @service.sync(self, data) end end def trap_signal Signal.trap("SIGINT") do system.log "Stopping..." EventMachine.stop end end end end