long_polling_controller.rb 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
  2. class LongPollingController < ApplicationController
  3. skip_action_callback :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 && 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. if !client_id
  54. render json: { error: 'Invalid client_id receive!' }, status: :unprocessable_entity
  55. return
  56. end
  57. # check queue to send
  58. begin
  59. # update last ping
  60. 4.times {
  61. sleep 0.25
  62. }
  63. #sleep 1
  64. Sessions.touch(client_id)
  65. # set max loop time to 24 sec. because of 30 sec. timeout of mod_proxy
  66. count = 3
  67. if Rails.env.production?
  68. count = 12
  69. end
  70. loop do
  71. count = count - 1
  72. queue = Sessions.queue(client_id)
  73. if queue && queue[0]
  74. logger.debug "send #{queue.inspect} to #{client_id}"
  75. render json: queue
  76. return
  77. end
  78. 8.times {
  79. sleep 0.25
  80. }
  81. #sleep 2
  82. if count.zero?
  83. render json: { event: 'pong' }
  84. return
  85. end
  86. end
  87. rescue => e
  88. logger.error e.inspect
  89. logger.error e.backtrace
  90. render json: { error: 'Invalid client_id in receive loop!' }, status: :unprocessable_entity
  91. return
  92. end
  93. end
  94. private
  95. def client_id_gen
  96. rand(9_999_999_999).to_s
  97. end
  98. def client_id_verify
  99. return if !params[:client_id]
  100. sessions = Sessions.sessions
  101. return if !sessions.include?(params[:client_id].to_s)
  102. params[:client_id].to_s
  103. end
  104. def log( data, client_id = '-' )
  105. logger.info "client(#{client_id}) #{data}"
  106. end
  107. end