Browse Source

Fixed issue #2353 - Chat does not work due to errors in WebSocket (Database connection). Credits to @d--j for providing the solution.

Martin Edenhofer 6 years ago
parent
commit
d0a36c36a8
3 changed files with 91 additions and 0 deletions
  1. 2 0
      lib/sessions/event.rb
  2. 4 0
      lib/sessions/event/base.rb
  3. 85 0
      test/unit/chat_test.rb

+ 2 - 0
lib/sessions/event.rb

@@ -7,6 +7,7 @@ class Sessions::Event
     begin
       backend = load_adapter(adapter)
     rescue => e
+      Rails.logger.error e
       return { event: 'error', data: { error: "No such event #{params[:event]}: #{e.inspect}", payload: params[:payload] } }
     end
 
@@ -16,6 +17,7 @@ class Sessions::Event
       instance.destroy
       result
     rescue => e
+      Rails.logger.error e
       return { event: 'error', data: { error: e.message, payload: params[:payload] } }
     end
   end

+ 4 - 0
lib/sessions/event/base.rb

@@ -15,6 +15,10 @@ class Sessions::Event::Base
     ActiveRecord::Base.establish_connection
   end
 
+  def self.inherited(subclass)
+    subclass.instance_variable_set(:@database_connection, @database_connection)
+  end
+
   def websocket_send(recipient_client_id, data)
     msg = if data.class != Array
             "[#{data.to_json}]"

+ 85 - 0
test/unit/chat_test.rb

@@ -39,6 +39,91 @@ class ChatTest < ActiveSupport::TestCase
     Setting.set('chat', false)
   end
 
+  test 'instance_variable test' do
+    assert_nil(Sessions::Event::Base.instance_variable_get(:@database_connection))
+    assert_equal(Sessions::Event::ChatBase.instance_variable_get(:@database_connection), true)
+    assert_equal(Sessions::Event::ChatStatusAgent.instance_variable_get(:@database_connection), true)
+  end
+
+  # check if db connection is available for chat events
+  # see: https://github.com/zammad/zammad/issues/2353
+  test 'chat event db connection test' do
+
+    class DummyWs
+      def send(msg)
+        Rails.logger.info "WS send: #{msg}"
+      end
+    end
+
+    # with websockets
+    assert(User.first)
+
+    message = Sessions::Event.run(
+      event: 'login',
+      payload: {},
+      session: 123,
+      remote_ip: '127.0.0.1',
+      client_id: '123',
+      clients: {
+        '123' => {
+          websocket: DummyWs.new # to simulate a ws connection
+        }
+      },
+      options: {},
+    )
+    assert_equal(message, false)
+
+    assert_raises(ActiveRecord::ConnectionNotEstablished) do
+      User.first
+    end
+
+    message = Sessions::Event.run(
+      event: 'chat_status_customer',
+      payload: {},
+      session: 123,
+      remote_ip: '127.0.0.1',
+      client_id: '123',
+      clients: {
+        '123' => DummyWs.new # to simulate a ws connection
+      },
+      options: {},
+    )
+    assert_equal(message[:event], 'chat_error')
+
+    assert_raises(ActiveRecord::ConnectionNotEstablished) do
+      User.first
+    end
+
+    # re-establish connection
+    ActiveRecord::Base.establish_connection
+
+    # with ajax long polling
+    assert(User.first)
+    message = Sessions::Event.run(
+      event: 'login',
+      payload: {},
+      session: 123,
+      remote_ip: '127.0.0.1',
+      client_id: '123',
+      clients: {},
+      options: {},
+    )
+    assert_equal(message, false)
+    assert(User.first)
+
+    message = Sessions::Event.run(
+      event: 'chat_status_customer',
+      payload: {},
+      session: 123,
+      remote_ip: '127.0.0.1',
+      client_id: '123',
+      clients: {},
+      options: {},
+    )
+    assert_equal(message[:event], 'chat_error')
+    assert(User.first)
+  end
+
   test 'default test' do
 
     chat = Chat.create_or_update(