node.rb 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. module Sessions::Node
  2. # get application root directory
  3. @root = Dir.pwd.to_s
  4. if @root.blank? || @root == '/'
  5. @root = Rails.root
  6. end
  7. # get working directories
  8. @path = "#{@root}/tmp/session_node_#{Rails.env}"
  9. def self.session_assigne(client_id, force = false)
  10. # get available nodes
  11. nodes = Sessions::Node.registered
  12. session_count = {}
  13. nodes.each do |node|
  14. count = Sessions::Node.sessions_by(node['node_id'], force).count
  15. session_count[node['node_id']] = count
  16. end
  17. # search for lowest session count
  18. node_id = nil
  19. node_count = nil
  20. session_count.each do |local_node_id, count|
  21. next if !node_count.nil? && count > node_count
  22. node_count = count
  23. node_id = local_node_id
  24. end
  25. # assigne session
  26. Rails.logger.info "Assigne session to node #{node_id} (#{client_id})"
  27. Sessions::Node.sessions_for(node_id, client_id)
  28. # write node status file
  29. node_id
  30. end
  31. def self.cleanup
  32. FileUtils.rm_rf @path
  33. end
  34. def self.registered
  35. path = "#{@path}/*.status"
  36. nodes = []
  37. files = Dir.glob(path)
  38. files.each do |filename|
  39. File.open(filename, 'rb') do |file|
  40. file.flock(File::LOCK_SH)
  41. content = file.read
  42. file.flock(File::LOCK_UN)
  43. begin
  44. data = JSON.parse(content)
  45. nodes.push data
  46. rescue => e
  47. Rails.logger.error "can't parse status file #{filename}, #{e.inspect}"
  48. #to_delete.push "#{path}/#{entry}"
  49. #next
  50. end
  51. end
  52. end
  53. nodes
  54. end
  55. def self.register(node_id)
  56. if !File.exist?(@path)
  57. FileUtils.mkpath @path
  58. end
  59. status_file = "#{@path}/#{node_id}.status"
  60. # write node status file
  61. data = {
  62. updated_at_human: Time.now.utc,
  63. updated_at: Time.now.utc.to_i,
  64. node_id: node_id.to_s,
  65. pid: $PROCESS_ID,
  66. }
  67. content = data.to_json
  68. # store session data in session file
  69. File.open(status_file, 'wb') do |file|
  70. file.write content
  71. end
  72. end
  73. def self.stats
  74. # read node sessions
  75. path = "#{@path}/*.session"
  76. sessions = {}
  77. files = Dir.glob(path)
  78. files.each do |filename|
  79. File.open(filename, 'rb') do |file|
  80. file.flock(File::LOCK_SH)
  81. content = file.read
  82. file.flock(File::LOCK_UN)
  83. begin
  84. next if content.blank?
  85. data = JSON.parse(content)
  86. next if data.blank?
  87. next if data['client_id'].blank?
  88. sessions[data['client_id']] = data['node_id']
  89. rescue => e
  90. Rails.logger.error "can't parse session file #{filename}, #{e.inspect}"
  91. #to_delete.push "#{path}/#{entry}"
  92. #next
  93. end
  94. end
  95. end
  96. sessions
  97. end
  98. def self.sessions_for(node_id, client_id)
  99. if !File.exist?(@path)
  100. FileUtils.mkpath @path
  101. end
  102. status_file = "#{@path}/#{node_id}.#{client_id}.session"
  103. # write node status file
  104. data = {
  105. updated_at_human: Time.now.utc,
  106. updated_at: Time.now.utc.to_i,
  107. node_id: node_id.to_s,
  108. client_id: client_id.to_s,
  109. pid: $PROCESS_ID,
  110. }
  111. content = data.to_json
  112. # store session data in session file
  113. File.open(status_file, 'wb') do |file|
  114. file.write content
  115. end
  116. end
  117. def self.sessions_by(node_id, force = false)
  118. # read node sessions
  119. path = "#{@path}/#{node_id}.*.session"
  120. sessions = []
  121. files = Dir.glob(path)
  122. files.each do |filename|
  123. File.open(filename, 'rb') do |file|
  124. file.flock(File::LOCK_SH)
  125. content = file.read
  126. file.flock(File::LOCK_UN)
  127. begin
  128. next if content.blank?
  129. data = JSON.parse(content)
  130. next if data.blank?
  131. next if data['client_id'].blank?
  132. next if !Sessions.session_exists?(data['client_id']) && force == false
  133. sessions.push data['client_id']
  134. rescue => e
  135. Rails.logger.error "can't parse session file #{filename}, #{e.inspect}"
  136. #to_delete.push "#{path}/#{entry}"
  137. #next
  138. end
  139. end
  140. end
  141. sessions
  142. end
  143. end