lib/redis_token.rb in redis_token-0.0.4 vs lib/redis_token.rb in redis_token-0.0.5

- old
+ new

@@ -1,6 +1,8 @@ require 'redis_token/version' +require 'redis_token/serializers/native' + require 'redis' require 'securerandom' require 'time' @@ -23,10 +25,11 @@ # RedisToken.new(redis, ttl: 5.days, prefix: 'project.tokens.') # # @param [Hash] args # @option args [String] :prefix redis keys prefix (e.g. 'myproject.tokens.') # @option args [Integer] :ttl token time to live value (14 days by default) + # @option args [Class] :serializer_class serialization class, see RedisToken::Serializers::Native, or #use method # # @return [RedisToken] a new RedisToken instance def initialize(args = {}, opts = {}) @redis = if args.nil? || args.is_a?(Hash) init_params(args) @@ -39,28 +42,29 @@ # Create a new token # # @param [String] owner owner of a token, e.g. 'client.1' or 'user-123' # @param [Hash] args + # @option args [String] :token (SecureRandom.hex(16)) user defined token # @option args :payload # @option args [Integer] :ttl redefines the default ttl # # @return [String] a new token def create(owner, args = {}) raise 'owner should be specified' unless owner token = args[:token] || generate_token - value = { owner: owner, at: Time.now } + value = { owner: owner, at: Time.now.to_i } payload = args[:payload] value[:payload] = payload if payload @created_value = value key_ttl = args[:ttl] || @default_ttl @redis.multi do |multi| - multi.set(token_to_key(token), Marshal.dump(value), ex: key_ttl) + multi.set(token_to_key(token), serializer.pack(value), ex: key_ttl) multi.set(token_to_owner(owner, token), nil, ex: key_ttl) end token end @@ -81,11 +85,11 @@ key_ttl = args[:ttl] || @default_ttl @redis.multi do |multi| multi.expire(key, key_ttl) - multi.expire(token_to_owner(value[:owner], token), key_ttl) + multi.expire(token_to_owner(hash_get(value, :owner), token), key_ttl) end value end @@ -104,12 +108,12 @@ value[:payload] = args[:payload] key_ttl = args[:ttl] || @redis.ttl(key) @redis.multi do |multi| - multi.set(key, Marshal.dump(value), ex: key_ttl) - multi.expire(token_to_owner(value[:owner], token), key_ttl) + multi.set(key, serializer.pack(value), ex: key_ttl) + multi.expire(token_to_owner(hash_get(value, :owner), token), key_ttl) end true end @@ -117,11 +121,11 @@ # # @param [String] owner # # @return [Enumerator] def owned_by(owner) - owned_tokens(owner).map { |token| [token, redis_get(token_to_key(token))]} + owned_tokens(owner).map { |token| [token, redis_get(token_to_key(token))] } end # Delete a token # # @param [String] token @@ -132,11 +136,11 @@ value = redis_get(key) return false unless value @redis.multi do |multi| multi.del(key) - multi.del(token_to_owner(value[:owner], token)) + multi.del(token_to_owner(hash_get(value, :owner), token)) end true end @@ -164,19 +168,62 @@ # @return [Integer] ttl def ttl(token) @redis.ttl(token_to_key(token)) end + # Use custom serialization class + # + # Base serializer example: + # class RedisToken + # class Serializers + # class Native + # def pack(value) + # Marshal.dump(value) + # end + # + # def unpack(value) + # Marshal.load(value) + # end + # end + # end + # end + # + # MessagePack example: + # require 'msgpack' + # + # class MsgPackSerializer + # def pack(value) + # MessagePack.pack(value) + # end + # + # def unpack(value) + # MessagePack.unpack(value) + # end + # end + # + # RedisToken.new(prefix: PREFIX).use(MsgPackSerializer) + # + # @param [Object] serializer_class + # + # @return [RedisToken] + def use(serializer_class) + @serializer_class = serializer_class + self + end + private def generate_token SecureRandom.hex(16) end def init_params(args) @default_ttl = args[:ttl] || DEFAULT_TTL @prefix = args[:prefix] + + @serializer_class = args[:serializer_class] + @serializer_class = Serializers::Native unless @serializer_class end def token_to_key(token) "#{@prefix}#{token}" end @@ -190,27 +237,35 @@ end def redis_get(key) value = @redis.get(key) return unless value - Marshal.load(value) + serializer.unpack(value) end def owned_tokens(owner) mask = "#{@prefix}#{owner}.*" Enumerator.new do |y| - cursor = 0 + cursor = '0' loop do cursor, r = @redis.scan(cursor, match: mask) - cursor = cursor.to_i r.each do |key| token = owner_key_to_token(owner, key) y << token end - break if cursor == 0 + break if cursor == '0' end end + end + + def serializer + @serializer ||= @serializer_class.new + end + + # Some serializers can't store symbols out of the box + def hash_get(hash, sym) + hash.key?(sym) ? hash[sym] : hash[sym.to_s] end end