Skip to content

Commit

Permalink
refactor(all): back delete_all! methods
Browse files Browse the repository at this point in the history
  • Loading branch information
Napolskih committed Nov 20, 2013
1 parent 2d1c733 commit 3897988
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 3 deletions.
37 changes: 36 additions & 1 deletion lib/redis_counters/clusterize_and_partitionize.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,25 @@ def delete_partitions!(params = {})
end
end

# Public: Транзакционно удаляет все данные счетчика в кластере.
# Если кластеризация не используется, то удаляет все данные.
#
# cluster - Hash - хеш параметров, определяющих кластер.
# Опционально, если кластеризация не используется.
#
# Если передан блок, то вызывает блок, после удаления всех данных, в транзакции.
#
# Returns Nothing.
#
def delete_all!(cluster = {})
parts = partitions(cluster)

transaction do
delete_all_direct!(cluster, redis, parts)
yield if block_given?
end
end

# Public: Нетранзакционно удаляет данные конкретной конечной партиции.
#
# params - Hash - хеш параметров, определяющий кластер и листовую партицию.
Expand All @@ -91,6 +110,22 @@ def delete_partition_direct!(params = {}, write_session = redis)
write_session.del(key)
end

# Public: Нетранзакционно удаляет все данные счетчика в кластере.
# Если кластеризация не используется, то удаляет все данные.
#
# cluster - Hash - хеш параметров, определяющих кластер.
# write_session - Redis - соединение с Redis, в рамках которого
# будет производится удаление (опционально).
# По умолчанию - основное соединение счетчика.
#
# Returns Nothing.
#
def delete_all_direct!(cluster, write_session = redis, parts = partitions(cluster))
parts.each do |partition|
delete_partition_direct!(cluster.merge(partition), write_session)
end
end

protected

def key(partition = partition_params, cluster = cluster_params)
Expand Down Expand Up @@ -121,7 +156,7 @@ def use_partitions?

# Protected: Возвращает массив листовых партиций в виде ключей.
#
# params - Hash - хеш параметров, определяющий кластер и партицию.
# params - Hash - хеш параметров, определяющий кластер и партицию.
#
# Если кластер не указан и нет кластеризации в счетчике, то возвращает все партиции.
# Партиция может быть не задана, тогда будут возвращены все партиции кластера (все партиции, если нет кластеризации).
Expand Down
22 changes: 20 additions & 2 deletions lib/redis_counters/unique_values_lists/fast.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,41 @@ module UniqueValuesLists
# Особенности:
# * 2-х кратный расход памяти в случае использования партиций;
# * Не ведет список партиций;
# * Не транзакционен.
# * Не транзакционен;
# * Методы delete_partitions! и delete_partition_direct!, удаляют только дублирующие партиции,
# но не удаляют данные из основной партиции.
# Для удаления основной партиции необходимо вызвать delete_main_partition!
# или воспользоваться методами delete_all! или delete_all_direct!,
# для удаления всех партиций кластера включая основную.

class Fast < UniqueValuesLists::Base

# Public: Нетранзакционно удаляет все данные счетчика в кластере, включая основную партицию.
# Если кластеризация не используется, то удаляет все данные.
#
# cluster - Hash - хеш параметров, определяющих кластер.
# write_session - Redis - соединение с Redis, в рамках которого
# будет производится удаление (опционально).
# По умолчанию - основное соединение счетчика.
#
# Returns Nothing.
#
def delete_all_direct!(cluster, write_session = redis, parts = partitions(cluster))
super(cluster, write_session, parts)
delete_main_partition!(cluster, write_session)
end

# Public: Удаляет основную партицию.
#
# cluster - Hash - хеш параметров, определяющих кластер.
# Опционально, если кластеризация не используется.
# write_session - Redis - соединение с Redis, в рамках которого
# будет производится удаление (опционально).
# По умолчанию - основное соединение счетчика.
#
# Returns Nothing.
#
def delete_main_partition!(cluster, write_session = redis)
def delete_main_partition!(cluster = {}, write_session = redis)
cluster = ::RedisCounters::Cluster.new(self, cluster).params
key = key([], cluster)
write_session.del(key)
Expand Down
8 changes: 8 additions & 0 deletions spec/redis_counters/hash_counter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,14 @@
before { counter.process(partition_2) }
before { counter.process(partition_3) }

context '#delete_all!' do
before { counter.delete_all! }

it { expect(counter.partitions).to eq [] }
it { expect(counter.data).to eq [] }
it { expect(redis.keys).to eq [] }
end

context '#delete_partitions!' do
context 'when no params given' do
before { counter.delete_partitions! }
Expand Down
110 changes: 110 additions & 0 deletions spec/support/unique_values_lists.rb
Original file line number Diff line number Diff line change
Expand Up @@ -526,4 +526,114 @@
end
end
end

context '#delete_all!' do
let(:cluster1_subcluster1) { {:cluster => :cluster1, :subcluster => :subcluster1} }
let(:cluster1_subcluster2) { {:cluster => :cluster1, :subcluster => :subcluster2} }
let(:cluster1_subcluster3) { {:cluster => :cluster1, :subcluster => :subcluster} }
let(:cluster2_subcluster1) { {:cluster => :cluster2, :subcluster => :subcluster1} }

let(:part1_subpart1) { {:part => 'part1', :subpart => 'subpart1'}.with_indifferent_access }
let(:part1_subpart2) { {:part => 'part1', :subpart => 'subpart2'}.with_indifferent_access }
let(:part2_subpart1) { {'part' => 'part2', :subpart => 'subpart1'}.with_indifferent_access }

