Class: ScClient

Inherits:
Object
  • Object
show all
Includes:
DataModels, Emitter, Log, Reconnect
Defined in:
lib/sc_client.rb

Overview

Class ScClient provides an interface to connect to the socketcluster server

Author:

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Log

#disable_logging, #enable_logging, #initialize_logger, #logger, #set_logging_level

Methods included from Reconnect

#initialize_reconnect, #set_reconnection_listener

Methods included from DataModels

#get_ack_object, #get_emit_ack_object, #get_emit_object, #get_handshake_object, #get_publish_object, #get_subscribe_object, #get_unsubscribe_object

Methods included from Emitter

#execute, #executeack, #haseventack, #initialize_emitter, #on, #onack, #onchannel

Constructor Details

#initialize(url) ⇒ ScClient

Initializes instance variables in socketcluster client

Parameters:

  • url (String)

    ScServer connection URL



29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/sc_client.rb', line 29

def initialize(url)
  @id = ''
  @cnt = 0
  @url = url
  @acks = {}
  @channels = []
  @enable_reconnection = false
  @delay = 3
  initialize_emitter
  initialize_reconnect
  initialize_logger
end

Instance Attribute Details

#max_attemptsObject

Returns the value of attribute max_attempts.



22
23
24
# File 'lib/sc_client.rb', line 22

def max_attempts
  @max_attempts
end

#max_reconnect_intervalObject

Returns the value of attribute max_reconnect_interval.



22
23
24
# File 'lib/sc_client.rb', line 22

def max_reconnect_interval
  @max_reconnect_interval
end

#reconnect_intervalObject

Returns the value of attribute reconnect_interval.



22
23
24
# File 'lib/sc_client.rb', line 22

def reconnect_interval
  @reconnect_interval
end

Instance Method Details

#ack_block(cid) ⇒ Lambda

Acknowledment block to be executed on event

Parameters:

  • cid (String)

    @cnt id received from ScServer

Returns:

  • (Lambda)

    Acknowledgment to be sent to ScServer



108
109
110
111
112
113
# File 'lib/sc_client.rb', line 108

def ack_block(cid)
  ws = @ws
  lambda do |error, data|
    ws.send(get_ack_object(error, data, cid))
  end
end

#connectObject

Connects to the ScServer



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/sc_client.rb', line 121

def connect
  EM.epoll

  EM.run do
    trap('TERM') do
      @enable_reconnection = false
      disconnect
    end

    trap('INT') do
      @enable_reconnection = false
      disconnect
    end

    @ws = WebSocket::EventMachine::Client.connect(uri: @url)

    @ws.onopen do
      reset_value
      @ws.send(get_handshake_object(increment_cnt).to_json)
      @on_connected.call if @on_connected
    end

    @ws.onmessage do |message, _type|
      @logger.info("Message received : #{message}") if @logger
      if message == ''
        @logger.info("Ping received, sending PONG back")
        @ws.send('')
      else
        main_object = JSON.parse(message)
        data_object = main_object['data']
        rid = main_object['rid']
        cid = main_object['cid']
        event = main_object['event']
        result = Parser.parse(event, rid)
        if result == Parser::CHECK_AUTHENTICATION
          if @on_authentication
            @id = data_object['id']
            @on_authentication.call(self, data_object['isAuthenticated'])
          end
          subscribe_channels
        elsif result == Parser::PUBLISH
          execute(data_object['channel'], data_object['data'])
        elsif result == Parser::REMOVE_AUTHENTICATION
          @auth_token = nil
        elsif result == Parser::SET_AUTHENTICATION
          if @on_set_authentication
            @on_set_authentication.call(self, data_object['token'])
          end
        elsif result == Parser::EVENT
          if haseventack(event)
            executeack(event, data_object, ack_block(cid))
          else
            execute(event, data_object)
          end
        else # Parser::ACKNOWLEDGEMENT
          tuple = @acks[rid] if @acks.include?(rid)
          if tuple
            ack = tuple[1]
            ack.call(tuple[0], String(main_object['error']), String(main_object['data']))
          end
        end
      end
    end

    @ws.onerror do |error|
      @on_connect_error.call(error) if @on_connect_error
    end

    @ws.onclose do
      if should_reconnect
        @reconnect_interval = @max_reconnect_interval if @reconnect_interval > @max_reconnect_interval
        sleep(@reconnect_interval / 1000)
        @attempts_made += 1
        @logger.info("Attempting to reconnect : #{@attempts_made}") if @logger
        connect
      else
        stop
      end
    end

    def stop
      EventMachine.stop
    end
  end
end

#disconnectObject

Disconnects the connection with ScServer



235
236
237
238
239
# File 'lib/sc_client.rb', line 235

def disconnect
  @on_disconnected.call if @on_disconnected
  @enable_reconnection = false
  @ws.close
end

#emit(event, object) ⇒ Object

Emits the specified event on the corresponding server-side socket

Parameters:

  • event (String)

    Event

  • object (String)

    Data for the specified event



249
250
251
# File 'lib/sc_client.rb', line 249

def emit(event, object)
  @ws.send(get_emit_object(event, object).to_json)
end

#emitack(event, object, ack) ⇒ <type>

Emits the specified event on the corresponding server-side socket with acknowledgment

