Skip to content

Commit

Permalink
refactor(all): extract Cluster and Partition classes
Browse files Browse the repository at this point in the history
  • Loading branch information
Napolskih committed Nov 15, 2013
1 parent 020cc8e commit 2d1c733
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 75 deletions.
59 changes: 59 additions & 0 deletions lib/redis_counters/bucket.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# coding: utf-8
module RedisCounters

class Bucket

def self.default_options
{:only_leaf => false}
end

def initialize(counter, bucket_params)
@counter = counter
@bucket_params = bucket_params.with_indifferent_access

if bucket_keys.present? && bucket_params.blank? && required?
raise ArgumentError, "You must specify a #{self.class.name}"
end
end

attr_reader :counter
attr_reader :bucket_params

# Protected: Возвращает букет в виде массива параметров, однозначно его идентифицирующих.
#
# cluster - Hash - хеш параметров, определяющий букет.
# options - Hash - хеш опций:
# :only_leaf - Boolean - выбирать только листовые букеты (по умолачнию - true).
# Если флаг установлен в true и передана не листовой букет, то
# будет сгенерировано исключение KeyError.
#
# Метод генерирует исключение ArgumentError, если переданы параметры не верно идентифицирующие букет.
# Например: ключи группировки счетчика {:param1, :param2, :param3}, а переданы {:param1, :param3}.
# Метод генерирует исключение ArgumentError, 'You must specify a cluster',
# если букет передан в виде пустого хеша, но группировка используется в счетчике.
#
# Returns Array.
#
def params(options = {})
options.reverse_merge!(self.class.default_options)

bucket_keys.inject(Array.new) do |result, key|
param = (options[:only_leaf] ? bucket_params.fetch(key) : bucket_params[key])
next result unless bucket_params.has_key?(key)
next result << param if result.size >= bucket_keys.index(key)

raise ArgumentError, 'An incorrectly specified %s %s' % [self.class.name, bucket_params]
end
end

protected

def bucket_keys
raise NotImplementedError.new 'You must specify the grouping key'
end

def required?
false
end
end
end
22 changes: 22 additions & 0 deletions lib/redis_counters/cluster.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# coding: utf-8

require 'redis_counters/bucket'

module RedisCounters

class Cluster < Bucket
def self.default_options
{:only_leaf => true}
end

protected

def bucket_keys
counter.send(:cluster_keys)
end

def required?
true
end
end
end
78 changes: 8 additions & 70 deletions lib/redis_counters/clusterize_and_partitionize.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ def partitions(params = {})
#
def data(params = {})
total_rows = 0
cluster = prepared_cluster(params)
parts = partitions(params).map { |partition| prepared_part(partition) }
cluster = ::RedisCounters::Cluster.new(self, params).params
parts = partitions(params).map { |partition| ::RedisCounters::Partition.new(self, partition).params }

result = parts.flat_map do |partition|
rows = partition_data(cluster, partition)
Expand Down Expand Up @@ -85,8 +85,8 @@ def delete_partitions!(params = {})
# Returns Nothing.
#
def delete_partition_direct!(params = {}, write_session = redis)
cluster = prepared_cluster(params)
partition = prepared_part(params, :only_leaf => true)
cluster = ::RedisCounters::Cluster.new(self, params).params
partition = ::RedisCounters::Partition.new(self, params).params(:only_leaf => true)
key = key(partition, cluster)
write_session.del(key)
end
Expand Down Expand Up @@ -119,81 +119,19 @@ def use_partitions?
partition_keys.present?
end

# Protected: Возвращает кластер в виде массива параметров, однозначно его идентифицирующих.
#
# cluster - Hash - хеш параметров, определяющий кластер.
# options - Hash - хеш опций:
# :only_leaf - Boolean - выбирать только листовые кластеры (по умолачнию - true).
# Если флаг установлен в true и передана не листовой кластер, то
# будет сгенерировано исключение KeyError.
#
# Метод генерирует исключение ArgumentError, если переданы параметры не верно идентифицирующие кластер.
# Например: ключи кластеризации счетчика {:param1, :param2, :param3}, а переданы {:param1, :param3}.
# Метод генерирует исключение ArgumentError, 'You must specify a cluster',
# если кластер передан в виде пустого хеша, но кластеризация используется в счетчике.
#
# Returns Array.
#
def prepared_cluster(cluster, options = {})
if cluster_keys.present? && cluster.blank?
raise ArgumentError, 'You must specify a cluster'
end

