Kouhei Sutou
null+****@clear*****
Tue Mar 7 15:13:55 JST 2017
Kouhei Sutou 2017-03-07 15:13:55 +0900 (Tue, 07 Mar 2017) New Revision: 48c6ebce0ee3efdefdd10daafd8b25d8b2178927 https://github.com/ranguba/groonga-client-model/commit/48c6ebce0ee3efdefdd10daafd8b25d8b2178927 Message: Support groonga:migrate:redo and groonga:migrate:rollback Added files: test/unit/fixtures/migrate/20170301061420_create_posts.rb test/unit/fixtures/migrate/20170303115054_create_terms.rb test/unit/fixtures/migrate/20170303115135_create_ages.rb test/unit/test_migrator.rb Modified files: lib/groonga_client_model/migrator.rb lib/groonga_client_model/railties/groonga.rake Modified: lib/groonga_client_model/migrator.rb (+62 -20) =================================================================== --- lib/groonga_client_model/migrator.rb 2017-03-07 14:35:25 +0900 (081ec5e) +++ lib/groonga_client_model/migrator.rb 2017-03-07 15:13:55 +0900 (f2d0216) @@ -30,26 +30,50 @@ module GroongaClientModel attr_accessor :output - def initialize(search_paths, target_version) + def initialize(search_paths) @output = nil @search_paths = Array(search_paths) - @target_version = target_version ensure_versions - @current_version =****@versi***** || 0 + ensure_loaded_versions + @current_version = @loaded_versions.last + @target_version = nil + end + + def target_version=(version) + @target_version = version + end + + def step=(step) + if @current_version.nil? + index = step - 1 + else + index =****@versi*****(@current_version) + index += step if index + end + if index.nil? or index < 0 + version = 0 + else + version = @versions[index] + end + self.target_version = version end def migrate + is_forward = forward? each do |definition| Client.open do |client| migration = definition.create_migration(client) migration.output = @output report(definition) do - if forward? + if is_forward migration.up add_version(client, definition.version) + @current_version = definition.version else migration.down delete_version(client, definition.version) + previous_version_index =****@versi*****(definition.version) - 1 + @current_version = @versions[previous_version_index] || 0 end end end @@ -57,26 +81,20 @@ module GroongaClientModel end def each - paths = [] - @search_paths.each do |search_path| - paths |= Dir.glob("#{search_path}/**/[0-9]*_*.rb").collect do |path| - File.expand_path(path) - end - end - definitions = [] - paths.each do |path| - definition = Definition.new(path) - definitions << definition if definition.valid? - end - sorted_definitions = definitions.sort_by(&:version) + return to_enum(:each) unless block_given? + current_version = @current_version || 0 if forward? sorted_definitions.each do |definition| - yield(definition) if definition.version > @current_version + next if definition.version <= current_version + next if @target_version and definition.version > @target_version + yield(definition) end else sorted_definitions.reverse_each do |definition| - yield(definition) if definition.version <= @current_version + next if definition.version > current_version + next if @target_version and definition.version <= @target_version + yield(definition) end end end @@ -94,12 +112,35 @@ module GroongaClientModel "schema_versions" end + def collect_definitions + paths = [] + @search_paths.each do |search_path| + paths |= Dir.glob("#{search_path}/**/[0-9]*_*.rb").collect do |path| + File.expand_path(path) + end + end + definitions = [] + paths.each do |path| + definition = Definition.new(path) + definitions << definition if definition.valid? + end + definitions + end + + def sorted_definitions + @sorted_definitions ||= collect_definitions.sort_by(&:version) + end + def ensure_versions + @versions = sorted_definitions.collect(&:version) + end + + def ensure_loaded_versions Client.open do |client| table_name = version_table_name exist = client.object_exist(name: table_name).body if exist - @versions = client.request(:select). + @loaded_versions = client.request(:select). parameter(:table, table_name). sort_keys([:_key]). limit(-1). @@ -113,13 +154,14 @@ module GroongaClientModel flags_parameter(:flags, ["TABLE_PAT_KEY"]). parameter(:key_type, "UInt64"). response - @versions = [] + @loaded_versions = [] end end end def forward? @target_version.nil? or + @current_version.nil? or (@target_version > @current_version) end Modified: lib/groonga_client_model/railties/groonga.rake (+46 -6) =================================================================== --- lib/groonga_client_model/railties/groonga.rake 2017-03-07 14:35:25 +0900 (135ba8f) +++ lib/groonga_client_model/railties/groonga.rake 2017-03-07 15:13:55 +0900 (5cab18c) @@ -35,14 +35,54 @@ namespace :groonga do end end + namespace :migrate do + task setup: ["config:load"] do + Rails.application.paths["db/groonga/migrate"] ||= + GroongaClientModel::Migrator.default_search_path + end + + desc "Rollbacks the Groonga database one version and re-migrates" + task redo: ["setup"] do + migration_paths = Rails.application.paths["db/groonga/migrate"].to_a + migrator = GroongaClientModel::Migrator.new(migration_paths) + if ENV["VERSION"] + current_version = migrator.current_version + migrator.target_version = Integer(ENV["VERSION"]) + migrator.migrate + migrator.target_version = current_version + migrator.migrate + else + if ENV["STEP"] + step = Integer(ENV["STEP"]) + else + step = 1 + end + migrator.step = -step + migrator.migrate + migrator.step = step + migrator.migrate + end + end + + desc "Rolls the Groonga database back to the previous version" + task rollback: ["setup"] do + migration_paths = Rails.application.paths["db/groonga/migrate"].to_a + migrator = GroongaClientModel::Migrator.new(migration_paths) + if ENV["STEP"] + step = Integer(ENV["STEP"]) + else + step = 1 + end + migrator.step = -step + migrator.migrate + end + end + desc "Migrates the Groonga database" - task migrate: ["config:load"] do - Rails.application.paths["db/groonga/migrate"] ||= - GroongaClientModel::Migrator.default_search_path + task migrate: ["migrate:setup"] do migration_paths = Rails.application.paths["db/groonga/migrate"].to_a - version = nil - version = Integer(ENV["VERSION"]) if ENV["VERSION"] - migrator = GroongaClientModel::Migrator.new(migration_paths, version) + migrator = GroongaClientModel::Migrator.new(migration_paths) + migrator.target_version = Integer(ENV["VERSION"]) if ENV["VERSION"] migrator.migrate end end Added: test/unit/fixtures/migrate/20170301061420_create_posts.rb (+8 -0) 100644 =================================================================== --- /dev/null +++ test/unit/fixtures/migrate/20170301061420_create_posts.rb 2017-03-07 15:13:55 +0900 (5373899) @@ -0,0 +1,8 @@ +class CreatePosts < GroongaClientModel::Migration + def change + create_table :posts do |t| + t.short_text :title + t.text :body + end + end +end Added: test/unit/fixtures/migrate/20170303115054_create_terms.rb (+7 -0) 100644 =================================================================== --- /dev/null +++ test/unit/fixtures/migrate/20170303115054_create_terms.rb 2017-03-07 15:13:55 +0900 (8027534) @@ -0,0 +1,7 @@ +class CreateTerms < GroongaClientModel::Migration + def change + create_table :terms, propose: :full_text_search do |t| + t.index :posts, :body + end + end +end Added: test/unit/fixtures/migrate/20170303115135_create_ages.rb (+6 -0) 100644 =================================================================== --- /dev/null +++ test/unit/fixtures/migrate/20170303115135_create_ages.rb 2017-03-07 15:13:55 +0900 (22b513c) @@ -0,0 +1,6 @@ +class CreateAges < GroongaClientModel::Migration + def change + create_table :ages, type: :hash_table, key_type: :uint32 do |t| + end + end +end Added: test/unit/test_migrator.rb (+125 -0) 100644 =================================================================== --- /dev/null +++ test/unit/test_migrator.rb 2017-03-07 15:13:55 +0900 (12e566b) @@ -0,0 +1,125 @@ +# Copyright (C) 2017 Kouhei Sutou <kou �� clear-code.com> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +class TestMigrator < Test::Unit::TestCase + include GroongaClientModel::TestHelper + + def create_migrator + path = File.expand_path("fixtures/migrate", __dir__) + migrator = GroongaClientModel::Migrator.new(path) + migrator.output = StringIO.new + migrator + end + + sub_test_case("#target_version=") do + sub_test_case("exist") do + test("forward") do + migrator = create_migrator + migrator.target_version = 20170303115054 + assert_equal([ + 20170301061420, + 20170303115054, + ], + migrator.each.collect(&:version)) + end + + test("backward") do + create_migrator.migrate + + migrator = create_migrator + migrator.target_version = 20170303115054 + assert_equal([ + 20170303115135, + ], + migrator.each.collect(&:version)) + end + end + + sub_test_case("not exist") do + test("forward") do + migrator = create_migrator + migrator.target_version = 9999_99_99_999999 + assert_equal([ + 20170301061420, + 20170303115054, + 20170303115135, + ], + migrator.each.collect(&:version)) + end + + test("backward") do + create_migrator.migrate + + migrator = create_migrator + migrator.target_version = -1 + assert_equal([ + 20170303115135, + 20170303115054, + 20170301061420, + ], + migrator.each.collect(&:version)) + end + end + end + + sub_test_case("#step=") do + test("positive") do + migrator = create_migrator + migrator.step = 2 + assert_equal([ + 20170301061420, + 20170303115054, + ], + migrator.each.collect(&:version)) + end + + test("too large") do + migrator = create_migrator + migrator.step = 4 + assert_equal([ + 20170301061420, + 20170303115054, + 20170303115135, + ], + migrator.each.collect(&:version)) + end + + test("negative") do + create_migrator.migrate + + migrator = create_migrator + migrator.step = -2 + assert_equal([ + 20170303115135, + 20170303115054, + ], + migrator.each.collect(&:version)) + end + + test("too small") do + create_migrator.migrate + + migrator = create_migrator + migrator.step = -4 + assert_equal([ + 20170303115135, + 20170303115054, + 20170301061420, + ], + migrator.each.collect(&:version)) + end + end +end -------------- next part -------------- HTML����������������������������...Download