Module: Isomorfeus::Transport

Defined in:
lib/isomorfeus/transport.rb,
lib/isomorfeus/transport/imports.rb,
lib/isomorfeus/transport/version.rb,
lib/isomorfeus/transport/ssr_login.rb,
lib/isomorfeus/transport/middlewares.rb,
lib/isomorfeus/transport/request_agent.rb,
lib/isomorfeus/transport/response_agent.rb,
lib/isomorfeus/transport/compressor_rack.rb,
lib/isomorfeus/transport/rack_middleware.rb,
lib/isomorfeus/transport/client_processor.rb,
lib/isomorfeus/transport/server_processor.rb,
lib/isomorfeus/transport/websocket_client.rb,
lib/isomorfeus/transport/server_socket_processor.rb,
lib/isomorfeus/transport/handler/authentication_handler.rb

Defined Under Namespace

Modules: Handler, Imports, Middlewares, ServerProcessor Classes: ClientProcessor, CompressorRack, RackMiddleware, RequestAgent, ResponseAgent, ServerSocketProcessor, SsrLogin, WebsocketClient

Constant Summary collapse

PING =
`JSON.stringify({iso_ping: true})`
VERSION =
'2.5.5'

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#socketObject

Returns the value of attribute socket.



7
8
9
# File 'lib/isomorfeus/transport.rb', line 7

def socket
  @socket
end

Instance Method Details

#busy?Boolean

Returns:

  • (Boolean)


169
170
171
# File 'lib/isomorfeus/transport.rb', line 169

def busy?
  requests_in_progress[:requests].size != 0
end

#disconnectObject



74
75
76
77
# File 'lib/isomorfeus/transport.rb', line 74

def disconnect
  @socket.close if @socket
  @socket = nil
end

#get_agent_for_request_in_progress(request) ⇒ Object



181
182
183
184
# File 'lib/isomorfeus/transport.rb', line 181

def get_agent_for_request_in_progress(request)
  agent_id = requests_in_progress[:requests][request]
  Isomorfeus::Transport::RequestAgent.get(agent_id)
end

#initObject



9
10
11
12
13
# File 'lib/isomorfeus/transport.rb', line 9

def init
  @socket = nil
  promise_connect if Isomorfeus.on_browser? || Isomorfeus.on_mobile?
  true
end

#keep_session_aliveObject



67
68
69
70
71
72
# File 'lib/isomorfeus/transport.rb', line 67

def keep_session_alive
  after 480000 do
    @socket.send(PING)
    keep_session_alive
  end
end

#promise_connect(session_id = nil, promise = nil) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/isomorfeus/transport.rb', line 15

def promise_connect(session_id = nil, promise = nil)
  promise = Promise.new unless promise
  if @socket && @socket.ready_state < 2
    promise.resolve(true)
    return promise
  end
  if on_browser?
    window_protocol = `window.location.protocol`
    ws_protocol = window_protocol == 'https:' ? 'wss:' : 'ws:'
    ws_url = "#{ws_protocol}//#{`window.location.host`}#{Isomorfeus.api_websocket_path}"
  else
    ws_url = "#{Isomorfeus::TopLevel.transport_ws_url}"
  end
  headers = (session_id.nil? || session_id.empty?) ? nil : { 'Cookie': "session=#{session_id}" }
  @socket = Isomorfeus::Transport::WebsocketClient.new(ws_url, nil, headers)
  @socket.on_error do |error|
    if on_browser?
      `console.warn('Isomorfeus::Transport: Will try again, but so far error connecting:', error)`
      @socket.close
      after 1000 do
        Isomorfeus::Transport.promise_connect(session_id, promise)
      end
    else
      Isomorfeus.raise_error(message: error.JS[:message], stack: error.JS[:stack])
      promise.reject
    end
  end
  @socket.on_message do |event|
    json_hash = `Opal.Hash.$new(JSON.parse(event.data))`
    Isomorfeus::Transport::ClientProcessor.process(json_hash)
  end
  @socket.on_open do |event|
    init_promises = []
    Isomorfeus.transport_init_class_names.each do |constant|
      result = constant.constantize.send(:init)
      init_promises << result if result.class == Promise
    end
    open_promise = if init_promises.size > 0
                     Promise.when(*init_promises)
                   else
                     Promise.new.resolve(true)
                   end
    requests_in_progress[:requests].each_key do |request|
      agent = get_agent_for_request_in_progress(request)
      open_promise.then { promise_send_request(request) } if agent && !agent.sent
    end
    open_promise.then { promise.resolve(true) }
    keep_session_alive if on_browser?
  end
  promise
end

