Class: AnyCable::RackServer::Socket

Inherits:
Object
  • Object
show all
Includes:
Logging
Defined in:
lib/anycable/rack-server/socket.rb

Constant Summary

Constants included from Logging

Logging::PREFIX

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(env, socket, version) ⇒ Socket

Returns a new instance of Socket.



11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/anycable/rack-server/socket.rb', line 11

def initialize(env, socket, version)
  log(:debug, "WebSocket version #{version}")
  @env = env
  @socket = socket
  @version = version

  @_open_handlers    = []
  @_message_handlers = []
  @_close_handlers   = []
  @_error_handlers   = []
  @_active           = true
end

Instance Attribute Details

#socketObject (readonly)

Returns the value of attribute socket.



9
10
11
# File 'lib/anycable/rack-server/socket.rb', line 9

def socket
  @socket
end

#versionObject (readonly)

Returns the value of attribute version.



9
10
11
# File 'lib/anycable/rack-server/socket.rb', line 9

def version
  @version
end

Instance Method Details

#closeObject

rubocop: enable Metrics/MethodLength



81
82
83
84
85
86
87
88
# File 'lib/anycable/rack-server/socket.rb', line 81

def close
  return unless @_active

  @_close_handlers.each(&:call)
  close!

  @_active = false
end

#closed?Boolean

Returns:

  • (Boolean)


90
91
92
# File 'lib/anycable/rack-server/socket.rb', line 90

def closed?
  socket.closed?
end

#listenObject

rubocop: disable Metrics/MethodLength



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/anycable/rack-server/socket.rb', line 57

def listen
  keepalive
  Thread.new do
    Thread.current.abort_on_exception = true
    begin
      @_open_handlers.each(&:call)
      each_frame do |data|
        @_message_handlers.each do |handler|
          begin
            handler.call(data)
          rescue => e # rubocop: disable Style/RescueStandardError
            log(:error, "Socket receive failed: #{e}")
            @_error_handlers.each { |eh| eh.call(e, data) }
            close
          end
        end
      end
    ensure
      close
    end
  end
end

#onclose(&block) ⇒ Object



48
49
50
# File 'lib/anycable/rack-server/socket.rb', line 48

def onclose(&block)
  @_close_handlers << block
end

#onerror(&block) ⇒ Object



52
53
54
# File 'lib/anycable/rack-server/socket.rb', line 52

def onerror(&block)
  @_error_handlers << block
end

#onmessage(&block) ⇒ Object



44
45
46
# File 'lib/anycable/rack-server/socket.rb', line 44

def onmessage(&block)
  @_message_handlers << block
end

#onopen(&block) ⇒ Object



40
41
42
# File 'lib/anycable/rack-server/socket.rb', line 40

def onopen(&block)
  @_open_handlers << block
end

#requestObject



36
37
38
# File 'lib/anycable/rack-server/socket.rb', line 36

def request
  @_request ||= ::Rack::Request.new(@env)
end

#transmit(data, type: :text) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
# File 'lib/anycable/rack-server/socket.rb', line 24

def transmit(data, type: :text)
  frame = WebSocket::Frame::Outgoing::Server.new(
    version: version,
    data: data,
    type: type
  )
  socket.write(frame.to_s)
rescue IOError, Errno::EPIPE, Errno::ETIMEDOUT => e
  log(:error, "Socket send failed: #{e}")
  close
end