class Ribbon::Intercom::Service::Channel::Stores::RedisStore

Public Class Methods

new(params={}) click to toggle source
# File lib/ribbon/intercom/service/channel/stores/redis_store.rb, line 9
def initialize(params={})
  if params[:url]
    @_redis = Redis.new(url: params[:url])
  elsif params[:redis]
    @_redis = params[:redis]
  else
    raise Errors::InvalidStoreParamsError
  end
end

Public Instance Methods

delete(channel) click to toggle source
# File lib/ribbon/intercom/service/channel/stores/redis_store.rb, line 58
def delete(channel)
  raise Errors::InvalidChannelError, channel.inspect unless channel.is_a?(Channel)

  @_redis.del(_key_name(channel))
  @_redis.del(_key_name(channel, 'permissions'))
  nil
end
lookup_channel(token) click to toggle source
# File lib/ribbon/intercom/service/channel/stores/redis_store.rb, line 23
def lookup_channel(token)
  if (data=_load_data(token))
    Channel.new(self, data)
  end
end
persist(channel) click to toggle source
# File lib/ribbon/intercom/service/channel/stores/redis_store.rb, line 29
def persist(channel)
  raise Errors::InvalidChannelError, channel.inspect unless channel.is_a?(Channel)

  channel.tap { |channel|
    data_hash = {}
    [:name, :token, :secret_hash_crt, :secret_hash_prv].each { |key|
      value = channel.send(key)
      data_hash[key] = value if value
    }

    # Save channel data as hash
    @_redis.mapped_hmset(_key_name(channel), data_hash)

    # Associate permissions set to its channel
    channel.permissions.each { |p|
      @_redis.sadd(_key_name(channel, 'permissions'), p)
    }

    # Save signing keys
    key_hash = Hash[
      channel.signing_keys.map { |key_id, data|
        [key_id, Base64.strict_encode64(Marshal.dump(data))]
      }
    ]

    @_redis.mapped_hmset(_key_name(channel, 'signing_keys'), key_hash) unless key_hash.empty?
  }
end
token_exists?(token) click to toggle source
# File lib/ribbon/intercom/service/channel/stores/redis_store.rb, line 19
def token_exists?(token)
  @_redis.exists("channel:#{token}")
end
with_lock(channel, ttl=1000) { |validity| ... } click to toggle source
# File lib/ribbon/intercom/service/channel/stores/redis_store.rb, line 66
def with_lock(channel, ttl=1000)
  Mutex.new(@_redis, _key_name(channel, 'lock')).synchronize(ttl) { |validity|
    start_time = Mutex.time_in_ms
    channel.refresh(_load_data(channel.token))
    yield validity - (Mutex.time_in_ms - start_time)
  }
end

Private Instance Methods

_key_name(channel_or_token, *sub_names) click to toggle source
# File lib/ribbon/intercom/service/channel/stores/redis_store.rb, line 189
def _key_name(channel_or_token, *sub_names)
  token = channel_or_token.is_a?(Channel) ? channel_or_token.token : channel_or_token
  ['channel', token, *sub_names].join(':')
end
_load_data(token) click to toggle source
# File lib/ribbon/intercom/service/channel/stores/redis_store.rb, line 76
def _load_data(token)
  channel_data_future = nil
  permissions_future  = nil
  signing_keys_future = nil

  @_redis.pipelined {
    channel_data_future = @_redis.hgetall(_key_name(token))
    permissions_future  = @_redis.smembers(_key_name(token, 'permissions'))
    signing_keys_future = @_redis.hgetall(_key_name(token, 'signing_keys'))
  }

  channel_data = channel_data_future.value

  if channel_data && !channel_data.empty?
    permissions = permissions_future.value

    signing_keys = signing_keys_future.value.map { |key_id, data|
      [key_id.to_i, Marshal.load(Base64.strict_decode64(data))]
    }.to_h

    Utils.symbolize_keys(
      channel_data.merge(
        may: permissions,
        signing_keys: signing_keys
      )
    )
  end
end