Class: Juggernaut::Client

Inherits:
Object
  • Object
show all
Includes:
Miscel
Defined in:
lib/juggernaut/client.rb

Constant Summary collapse

@@clients =
[ ]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Miscel

#config_path, #log_path, #logger, #options, #options=, #pid_path

Constructor Details

#initialize(subscriber, request) ⇒ Client

Returns a new instance of Client.



92
93
94
95
96
97
98
99
100
# File 'lib/juggernaut/client.rb', line 92

def initialize(subscriber, request)
  @connections = []
  @id         = request[:client_id]
  @session_id = request[:session_id]
  @messages   = []
  @logout_timeout = 0
  self.register
  add_new_connection(subscriber)
end

Instance Attribute Details

#connectionsObject (readonly)

Returns the value of attribute connections.



14
15
16
# File 'lib/juggernaut/client.rb', line 14

def connections
  @connections
end

#idObject (readonly)

Returns the value of attribute id.



12
13
14
# File 'lib/juggernaut/client.rb', line 12

def id
  @id
end

#session_idObject

Returns the value of attribute session_id.



13
14
15
# File 'lib/juggernaut/client.rb', line 13

def session_id
  @session_id
end

Class Method Details

.client_registered?(client) ⇒ Boolean

Returns:

  • (Boolean)


83
84
85
# File 'lib/juggernaut/client.rb', line 83

def client_registered?(client)
  @@clients.include?(client)
end

.find(&block) ⇒ Object



33
34
35
# File 'lib/juggernaut/client.rb', line 33

def find(&block)
  @@clients.select(&block).uniq
end

.find_allObject

Client find methods



29
30
31
# File 'lib/juggernaut/client.rb', line 29

def find_all
  @@clients
end

.find_by_channels(channels) ⇒ Object



48
49
50
51
52
# File 'lib/juggernaut/client.rb', line 48

def find_by_channels(channels)
  find do |client|
    client.has_channels?(channels)
  end
end

.find_by_id(id) ⇒ Object



37
38
39
# File 'lib/juggernaut/client.rb', line 37

def find_by_id(id)
  find { |client| client.id == id }.first
end

.find_by_id_and_channels(id, channels) ⇒ Object



54
55
56
57
58
# File 'lib/juggernaut/client.rb', line 54

def find_by_id_and_channels(id, channels)
  find do |client|
    client.has_channels?(channels) && client.id == id
  end.first
end

.find_by_signature(signature) ⇒ Object



41
42
43
44
45
46
# File 'lib/juggernaut/client.rb', line 41

def find_by_signature(signature)
  # signature should be unique
  find do |client|
    client.connections.select { |connection| connection.signature == signature }.any?
  end.first
end

.find_or_create(subscriber, request) ⇒ Object

Actually does a find_or_create_by_id



18
19
20
21
22
23
24
25
26
# File 'lib/juggernaut/client.rb', line 18

def find_or_create(subscriber, request)
  if client = find_by_id(request[:client_id])
    client.session_id = request[:session_id]
    client.add_new_connection(subscriber)
    client
  else
    self.new(subscriber, request)
  end
end

.register_client(client) ⇒ Object



79
80
81
# File 'lib/juggernaut/client.rb', line 79

def register_client(client)
  @@clients << client unless @@clients.include?(client)
end

.reset!Object



75
76
77
# File 'lib/juggernaut/client.rb', line 75

def reset!
  @@clients.clear
end

.send_logouts_after_timeoutObject



60
61
62
63
64
65
66
# File 'lib/juggernaut/client.rb', line 60

def send_logouts_after_timeout
  @@clients.each do |client|
    if client.give_up?
      client.logout_request
    end
  end
end

.send_logouts_to_all_clientsObject

Called when the server is shutting down



69
70
71
72
73
# File 'lib/juggernaut/client.rb', line 69

def send_logouts_to_all_clients
  @@clients.each do |client|
    client.logout_request
  end
end

.unregister_client(client) ⇒ Object



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

def unregister_client(client)
  @@clients.delete(client)
end

Instance Method Details

#add_channels(channels) ⇒ Object



