use versionable model ids in partition precreator

closes #CORE-3256

Change-Id: I88a21eb9c0b404ba843149d20cdd3e13b48bc313
Reviewed-on: https://gerrit.instructure.com/204647
Tested-by: Jenkins
Reviewed-by: Rob Orton <rob@instructure.com>
QA-Review: Rob Orton <rob@instructure.com>
Product-Review: Rob Orton <rob@instructure.com>
This commit is contained in:
James Williams 2019-08-12 09:00:59 -06:00
parent a81c12bb17
commit d641ac44e2
3 changed files with 51 additions and 9 deletions

View File

@ -59,11 +59,6 @@ SQL
def ensure_or_check_partitions(advance, create_partitions)
empties = 0
partitions = partition_tables
partitions.reverse_each do |partition|
break if empties >= advance
break if base_class.from(base_class.connection.quote_table_name(partition)).exists?
empties += 1
end
if partitions.empty?
current = -1
@ -71,6 +66,19 @@ SQL
current = partitions.last[base_class.table_name.length + 1..-1].to_i
end
if self.partition_on_primary_key?
partitions.reverse_each do |partition|
break if empties >= advance
break if base_class.from(base_class.connection.quote_table_name(partition)).exists?
empties += 1
end
else
id = self.maximum_foreign_id
last_needed = id ? (id / base_class.partition_size) : -1
# yes `empties` could be negative but that just means we'll make even more partitions to catch up
empties = current - last_needed
end
while empties < advance
current += 1
if create_partitions
@ -89,6 +97,27 @@ SQL
protected
def partition_on_primary_key?
base_class.partitioning_field.to_s == base_class.primary_key.to_s
end
def maximum_foreign_id
reflection = base_class.reflections.detect { |_, r| r.belongs_to? && base_class.partitioning_field.to_s }.last
klasses =
if reflection.polymorphic?
reflection.options[:polymorphic].map do |type|
if type.is_a?(Hash)
type.values.map{|v| v.constantize rescue nil}
else
type.to_s.classify.constantize rescue nil
end
end.flatten.compact
else
[reflection.klass]
end
klasses.map{|klass| klass.maximum(klass.primary_key)}.compact.max
end
def table_regex
@table_regex ||= /^#{Regexp.escape(base_class.table_name)}_(?<index>\d+)$/.freeze
end

View File

@ -161,6 +161,7 @@ describe CanvasPartman::PartitionManager do
describe "#ensure_partitions" do
it "creates the proper number of partitions" do
expect(subject).to receive(:partition_tables).and_return([])
expect(Zoo).to receive(:maximum).and_return(nil)
expect(subject).to receive(:create_partition).with(0)
expect(subject).to receive(:create_partition).with(5)
@ -169,11 +170,23 @@ describe CanvasPartman::PartitionManager do
it "detects when enough partitions already exist" do
expect(subject).to receive(:partition_tables).and_return(['partman_trails_0', 'partman_trails_1'])
expect(subject.base_class).to receive(:from).twice.and_return(Trail.none)
expect(Zoo).to receive(:maximum).and_return(nil)
expect(subject).to receive(:create_partition).never
subject.ensure_partitions(2)
end
it "detects how many partitions are needed based on the foreign key table" do
expect(subject).to receive(:partition_tables).and_return([])
expect(Zoo).to receive(:maximum).and_return(7)
expect(subject).to receive(:create_partition).with(0)
expect(subject).to receive(:create_partition).with(5) # catches up
expect(subject).to receive(:create_partition).with(10)
expect(subject).to receive(:create_partition).with(15) # and adds two more
subject.ensure_partitions(2)
end
end
end
end

View File

@ -63,9 +63,9 @@ describe InfoController do
# stick a Version into last partition
last_partition = CanvasPartman::PartitionManager.create(Version).partition_tables.last
v_id = (last_partition.sub("versions_", "").to_i * Version.partition_size) + 1
Version.suspend_callbacks(:initialize_number) do
Version.create!(:versionable_id => v_id, :versionable_type => "Assignment")
end
# don't have to make a real version anymore, just an object that _could_ make a version
Course.create.wiki_pages.create!(:id => v_id, :title => "t")
Timecop.freeze(4.years.from_now) do # and jump forward a ways
get "health_prognosis"