default_options = {:only_leaf => true}
options.reverse_merge!(default_options)

cluster = cluster.with_indifferent_access
cluster_keys.inject(Array.new) do |result, key|
param = (options[:only_leaf] ? cluster.fetch(key) : cluster[key])
next result unless cluster.has_key?(key)
next result << param if result.size >= cluster_keys.index(key)

raise ArgumentError, 'An incorrectly specified cluster %s' % [cluster]
end
end


# Protected: Возвращает массив партиций, где каждая партиция,
# представляет собой массив параметров, однозначно её идентифицирующих.
#
# part - Hash - хеш параметров, определяющий партицию.
# options - Hash - хеш опций:
# :only_leaf - Boolean - выбирать только листовые партиции (по умолачнию - false).
# Если флаг установлен в true и передана не листовая партиция, то
# будет сгенерировано исключение KeyError.
#
# Метод генерирует исключение ArgumentError, если переданы параметры не верно идентифицирующие партицию.
# Например: ключи партиционирования счетчика {:param1, :param2, :param3}, а переданы {:param1, :param3}.
#
# Returns Array of Array.
#
def prepared_part(parts, options = {})
default_options = {:only_leaf => false}
options.reverse_merge!(default_options)

partition = parts.with_indifferent_access
partition_keys.inject(Array.new) do |result, key|
param = (options[:only_leaf] ? partition.fetch(key) : partition[key])
next result unless partition.has_key?(key)
next result << param if result.size >= partition_keys.index(key)

raise ArgumentError, 'An incorrectly specified partition %s' % [partition]
end
end

# Protected: Возвращает массив листовых партиций в виде ключей.
#
# params - Hash - параметров, определяющий кластер и партицию.
# params - Hash - хеш параметров, определяющий кластер и партицию.
#
# Если кластер не указан и нет кластеризации в счетчике, то возвращает все партиции.
# Партиция может быть не задана, тогда будут возвращены все партиции кластера (все партиции, если нет кластеризации).
# Может быть задана не листовая партиция, тогда будут все её листовые подпартции.
#
# Returns Array of Hash.
#
def partitions_raw(params = {})
cluster = prepared_cluster(params)
partition = prepared_part(params)
def partitions_keys(params = {})
cluster = ::RedisCounters::Cluster.new(self, params).params
partition = ::RedisCounters::Partition.new(self, params).params

strict_pattern = key(partition, cluster) if (cluster.present? && partition_keys.blank?) || partition.present?
fuzzy_pattern = key(partition << '*', cluster)
Expand Down
16 changes: 16 additions & 0 deletions lib/redis_counters/partition.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# coding: utf-8

require 'redis_counters/bucket'

module RedisCounters

class Partition < Bucket
def self.default_options
{:only_leaf => false}
end

def bucket_keys
counter.send(:partition_keys)
end
end
end
2 changes: 1 addition & 1 deletion lib/redis_counters/unique_values_lists/fast.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Fast < UniqueValuesLists::Base
# Returns Nothing.
#
def delete_main_partition!(cluster, write_session = redis)
cluster = prepared_cluster(cluster)
cluster = ::RedisCounters::Cluster.new(self, cluster).params
key = key([], cluster)
write_session.del(key)
end
Expand Down
10 changes: 6 additions & 4 deletions lib/redis_counters/unique_values_lists/standard.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ def delete_partition_direct!(params = {}, write_session = redis)

# удаляем партицию из списка
return unless use_partitions?
cluster = prepared_cluster(params)
partition = prepared_part(params, :only_leaf => true)

cluster = ::RedisCounters::Cluster.new(self, params).params
partition = ::RedisCounters::Partition.new(self, params).params(:only_leaf => true)

partition = partition.flatten.join(key_delimiter)
write_session.lrem(partitions_list_key(cluster), 0, partition)
end
Expand Down Expand Up @@ -136,8 +138,8 @@ def new_partition?
def partitions_keys(params = {})
reset_partitions_cache

cluster = prepared_cluster(params)
partition = prepared_part(params)
cluster = ::RedisCounters::Cluster.new(self, params).params
partition = ::RedisCounters::Partition.new(self, params).params

partitions_keys = all_partitions(cluster).map { |part| key(part, cluster) }

Expand Down

0 comments on commit 2d1c733

Please sign in to comment.