Class: Faye::Client

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
EventMachine::Deferrable
Defined in:
lib/faye/client.rb

Constant Summary collapse

UNCONNECTED =
1
CONNECTING =
2
CONNECTED =
3
DISCONNECTED =
4
HANDSHAKE =
'handshake'
RETRY =
'retry'
NONE =
'none'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(endpoint = nil) ⇒ Client

Returns a new instance of Client.



19
20
21
22
23
24
25
26
27
28
# File 'lib/faye/client.rb', line 19

def initialize(endpoint = nil)
  @endpoint = endpoint || RackAdapter::DEFAULT_ENDPOINT
  @transport = Transport.get(self)
  @state     = UNCONNECTED
  @namespace = Namespace.new
  @outbox    = []
  @channels  = Channel::Tree.new
  
  @advice = {'reconnect' => RETRY, 'interval' => Connection::INTERVAL}
end

Instance Attribute Details

#endpointObject (readonly)

Returns the value of attribute endpoint.



17
18
19
# File 'lib/faye/client.rb', line 17

def endpoint
  @endpoint
end

#namespaceObject (readonly)

Returns the value of attribute namespace.



17
18
19
# File 'lib/faye/client.rb', line 17

def namespace
  @namespace
end

Instance Method Details

#connect(&block) ⇒ Object

Request Response MUST include: * channel MUST include: * channel

* clientId                           * successful
* connectionType                     * clientId

MAY include: * ext MAY include: * error

* id                                 * advice
                                     * ext
                                     * id
                                     * timestamp


84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/faye/client.rb', line 84

def connect(&block)
  return if @advice['reconnect'] == NONE or
            @state == DISCONNECTED
  
  if @advice['reconnect'] == HANDSHAKE or @state == UNCONNECTED
    return handshake { connect(&block) }
  end
  
  return callback(&block) if @state == CONNECTING
  return unless @state == CONNECTED
  
  set_deferred_status(:succeeded)
  set_deferred_status(:deferred)
  block.call if block_given?
  
  return unless @connection_id.nil?
  @connection_id = @namespace.generate
  
  @transport.send({
    'channel'         => Channel::CONNECT,
    'clientId'        => @client_id,
    'connectionType'  => @transport.connection_type,
    'id'              => @connection_id
    
  }) do |response|
    @connection_id = nil
    add_timer(@advice['interval'] / 1000.0) { connect }
  end
end

#disconnectObject

Request Response MUST include: * channel MUST include: * channel

* clientId                           * successful

MAY include: * ext * clientId

* id                  MAY include:   * error
                                     * ext
                                     * id


121
122
123
124
125
126
127
128
129
130
131
# File 'lib/faye/client.rb', line 121

def disconnect
  return unless @state == CONNECTED
  @state = DISCONNECT
  
  @transport.send({
    'channel'   => Channel::DISCONNECT,
    'clientId'  => @client_id
  })
  
  @channels = Channel::Tree.new
end

#handle_advice(advice) ⇒ Object



216
217
218
219
# File 'lib/faye/client.rb', line 216

def handle_advice(advice)
  @advice.update(advice)
  @client_id = nil if @advice['reconnect'] == HANDSHAKE
end

#handshake(&block) ⇒ Object

Request MUST include: * channel

* version
* supportedConnectionTypes

MAY include: * minimumVersion

* ext
* id

Success Response Failed Response MUST include: * channel MUST include: * channel

* version                                    * successful
* supportedConnectionTypes                   * error
* clientId                    MAY include:   * supportedConnectionTypes
* successful                                 * advice

MAY include: * minimumVersion * version

* advice                                     * minimumVersion
* ext                                        * ext
* id                                         * id
* authSuccessful


49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/faye/client.rb', line 49

def handshake(&block)
  return if @advice['reconnect'] == NONE
  return if @state != UNCONNECTED
  
  @state = CONNECTING
  
  @transport.send({
    'channel'     => Channel::HANDSHAKE,
    'version'     => BAYEUX_VERSION,
    'supportedConnectionTypes' => Transport.supported_connection_types
    
  }) do |response|
    
    unless response['successful']
      add_timer(@advice['interval'] / 1000.0) { handshake(&block) }
      return @state = UNCONNECTED
    end
    
    @state     = CONNECTED
    @client_id = response['clientId']
    @transport = Transport.get(self, response['supportedConnectionTypes'])
    
    block.call if block_given?
  end
end

#publish(channel, data) ⇒ Object

Request Response MUST include: * channel MUST include: * channel

* data                               * successful

MAY include: * clientId MAY include: * id

* id                                 * error
* ext                                * ext


197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/faye/client.rb', line 197

def publish(channel, data)
  connect {
    validate_channels([channel])
    
    enqueue({
      'channel'   => channel,
      'data'      => data,
      'clientId'  => @client_id
    })
    
    return if @timeout
    
    @timeout = add_timer(Connection::MAX_DELAY) do
      @timeout = nil
      flush!
    end
  }
end

#send_to_subscribers(message) ⇒ Object



221
222
223
224
# File 'lib/faye/client.rb', line 221

def send_to_subscribers(message)
  channels = @channels.glob(message['channel'])
  channels.each { |callback| callback.call(message['data']) }
end

#subscribe(channels, &block) ⇒ Object

Request Response MUST include: * channel MUST include: * channel

* clientId                           * successful
* subscription                       * clientId

MAY include: * ext * subscription

* id                  MAY include:   * error
                                     * advice
                                     * ext
                                     * id
                                     * timestamp


143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/faye/client.rb', line 143

def subscribe(channels, &block)
  connect {
    channels = [channels].flatten
    validate_channels(channels)
    
    @transport.send({
      'channel'       => Channel::SUBSCRIBE,
      'clientId'      => @client_id,
      'subscription'  => channels
      
    }) do |response|
      if response['successful']
        channels = [response['subscription']].flatten
        channels.each { |channel| @channels[channel] = block }
      end
    end
  }
end

#unsubscribe(channels, &block) ⇒ Object

Request Response MUST include: * channel MUST include: * channel

* clientId                           * successful
* subscription                       * clientId

MAY include: * ext * subscription

* id                  MAY include:   * error
                                     * advice
                                     * ext
                                     * id
                                     * timestamp


172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/faye/client.rb', line 172

def unsubscribe(channels, &block)
  connect {
    channels = [channels].flatten
    validate_channels(channels)
    
    @transport.send({
      'channel'       => Channel::UNSUBSCRIBE,
      'clientId'      => @client_id,
      'subscription'  => channels
      
    }) do |response|
      if response['successful']
        channels = [response['subscription']].flatten
        channels.each { |channel| @channels[channel] = nil }
      end
    end
  }
end