context 'when cluster and partition keys given' do
let(:options) { {
:counter_name => :test_counter,
:value_keys => [:param0, :param1],
:cluster_keys => [:cluster, :subcluster],
:partition_keys => [:part, :subpart]
} }

# 2 разных знач в одном кластере и партиции
before { values.times { counter.add(:param0 => 1, :param1 => 2, :cluster => :cluster1, :subcluster => :subcluster1, :part => :part1, :subpart => :subpart1) } }
before { values.times { counter.add(:param0 => 1, :param1 => 3, :cluster => :cluster1, :subcluster => :subcluster1, :part => :part1, :subpart => :subpart1) } }
# дубль знач в другой партиции
before { values.times { counter.add(:param0 => 1, :param1 => 2, :cluster => :cluster1, :subcluster => :subcluster1, :part => :part1, :subpart => :subpart3) } }
# дубль знач в другом кластере
before { values.times { counter.add(:param0 => 1, :param1 => 2, :cluster => :cluster1, :subcluster => :subcluster3, :part => :part1, :subpart => :subpart1) } }
# новое значение в новой подпартиции
before { values.times { counter.add(:param0 => 3, :param1 => 4, :cluster => :cluster1, :subcluster => :subcluster1, :part => :part1, :subpart => :subpart2) } }
# новое значение в новой партиции
before { values.times { counter.add(:param0 => 4, :param1 => 5, :cluster => :cluster1, :subcluster => :subcluster1, :part => :part2, :subpart => :subpart1) } }
# новое значение в новом кластере
before { values.times { counter.add(:param0 => 5, :param1 => 6, :cluster => :cluster2, :subcluster => :subcluster1, :part => :part1, :subpart => :subpart1) } }
# новое значение в новом подкластере
before { values.times { counter.add(:param0 => 6, :param1 => 7, :cluster => :cluster1, :subcluster => :subcluster2, :part => :part1, :subpart => :subpart1) } }

context 'when no cluster given' do
it { expect { counter.delete_all! }.to raise_error ArgumentError }
end

context 'when no leaf cluster given' do
it { expect { counter.delete_all!(:cluster => :cluster1) }.to raise_error KeyError }
end

context 'when unknown cluster given' do
before { counter.delete_all!(:cluster => :unknown_cluster, :subcluster => :subcluster) }

it { expect(counter.partitions(cluster1_subcluster1)).to have(3).partitions }
end

context 'when unknown params given' do
it { expect { counter.delete_all!(:cluster1 => :cluster1) }.to raise_error KeyError }
end

context 'when no partition given' do
before { counter.delete_all!(cluster1_subcluster1) }

it { expect(counter.data(cluster1_subcluster1)).to have(0).rows }
it { expect(counter.data(cluster2_subcluster1)).to have(1).rows }
it { expect(counter.data(cluster1_subcluster2)).to have(1).rows }
it { expect(counter.data(cluster2_subcluster1)).to include ({'param0' => '5', 'param1' => '6'}) }
it { expect(counter.data(cluster1_subcluster2)).to include ({'param0' => '6', 'param1' => '7'}) }

it { expect(counter.partitions(cluster1_subcluster1)).to have(0).partitions }
it { expect(counter.partitions(cluster2_subcluster1)).to have(1).partitions }
it { expect(counter.partitions(cluster2_subcluster1)).to have(1).partitions }
end
end

context 'when cluster not given and partition keys given' do
let(:options) { {
:counter_name => :test_counter,
:value_keys => [:param0, :param1],
:partition_keys => [:part, :subpart]
} }

# 2 разных знач в одном кластере и партиции
before { values.times { counter.add(:param0 => 1, :param1 => 2, :cluster => :cluster1, :subcluster => :subcluster1, :part => :part1, :subpart => :subpart1) } }
before { values.times { counter.add(:param0 => 1, :param1 => 3, :cluster => :cluster1, :subcluster => :subcluster1, :part => :part1, :subpart => :subpart1) } }
# дубль знач в другой партиции
before { values.times { counter.add(:param0 => 1, :param1 => 2, :cluster => :cluster1, :subcluster => :subcluster1, :part => :part1, :subpart => :subpart3) } }
# дубль знач в другом кластере
before { values.times { counter.add(:param0 => 1, :param1 => 2, :cluster => :cluster1, :subcluster => :subcluster3, :part => :part1, :subpart => :subpart1) } }
# новое значение в новой подпартиции
before { values.times { counter.add(:param0 => 3, :param1 => 4, :cluster => :cluster1, :subcluster => :subcluster1, :part => :part1, :subpart => :subpart2) } }
# новое значение в новой партиции
before { values.times { counter.add(:param0 => 4, :param1 => 5, :cluster => :cluster1, :subcluster => :subcluster1, :part => :part2, :subpart => :subpart1) } }
# новое значение в новом кластере
before { values.times { counter.add(:param0 => 5, :param1 => 6, :cluster => :cluster2, :subcluster => :subcluster1, :part => :part1, :subpart => :subpart1) } }
# новое значение в новом подкластере
before { values.times { counter.add(:param0 => 6, :param1 => 7, :cluster => :cluster1, :subcluster => :subcluster2, :part => :part1, :subpart => :subpart1) } }

context 'when no cluster given' do
before { counter.delete_all! }

it { expect(counter.partitions).to have(0).partitions }
end

context 'when unknown cluster given' do
before { counter.delete_all!(:cluster => :unknown_cluster, :subcluster => :subcluster) }

it { expect(counter.partitions).to have(0).partitions }
end

context 'when unknown params given' do
before { counter.delete_all!(:cluster1 => :cluster1) }

it { expect(counter.partitions).to have(0).partitions }
end
end
end
end

0 comments on commit 3897988

Please sign in to comment.