long_polling_controller.rb 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
  2. class LongPollingController < ApplicationController
  3. skip_before_action :session_update # prevent race conditions
  4. # GET /api/v1/message_send
  5. def message_send
  6. new_connection = false
  7. # check client id
  8. client_id = client_id_verify
  9. if !client_id
  10. new_connection = true
  11. client_id = client_id_gen
  12. log 'new client connection', client_id
  13. end
  14. if !params['data']
  15. params['data'] = {}
  16. end
  17. session_data = {}
  18. if current_user&.id
  19. session_data = { 'id' => current_user.id }
  20. end
  21. # spool messages for new connects
  22. if params['data']['spool']
  23. Sessions.spool_create(params['data'])
  24. end
  25. if params['data']['event'] == 'login'
  26. Sessions.create(client_id, session_data, { type: 'ajax' })
  27. elsif params['data']['event']
  28. message = Sessions::Event.run(
  29. event: params['data']['event'],
  30. payload: params['data'],
  31. session: session_data,
  32. client_id: client_id,
  33. clients: {},
  34. options: {},
  35. )
  36. if message
  37. Sessions.send(client_id, message)
  38. end
  39. else
  40. log "unknown message '#{params['data'].inspect}'", client_id
  41. end
  42. if new_connection
  43. result = { client_id: client_id }
  44. render json: result
  45. else
  46. render json: {}
  47. end
  48. end
  49. # GET /api/v1/message_receive
  50. def message_receive
  51. # check client id
  52. client_id = client_id_verify
  53. raise Exceptions::UnprocessableEntity, 'Invalid client_id receive!' if !client_id
  54. # check queue to send
  55. begin
  56. # update last ping
  57. 4.times do
  58. sleep 0.25
  59. end
  60. #sleep 1
  61. Sessions.touch(client_id) # rubocop:disable Rails/SkipsModelValidations
  62. # set max loop time to 24 sec. because of 30 sec. timeout of mod_proxy
  63. count = 3
  64. if Rails.env.production?
  65. count = 12
  66. end
  67. loop do
  68. count = count - 1
  69. queue = Sessions.queue(client_id)
  70. if queue && queue[0]
  71. logger.debug "send #{queue.inspect} to #{client_id}"
  72. render json: queue
  73. return
  74. end
  75. 8.times do
  76. sleep 0.25
  77. end
  78. #sleep 2
  79. if count.zero?
  80. render json: { event: 'pong' }
  81. return
  82. end
  83. end
  84. rescue => e
  85. raise Exceptions::UnprocessableEntity, 'Invalid client_id in receive loop!'
  86. end
  87. end
  88. private
  89. def client_id_gen
  90. rand(9_999_999_999).to_s
  91. end
  92. def client_id_verify
  93. return if !params[:client_id]
  94. sessions = Sessions.sessions
  95. return if !sessions.include?(params[:client_id].to_s)
  96. params[:client_id].to_s
  97. end
  98. def log( data, client_id = '-' )
  99. logger.info "client(#{client_id}) #{data}"
  100. end
  101. end