Class: Roda::Component::Faye::ChannelManager

Inherits:
Object
  • Object
show all
Defined in:
lib/roda/component/faye.rb

Instance Method Summary collapse

Instance Method Details

#get_app(request) ⇒ Object



223
224
225
226
227
228
# File 'lib/roda/component/faye.rb', line 223

def get_app request
  request.env['RODA_COMPONENT_FROM_FAYE'] = true
  a = Class.new(Roda::Component.app.class).new
  a.instance_variable_set(:@_request, request)
  a
end

#incoming(message, r, callback) ⇒ Object



118
119
120
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
# File 'lib/roda/component/faye.rb', line 118

def incoming(message, r, callback)
  r.env['RODA_COMPONENT_FROM_FAYE'] = true
  r.env['HTTP_X_RODA_COMPONENT_ON_SERVER'] = true

  app = get_app(r)

  session_id = r.session['session_id']
  public_id  = message['ext'] && message['ext']['public_id']
  private_id = message['ext'] && message['ext'].delete('private_id')
  key        = "#{app.component_opts[:redis_namespace]}users:#{session_id}"

  case message['channel']
  when '/meta/connect'
    if session_id
      redis.call 'HSET', "#{key}/ids", private_id, public_id
      # puts redis.call 'HGETALL', "#{key}/ids"
    end
    callback.call message
  when '/meta/disconnect'
    callback.call message

    redis.call 'DEL', "#{key}/ids"
    channels = redis.call 'GET', "#{key}/channels/#{public_id}"
    channels = channels ? JSON.parse(channels) : []

    channels.each do |channel|
      send_sub_to({
        'channel'      => '/meta/unsubscribe',
        'subscription' => channel,
        'ext'          => message['ext']
      }, public_id, private_id, app, key, r)
    end

    redis.call 'DEL', "#{key}/channels/#{public_id}"
  when '/meta/subscribe', '/meta/unsubscribe'
    if message['subscription'][%r{\A/components/}]
      callback.call message
      send_sub_to message, public_id, private_id, app, key, r
    end
  else
    if data = message['data']
      case data['type']
      when 'event'
        options ||= {}
        options.merge! data['local']

        data['event_type'] == 'call' \
          ? options[:call]    = data['event_method'] \
          : options[:trigger] = data['event_method']

        begin
          message['data']['local'] = app.roda_component(:"#{data['name']}", options)
          message['channel']       = message['channel'].gsub(/outgoing/, 'incoming')
        rescue Exception => e
          #fix: faye extentions are capturing errors for some reason
          ap e.message
          ap e.message.inspect
        end
      end
    end

    callback.call message
  end
end

#outgoing(message, request, callback) ⇒ Object

/components/:id/:comp/:action



211
212
213
214
215
216
217
218
219
220
221
# File 'lib/roda/component/faye.rb', line 211

def outgoing(message, request, callback)
  app = get_app request

  # message[:data] = app.roda_component(:auth, call: :cow) || false

  # ap '====OUTGOING===='
  # ap message
  # ap '================'

  callback.call message
end

#redisObject



114
115
116
# File 'lib/roda/component/faye.rb', line 114

def redis
  @redis ||= Redic.new(Roda::Component.app.component_opts[:redis_uri])
end

#send_sub_to(message, public_id, private_id, app, key, request) ⇒ Object



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/roda/component/faye.rb', line 183

def send_sub_to message, public_id, private_id, app, key, request
  key = "#{key}/channels/#{public_id}"

  joining = message['channel'] == '/meta/subscribe' ? true : false

  component_name = message['subscription'].split('/').last

  channels = redis.call 'GET', key
  channels = channels ? JSON.parse(channels) : []

  if joining
    channels << message['subscription']
  else
    channels.delete message['subscription']
  end

  if channels.length
    redis.call 'SET', key, channels.to_json
  end

  data = app.roda_component(:"#{component_name}", { trigger: (joining ? :join : :leave), public_id: public_id, private_id: private_id })

  url = "http#{request.env['SERVER_PORT'] == '443' ? 's' : ''}://#{request.env['SERVER_NAME']}:#{request.env['SERVER_PORT']}/faye"
  client = ::Faye::Client.new(url)
  client.publish "/components/#{component_name}", type: (joining ? 'join' : 'leave'), public_id: public_id, token: app.component_opts[:token], local: data
end