require 'aasm' require 'json' require 'pp' require 'HTTParty' require 'optimus-runner/DeviceDetails' require 'json' require 'optimus-runner/AppiumLocalService' require 'optimus-runner/SessionInfoBuilder' require 'optimus-runner/clients/AkiraClient' require 'optimus-runner/clients/AppiumServerClient' require 'logger' require 'optimus-runner/commands/ShellCommands' require 'exponential_backoff' class OptimusRunnerSM include AASM attr_accessor :session_info def initialize @logger = Logger.new(STDOUT) @initial_device_set = [] @device_details = [] set_restart_session set_is_session_added set_is_session_removed set_is_session_restarted end aasm do state :idle, :initial => true, :before_enter => :gather_initial_device_set state :created, :added, :removed, :restarted event :create, :before => [:create_sessions, :gather_initial_device_set] do transitions :from => :idle, :to => :created, :guard => :devices_available? transitions :from => :idle, :to => :idle end event :add, :before => :add_sessions do transitions :from => [:created, :added, :removed, :restarted], :to => :added, :guard => :session_added? transitions :from => [:created, :added, :removed, :restarted], :to => :created, :guard => :devices_available? transitions :from => [:created, :added, :removed, :restarted], :to => :idle end event :remove, :before => :remove_sessions do transitions :from => [:created, :added, :removed, :restarted], :to => :removed, :guard => :session_removed? transitions :from => [:created, :added, :removed, :restarted], :to => :created, :guard => :devices_available? transitions :from => [:created, :added, :removed, :restarted], :to => :idle end event :restart, :before => :restart_sessions do transitions :from => [:created, :added, :removed, :restarted], :to => :restarted, :guard => :session_restarted? transitions :from => [:created, :added, :removed, :restarted], :to => :created, :guard => :devices_available? transitions :from => [:created, :added, :removed, :restarted], :to => :idle end event :empty, :before => :empty_sessions do transitions :from => [:created, :added, :removed, :restarted], :to => :added, :guard => :cloud_session_empty? transitions :from => [:created, :added, :removed, :restarted], :to => :created, :guard => :devices_available? transitions :from => [:created, :added, :removed, :restarted], :to => :idle end event :session_state, :before => :is_session_alive? do transitions :from => [:created, :added, :removed, :restarted], :to => :created, :guard => :devices_available? end end def devices_available? gather_devices @device_details.length > 0 end def gather_initial_device_set details = DeviceDetails.new @initial_device_set = details.get_device_details @logger.info "Initial Device Set #{@initial_device_set}" end def session_added? @session_added end def session_removed? @session_removed end def session_restarted? @session_restarted end def session_empty? @sessions_empty end def gather_devices details = DeviceDetails.new @device_details = details.get_device_details @logger.info "Current devices connected are #{@device_details}" end def create_sessions return unless devices_available? @logger.info "Device details found are #{@device_details}" sessions = AppiumLocalService.new.launch_appium_sessions(@device_details) @session_info = sessions AkriaClient.new.save_sessions(@session_info) end def create_new_session(device_details) @logger.info "Found new device added #{device_details}" session_info = AppiumLocalService.new.launch_appium_sessions(device_details) # puts session # session_info = SessionInfo.new(session,device_details).create_session_info AkriaClient.new.save_sessions(session_info) @session_info.push session_info[0] end def add_sessions return unless devices_available? if new_device_added? create_new_session get_added_devices @initial_device_set = @device_details @session_added = true end end def remove_sessions return unless devices_available? if device_removed? get_removed_devices.each do |removed_device| p removed_device session_info = @session_info.detect {|info| info["sessionCapabilities"]==removed_device} p session_info AkriaClient.new.remove_session session_info["sessionUrl"] session_details = AppiumLocalService.new.get_session_details session_detail = session_details.detect {|session_detail| session_detail["session_id"]==session_info["sessionUrl"]} puts "Removed session details #{session_details}" ShellCommands.new.kill_process session_detail["session_pid"] @session_info.delete_if{ |session_inf| session_inf["sessionUrl"] == session_info["sessionUrl"]} @session_removed= true @initial_device_set = @device_details end end end def session_terminated? return false unless devices_available? akira = AkriaClient.new @session_info.each do |session| p "Session #{session}" @logger.info "Checking if the session #{session["sessionUrl"]} is terminated" session_info = akira.get_session_info session["sessionUrl"] session_state = session_info["sessionState"] @is_session_terminated = session_state.eql? "TERMINATED" @logger.info "Is session #{session["sessionUrl"]} terminated? #{@is_session_terminated}" @restart_session = session_info if @is_session_terminated @logger.info "Session Details to restart #{@restart_session}" break unless @restart_session.empty? end return @is_session_terminated end def restart_sessions session = AppiumLocalService.new.launch_appium_session @restart_session["sessionCapabilities"] @logger.info "Restarting session #{@restart_session}" @logger.info "Session details are #{@session_info}" @session_info.delete_if{ |session_inf| session_inf["sessionUrl"] == @restart_session["sessionUrl"]} @logger.info "Session details are #{@session_info}" @restart_session["sessionUrl"] = session @session_info.push(@restart_session) @logger.info "Session details are #{@session_info}" AkriaClient.new.save_session @restart_session set_restart_session @session_restarted = true end def empty_sessions return unless devices_available? if cloud_session_empty? p "Session Info #{@session_info}" AkriaClient.new.save_sessions(@session_info) end end def cloud_session_empty? sessions = AkriaClient.new.get_all_sessions return false if sessions.instance_of? Array return true if sessions.key?("errorCode") end def session_state return unless devices_available? @session_info.each do |session| if(is_session_engaged?(session["sessionUrl"])) AkriaClient.new.release_session session["sessionUrl"] unless AppiumServerClient.new.isSessionAlive? session["sessionUrl"] end end end def is_session_engaged?(session_url) session_state = AkriaClient.new.get_session_state session_url p "Session state is #{session_state}" return session_state.casecmp?("ENGAGED") end def new_device_added? added_device = get_added_devices p "Is new devices added #{added_device.length>0}" p "Added devices length #{added_device.length}" p "Added devices #{added_device}" return added_device.length>0 end def device_removed? removed_device = get_removed_devices @logger.info "Device #{removed_device} is removed" return removed_device.length>0 end def set_is_session_restarted @session_restarted = false end def set_is_session_removed @session_removed = false end def set_is_session_added @session_added = false end def set_restart_session @restart_session = {} end private def get_added_devices added_device = @device_details - @initial_device_set return added_device end def get_removed_devices removed_device = @initial_device_set - @device_details return removed_device end end