Parameters:

  • event (String)

    Event

  • object (String)

    Data for the specified event

  • ack (Lambda)

    Block to execute on event acknowledgment

Returns:

  • (<type>)

    <description>



262
263
264
265
# File 'lib/sc_client.rb', line 262

def emitack(event, object, ack)
  @ws.send(get_emit_ack_object(event, object, increment_cnt).to_json)
  @acks[@cnt] = [event, ack]
end

#publish(channel, data) ⇒ Object

Publish data to the specified channel name

Parameters:

  • channel (String)

    A channel name

  • data (String)

    Data to be published on the channel



327
328
329
# File 'lib/sc_client.rb', line 327

def publish(channel, data)
  @ws.send(get_publish_object(channel, data, increment_cnt).to_json)
end

#publishack(channel, data, ack) ⇒ Object

Publish data to the specified channel name

Parameters:

  • channel (String)

    A channel name

  • data (String)

    Data to be published on the channel

  • ack (Lambda)

    Block to execute on publish acknowledgment



340
341
342
343
# File 'lib/sc_client.rb', line 340

def publishack(channel, data, ack)
  @ws.send(get_publish_object(channel, data, increment_cnt).to_json)
  @acks[@cnt] = [channel, ack]
end

#set_auth_token(token) ⇒ Object

Method to set the authentication token

Parameters:

  • token (String)

    Authentication token provided by ScServer



77
78
79
# File 'lib/sc_client.rb', line 77

def set_auth_token(token)
  @auth_token = token.to_s
end

#set_authentication_listener(on_set_authentication, on_authentication) ⇒ Object

Adds handler for authentication

Parameters:

  • on_set_authentication (Lambda)

    Block to set authentication token

  • on_authentication (Lambda)

    Block to execute on authentication



65
66
67
68
# File 'lib/sc_client.rb', line 65

def set_authentication_listener(on_set_authentication, on_authentication)
  @on_set_authentication = on_set_authentication
  @on_authentication = on_authentication
end

#set_basic_listener(on_connected, on_disconnected, on_connect_error) ⇒ Object

Adds handler for connect, disconnect and error

Parameters:

  • on_connected (Lambda)

    Block to execute on connected

  • on_disconnected (Lambda)

    Block to execute on disconnected

  • on_connect_error (Lambda)

    Block to execute on connection error



51
52
53
54
55
# File 'lib/sc_client.rb', line 51

def set_basic_listener(on_connected, on_disconnected, on_connect_error)
  @on_connected = on_connected
  @on_disconnected = on_disconnected
  @on_connect_error = on_connect_error
end

#set_delay(delay) ⇒ Object

Set the delay for reconnection to ScServer

Parameters:

  • delay (Integer)

    Delay in seconds to reconnect



214
215
216
# File 'lib/sc_client.rb', line 214

def set_delay(delay)
  @delay = delay
end

#set_reconnection(enable) ⇒ Object

Allows to reconnect to ScServer

Parameters:

  • enable (Boolean)

    True to reconnect to server, False to disconnect



225
226
227
# File 'lib/sc_client.rb', line 225

def set_reconnection(enable)
  @enable_reconnection = enable
end

#subscribe(channel) ⇒ Object

Subscribes to a particular channel

Parameters:

  • channel (String)

    A channel name



274
275
276
277
# File 'lib/sc_client.rb', line 274

def subscribe(channel)
  @ws.send(get_subscribe_object(channel, increment_cnt).to_json)
  @channels << channel unless @channels.include?(channel)
end

#subscribe_channelsObject

Subscribe all the channels available



97
98
99
# File 'lib/sc_client.rb', line 97

def subscribe_channels
  @channels.each { |channel| subscribe(channel) }
end

#subscribeack(channel, ack) ⇒ Object

Subscribes to a particular channel with acknowledgment

Parameters:

  • channel (String)

    A channel name

  • ack (Lambda)

    Block to execute on subscribe acknowledgment



287
288
289
290
291
# File 'lib/sc_client.rb', line 287

def subscribeack(channel, ack)
  @ws.send(get_subscribe_object(channel, increment_cnt).to_json)
  @channels << channel
  @acks[@cnt] = [channel, ack]
end

#subscribed_channelsObject

Get the list of all subscribed channels



87
88
89
# File 'lib/sc_client.rb', line 87

def subscribed_channels
  @channels
end

#unsubscribe(channel) ⇒ Object

Unsubscribes to a particular channel

Parameters:

  • channel (String)

    A channel name



300
301
302
303
# File 'lib/sc_client.rb', line 300

def unsubscribe(channel)
  @ws.send(get_unsubscribe_object(channel, increment_cnt).to_json)
  @channels.delete(channel)
end

#unsubscribeack(channel, ack) ⇒ Object

Unsubscribes to a particular channel with acknowledgment

Parameters:

  • channel (String)

    A channel name

  • ack (Lambda)

    Block to execute on unsubscribe acknowledgment



313
314
315
316
317
# File 'lib/sc_client.rb', line 313

def unsubscribeack(channel, ack)
  @ws.send(get_unsubscribe_object(channel, increment_cnt).to_json)
  @channels.delete(channel)
  @acks[@cnt] = [channel, ack]
end