lib/rollout.rb in rollout-2.4.5 vs lib/rollout.rb in rollout-2.4.6

- old
+ new

@@ -1,142 +1,16 @@ # frozen_string_literal: true +require 'rollout/feature' require 'rollout/version' require 'zlib' require 'set' require 'json' class Rollout RAND_BASE = (2**32 - 1) / 100.0 - class Feature - attr_accessor :groups, :users, :percentage, :data - attr_reader :name, :options - - def initialize(name, string = nil, opts = {}) - @options = opts - @name = name - - if string - raw_percentage, raw_users, raw_groups, raw_data = string.split('|', 4) - @percentage = raw_percentage.to_f - @users = users_from_string(raw_users) - @groups = groups_from_string(raw_groups) - @data = raw_data.nil? || raw_data.strip.empty? ? {} : JSON.parse(raw_data) - else - clear - end - end - - def serialize - "#{@percentage}|#{@users.to_a.join(',')}|#{@groups.to_a.join(',')}|#{serialize_data}" - end - - def add_user(user) - id = user_id(user) - @users << id unless @users.include?(id) - end - - def remove_user(user) - @users.delete(user_id(user)) - end - - def add_group(group) - @groups << group.to_sym unless @groups.include?(group.to_sym) - end - - def remove_group(group) - @groups.delete(group.to_sym) - end - - def clear - @groups = groups_from_string('') - @users = users_from_string('') - @percentage = 0 - @data = {} - end - - def active?(rollout, user) - if user - id = user_id(user) - user_in_percentage?(id) || - user_in_active_users?(id) || - user_in_active_group?(user, rollout) - else - @percentage == 100 - end - end - - def user_in_active_users?(user) - @users.include?(user_id(user)) - end - - def to_hash - { - percentage: @percentage, - groups: @groups, - users: @users - } - end - - private - - def user_id(user) - if user.is_a?(Integer) || user.is_a?(String) - user.to_s - else - user.send(id_user_by).to_s - end - end - - def id_user_by - @options[:id_user_by] || :id - end - - def user_in_percentage?(user) - Zlib.crc32(user_id_for_percentage(user)) < RAND_BASE * @percentage - end - - def user_id_for_percentage(user) - if @options[:randomize_percentage] - user_id(user).to_s + @name.to_s - else - user_id(user) - end - end - - def user_in_active_group?(user, rollout) - @groups.any? do |g| - rollout.active_in_group?(g, user) - end - end - - def serialize_data - return '' unless @data.is_a? Hash - - @data.to_json - end - - def users_from_string(raw_users) - users = (raw_users || '').split(',').map(&:to_s) - if @options[:use_sets] - users.to_set - else - users - end - end - - def groups_from_string(raw_groups) - groups = (raw_groups || '').split(',').map(&:to_sym) - if @options[:use_sets] - groups.to_set - else - groups - end - end - end - def initialize(storage, opts = {}) @storage = storage @options = opts @groups = { all: ->(_user) { true } } end @@ -294,10 +168,16 @@ @storage.del(features_key) end def exists?(feature) - @storage.exists(key(feature)) + # since redis-rb v4.2, `#exists?` replaces `#exists` which now returns integer value instead of boolean + # https://github.com/redis/redis-rb/pull/918 + if @storage.respond_to?(:exists?) + @storage.exists?(key(feature)) + else + @storage.exists(key(feature)) + end end private def key(name)