123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- module Sessions::Node
- # get application root directory
- @root = Dir.pwd.to_s
- if @root.blank? || @root == '/'
- @root = Rails.root
- end
- # get working directories
- @path = "#{@root}/tmp/session_node_#{Rails.env}"
- def self.session_assigne(client_id, force = false)
- # get available nodes
- nodes = Sessions::Node.registered
- session_count = {}
- nodes.each do |node|
- count = Sessions::Node.sessions_by(node['node_id'], force).count
- session_count[node['node_id']] = count
- end
- # search for lowest session count
- node_id = nil
- node_count = nil
- session_count.each do |local_node_id, count|
- next if !node_count.nil? && count > node_count
- node_count = count
- node_id = local_node_id
- end
- # assigne session
- Rails.logger.info "Assigne session to node #{node_id} (#{client_id})"
- Sessions::Node.sessions_for(node_id, client_id)
- # write node status file
- node_id
- end
- def self.cleanup
- FileUtils.rm_rf @path
- end
- def self.registered
- path = "#{@path}/*.status"
- nodes = []
- files = Dir.glob(path)
- files.each do |filename|
- File.open(filename, 'rb') do |file|
- file.flock(File::LOCK_SH)
- content = file.read
- file.flock(File::LOCK_UN)
- begin
- data = JSON.parse(content)
- nodes.push data
- rescue => e
- Rails.logger.error "can't parse status file #{filename}, #{e.inspect}"
- #to_delete.push "#{path}/#{entry}"
- #next
- end
- end
- end
- nodes
- end
- def self.register(node_id)
- if !File.exist?(@path)
- FileUtils.mkpath @path
- end
- status_file = "#{@path}/#{node_id}.status"
- # write node status file
- data = {
- updated_at_human: Time.now.utc,
- updated_at: Time.now.utc.to_i,
- node_id: node_id.to_s,
- pid: $PROCESS_ID,
- }
- content = data.to_json
- # store session data in session file
- File.open(status_file, 'wb') do |file|
- file.write content
- end
- end
- def self.stats
- # read node sessions
- path = "#{@path}/*.session"
- sessions = {}
- files = Dir.glob(path)
- files.each do |filename|
- File.open(filename, 'rb') do |file|
- file.flock(File::LOCK_SH)
- content = file.read
- file.flock(File::LOCK_UN)
- begin
- next if content.blank?
- data = JSON.parse(content)
- next if data.blank?
- next if data['client_id'].blank?
- sessions[data['client_id']] = data['node_id']
- rescue => e
- Rails.logger.error "can't parse session file #{filename}, #{e.inspect}"
- #to_delete.push "#{path}/#{entry}"
- #next
- end
- end
- end
- sessions
- end
- def self.sessions_for(node_id, client_id)
- if !File.exist?(@path)
- FileUtils.mkpath @path
- end
- status_file = "#{@path}/#{node_id}.#{client_id}.session"
- # write node status file
- data = {
- updated_at_human: Time.now.utc,
- updated_at: Time.now.utc.to_i,
- node_id: node_id.to_s,
- client_id: client_id.to_s,
- pid: $PROCESS_ID,
- }
- content = data.to_json
- # store session data in session file
- File.open(status_file, 'wb') do |file|
- file.write content
- end
- end
- def self.sessions_by(node_id, force = false)
- # read node sessions
- path = "#{@path}/#{node_id}.*.session"
- sessions = []
- files = Dir.glob(path)
- files.each do |filename|
- File.open(filename, 'rb') do |file|
- file.flock(File::LOCK_SH)
- content = file.read
- file.flock(File::LOCK_UN)
- begin
- next if content.blank?
- data = JSON.parse(content)
- next if data.blank?
- next if data['client_id'].blank?
- next if !Sessions.session_exists?(data['client_id']) && force == false
- sessions.push data['client_id']
- rescue => e
- Rails.logger.error "can't parse session file #{filename}, #{e.inspect}"
- #to_delete.push "#{path}/#{entry}"
- #next
- end
- end
- end
- sessions
- end
- end
|