redis.rb 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. class Sessions::Store::Redis
  3. SESSIONS_KEY = 'sessions'.freeze
  4. MESSAGES_KEY = 'messages'.freeze
  5. SPOOL_KEY = 'spool'.freeze
  6. NODES_KEY = 'nodes'.freeze
  7. def initialize
  8. @redis = Redis.new(driver: :hiredis)
  9. end
  10. def create(client_id, data)
  11. @redis.set client_session_key(client_id), data
  12. @redis.sadd? SESSIONS_KEY, client_id
  13. end
  14. def sessions
  15. @redis.smembers SESSIONS_KEY
  16. end
  17. def session_exists?(client_id)
  18. @redis.sismember SESSIONS_KEY, client_id
  19. end
  20. def destroy(client_id)
  21. @redis.srem? SESSIONS_KEY, client_id
  22. @redis.del client_session_key(client_id)
  23. @redis.del client_messages_key(client_id)
  24. end
  25. def set(client_id, data)
  26. @redis.set client_session_key(client_id), data.to_json
  27. end
  28. def get(client_id)
  29. data = nil
  30. # if only session is missing, then it's an error behavior
  31. session = @redis.get client_session_key(client_id)
  32. if !session
  33. destroy(client_id)
  34. Sessions.log('error', "missing session value for '#{client_id}', removing session.")
  35. return
  36. end
  37. data_json = JSON.parse(session)
  38. if data_json
  39. data = Sessions.symbolize_keys(data_json)
  40. data[:user] = data_json['user'] # for compat. reasons
  41. end
  42. data
  43. end
  44. def send_data(client_id, data)
  45. key = client_messages_key(client_id)
  46. key_is_new = !@redis.exists?(key)
  47. @redis.rpush(key, data.to_json).positive?.tap do
  48. # Make sure message keys are cleaned up even if they are no longer listed in 'sessions'.
  49. @redis.expire(key, 1.hour) if key_is_new
  50. end
  51. end
  52. def queue(client_id)
  53. data = []
  54. while (item = @redis.lpop(client_messages_key(client_id)))
  55. data.push JSON.parse(item)
  56. end
  57. data
  58. end
  59. def cleanup
  60. clear_spool
  61. clear_sessions
  62. clear_messages
  63. true
  64. end
  65. def clear_spool
  66. @redis.del SPOOL_KEY
  67. end
  68. def clear_sessions
  69. @redis.keys("#{SESSIONS_KEY}/*").each do |key|
  70. @redis.del key
  71. end
  72. @redis.del SESSIONS_KEY
  73. end
  74. def clear_messages
  75. @redis.keys("#{MESSAGES_KEY}/*").each do |key|
  76. @redis.del key
  77. end
  78. end
  79. ### Node-specific methods ###
  80. def clear_nodes
  81. @redis.keys("#{NODES_KEY}/*").each do |key|
  82. @redis.del key
  83. end
  84. @redis.del NODES_KEY
  85. end
  86. def nodes
  87. nodes = []
  88. @redis.smembers(NODES_KEY).each do |node_id|
  89. content = @redis.get(node_key(node_id))
  90. if content
  91. data = JSON.parse(content)
  92. nodes.push data
  93. end
  94. end
  95. nodes
  96. end
  97. def add_node(node_id, data)
  98. @redis.set node_key(node_id), data.to_json
  99. @redis.sadd? NODES_KEY, node_id
  100. end
  101. def each_node_session(&)
  102. @redis.smembers(NODES_KEY).each do |node_id|
  103. each_session_by_node(node_id, &)
  104. end
  105. end
  106. def create_node_session(node_id, client_id, data)
  107. @redis.set node_client_session_key(node_id, client_id), data.to_json
  108. @redis.sadd? node_sessions_key(node_id), client_id
  109. end
  110. def each_session_by_node(node_id)
  111. @redis.smembers(node_sessions_key(node_id)).each do |client_id|
  112. content = @redis.get(node_client_session_key(node_id, client_id))
  113. if content
  114. data = JSON.parse(content)
  115. yield data
  116. end
  117. end
  118. end
  119. protected
  120. def client_session_key(client_id)
  121. "#{SESSIONS_KEY}/#{client_id}"
  122. end
  123. def client_messages_key(client_id)
  124. "#{MESSAGES_KEY}/#{client_id}"
  125. end
  126. def node_key(node_id)
  127. "#{NODES_KEY}/#{node_id}"
  128. end
  129. def node_sessions_key(node_id)
  130. "#{node_key(node_id)}/sessions"
  131. end
  132. def node_client_session_key(node_id, client_id)
  133. "#{node_sessions_key(node_id)}/#{client_id}"
  134. end
  135. end