#promise_send_path(*path, &block) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/isomorfeus/transport.rb', line 79

def promise_send_path(*path, &block)
  request = {}
  inject_path = path[0...-1]
  last_inject_path_el = inject_path.last
  last_path_el = path.last
  inject_path.inject(request) do |memo, key|
    if key == last_inject_path_el
      memo[key] = last_path_el
    else
      memo[key] = {}
    end
  end
  Isomorfeus::Transport.promise_send_request(request, &block)
end

#promise_send_request(request, &block) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/isomorfeus/transport.rb', line 94

def promise_send_request(request, &block)
  agent = if request_in_progress?(request)
            get_agent_for_request_in_progress(request)
          else
            Isomorfeus::Transport::RequestAgent.new(request)
          end
  unless agent.sent
    if block_given?
      agent.promise.then do |response|
        block.call(response)
      end
    end
    register_request_in_progress(request, agent.id)
    Isomorfeus.raise_error(message: 'No socket!') unless @socket
    begin
      @socket.send(`JSON.stringify(#{{request: { agent_ids: { agent.id => request }}}.to_n})`)
      agent.sent = true
      after(Isomorfeus.on_ssr? ? 5000 : 20000) do
        unless agent.promise.realized?
          agent.promise.reject({agent_response: { error: 'Request timeout!' }, full_response: {}})
        end
      end
    rescue
      @socket.close
      after (Isomorfeus.on_ssr? ? 10 : 3000) do
        @reconnect = true
        if on_browser?
          Isomorfeus::Transport.promise_connect
        else
          Isomorfeus.raise_error(message: 'Transport lost connection!')
        end
      end
    end
  end
  agent.promise
end

#promise_subscribe(channel_class, channel, &block) ⇒ Object



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/isomorfeus/transport.rb', line 137

def promise_subscribe(channel_class_name, channel)
  request = { subscribe: true, class: channel_class_name, channel: channel }
  if request_in_progress?(request)
    agent = get_agent_for_request_in_progress(request)
  else
    agent = Isomorfeus::Transport::RequestAgent.new(request)
    register_request_in_progress(request, agent.id)
    Isomorfeus.raise_error(message: 'No socket!') unless @socket
    @socket.send(`JSON.stringify(#{{ subscribe: { agent_ids: { agent.id => request }}}.to_n})`)
  end
  result_promise = agent.promise.then do |agent|
    agent.response
  end
  result_promise
end

#promise_unsubscribe(channel_class, channel, &block) ⇒ Object



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/isomorfeus/transport.rb', line 153

def promise_unsubscribe(channel_class_name, channel)
  request = { unsubscribe: true, class: channel_class_name, channel: channel }
  if request_in_progress?(request)
    agent = get_agent_for_request_in_progress(request)
  else
    agent = Isomorfeus::Transport::RequestAgent.new(request)
    register_request_in_progress(request, agent.id)
    Isomorfeus.raise_error(message: 'No socket!') unless @socket
    @socket.send(`JSON.stringify(#{{ unsubscribe: { agent_ids: { agent.id => request }}}.to_n})`)
  end
  result_promise = agent.promise.then do |agent|
    agent.response
  end
  result_promise
end

#register_request_in_progress(request, agent_id) ⇒ Object



186
187
188
189
# File 'lib/isomorfeus/transport.rb', line 186

def register_request_in_progress(request, agent_id)
  requests_in_progress[:requests][request] = agent_id
  requests_in_progress[:agent_ids][agent_id] = request
end

#request_in_progress?(request) ⇒ Boolean

Returns:

  • (Boolean)


177
178
179
# File 'lib/isomorfeus/transport.rb', line 177

def request_in_progress?(request)
  requests_in_progress[:requests].key?(request)
end

#requests_in_progressObject



173
174
175
# File 'lib/isomorfeus/transport.rb', line 173

def requests_in_progress
  @requests_in_progress ||= { requests: {}, agent_ids: {} }
end

#send_message(channel_class, channel, message) ⇒ Object

RUBY_ENGINE



196
197
198
199
200
# File 'lib/isomorfeus/transport.rb', line 196

def send_message(channel_class, channel, message)
  Isomorfeus.raise_error(message: 'No socket!') unless @socket
  @socket.send(`JSON.stringify(#{{ notification: { class: channel_class.name, channel: channel, message: message }}.to_n})`)
  true
end

#unregister_request_in_progress(agent_id) ⇒ Object



191
192
193
194
# File 'lib/isomorfeus/transport.rb', line 191

def unregister_request_in_progress(agent_id)
  request = requests_in_progress[:agent_ids].delete(agent_id)
  requests_in_progress[:requests].delete(request)
end