180
181
182
183
184
# File 'lib/juggernaut/client.rb', line 180

def add_channels(channels)
  @connections.each do |em|
    em.add_channels(channels)
  end
end

#add_new_connection(subscriber) ⇒ Object



111
112
113
# File 'lib/juggernaut/client.rb', line 111

def add_new_connection(subscriber)
  @connections << subscriber
end

#alive?Boolean

Returns:

  • (Boolean)


192
193
194
# File 'lib/juggernaut/client.rb', line 192

def alive?
  @connections.select { |em| em.alive? }.any?
end

#channelsObject



169
170
171
# File 'lib/juggernaut/client.rb', line 169

def channels
  @connections.collect { |em| em.channels }.flatten.uniq
end

#friendly_idObject



115
116
117
118
119
120
121
# File 'lib/juggernaut/client.rb', line 115

def friendly_id
  if self.id
    "with ID #{self.id}"
  else
    "session #{self.session_id}"
  end
end

#give_up?Boolean

This client is only dead if there are no connections and we are past the timeout (if we are within the timeout, the user could just be doing a page reload or going to a new page)

Returns:

  • (Boolean)


199
200
201
# File 'lib/juggernaut/client.rb', line 199

def give_up?
  !alive? and (Time.now > @logout_timeout)
end

#has_channels?(channels) ⇒ Boolean

Returns:

  • (Boolean)


173
174
175
176
177
178
# File 'lib/juggernaut/client.rb', line 173

def has_channels?(channels)
  @connections.each do |em|
    return true if em.has_channels?(channels)
  end
  false
end

#logout_connection_request(channels) ⇒ Object



128
129
130
131
# File 'lib/juggernaut/client.rb', line 128

def logout_connection_request(channels)
  return true unless options[:logout_connection_url]
  post_request(options[:logout_connection_url], channels, :timeout => options[:post_request_timeout] || 5)
end

#logout_requestObject



133
134
135
136
137
138
# File 'lib/juggernaut/client.rb', line 133

def logout_request
  self.unregister
  logger.debug("Timed out client #{friendly_id}")
  return true unless options[:logout_url]
  post_request(options[:logout_url], [ ], :timeout => options[:post_request_timeout] || 5)
end

#remove_channels!(channels) ⇒ Object



186
187
188
189
190
# File 'lib/juggernaut/client.rb', line 186

def remove_channels!(channels)
  @connections.each do |em|
    em.remove_channels!(channels)
  end
end

#remove_connection(connection) ⇒ Object



140
141
142
143
144
# File 'lib/juggernaut/client.rb', line 140

def remove_connection(connection)
  @connections.delete(connection)
  self.reset_logout_timeout!
  self.logout_request if self.give_up?
end

#send_message(msg, channels = nil) ⇒ Object



146
147
148
149
# File 'lib/juggernaut/client.rb', line 146

def send_message(msg, channels = nil)
  store_message(msg, channels) if options[:store_messages]
  send_message_to_connections(msg, channels)
end

#send_queued_messages(connection) ⇒ Object

Send messages that are queued up for this particular client. Messages are only queued for previously-connected clients.



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

def send_queued_messages(connection)
  self.expire_queued_messages!

  # Weird looping because we don't want to send messages that get
  # added to the array after we start iterating (since those will
  # get sent to the client anyway).
  @length = @messages.length

  logger.debug("Sending #{@length} queued message(s) to client #{friendly_id}")

  @length.times do |id|
    message = @messages[id]
    send_message_to_connection(connection, message[:message], message[:channels])
  end
end

#subscription_request(channels) ⇒ Object



123
124
125
126
# File 'lib/juggernaut/client.rb', line 123

def subscription_request(channels)
  return true unless options[:subscription_url]
  post_request(options[:subscription_url], channels, :timeout => options[:post_request_timeout] || 5)
end

#to_jsonObject



102
103
104
105
106
107
108
109
# File 'lib/juggernaut/client.rb', line 102

def to_json
  {
    :client_id  => @id,
    :num_connections => @connections.size,
    :session_id => @session_id,
    :channels => self.channels
  }.to_json
end