[Groonga-commit] ranguba/groonga-client-model at 48c6ebc [master] Support groonga:migrate:redo and groonga:migrate:rollback

Back to archive index

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 



More information about the Groonga-commit mailing list
Back to archive index