themigrator 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e7b0bd4c2f45a3da0af9c48c3b6cba896b0fab28
4
- data.tar.gz: 9590ad4e9ac568a4aeb884c6eeca181cac4df735
3
+ metadata.gz: 085e22641bbbe62e08c1e198162675d47b6db9c5
4
+ data.tar.gz: 538f05195800115aa28338cc4896378bc57df811
5
5
  SHA512:
6
- metadata.gz: 7b04dc8e517f01daf72e181782ddafd2b2d944db7dbdc5db269bbb445c8f2db7775eb328f93c5dd070e806ab2ec9d364a36e74d6bbf87f4f653f217f33a39f92
7
- data.tar.gz: 69a04b5e51d35ce5329569bc68568ae83e61e77b0f0434769a72458f355ec27297247678f52603c2a409c23b12fd424fe7ff044e19addecc14dbaa6d76709a98
6
+ metadata.gz: ee81f2adb4f68ccb702a32931fbabb4a6030edc2732bc87e1b6ad12d54c803ee4a8f34c6e8a620d6db08fb53ade3618a67d8d7fb2080550f2fc3965518e2d0ad
7
+ data.tar.gz: 1e0483923ba73473f685f91cda9a9f132fbb2df7bf67a958ede16f825d5082ee8f3cab1725d1f9a5636236477fc09fcec1898f998c15c95ad58af0aaa0a34dd5
@@ -1,9 +1,33 @@
1
1
  require 'fileutils'
2
+ require 'logger'
2
3
 
3
4
  module Themigrator
4
5
  module Logger
6
+
7
+ MAINLOGFILE = "themigrator.log"
5
8
  include FileUtils
6
9
 
10
+ def log(msg)
11
+ logger.info msg
12
+ end
13
+
14
+ def init_logger(log_file)
15
+ @logger = ::Logger.new(log_file)
16
+ @logger.formatter = proc do |severity, datetime, progname, msg|
17
+ t = datetime.strftime('%Y-%m-%d %H:%M:%S')
18
+ "#{t}: #{msg}\n"
19
+ end
20
+ end
21
+
22
+ def logger
23
+ @logger || ::Logger.new(STDOUT)
24
+ end
25
+
26
+ def main_log_path(base_dir, run_id)
27
+ filename = MAINLOGFILE
28
+ directory = log_dir(base_dir, run_id)
29
+ File.join(directory,filename)
30
+ end
7
31
 
8
32
  def log_path(base_dir, run_id, role, action)
9
33
  filename = "#{role}-#{action}.log"
@@ -0,0 +1,30 @@
1
+
2
+
3
+ module Themigrator
4
+ class MigrationProgress
5
+ include Logger
6
+
7
+
8
+ def initialize(dir, run_id)
9
+ @dir, @run_id = dir, run_id
10
+ @log_file_path = main_log_path(dir, run_id)
11
+ start_log_parser
12
+ end
13
+
14
+ private
15
+
16
+ def start_log_parser
17
+
18
+ File.open(@log_file_path, "r") do |f|
19
+ f.readline
20
+ raise File.read(@log_file_path)
21
+
22
+
23
+ end
24
+
25
+ rescue EOFError
26
+
27
+ end
28
+
29
+ end
30
+ end
@@ -1,11 +1,10 @@
1
- require 'themigrator/runner'
2
1
  require 'themigrator/logger'
3
2
  require 'themigrator/migration'
3
+ require 'themigrator/script_pool'
4
4
 
5
5
 
6
6
  module Themigrator
7
7
  class Migrator
8
- include Runner
9
8
  include Logger
10
9
 
11
10
 
@@ -17,51 +16,68 @@ module Themigrator
17
16
  def migrate!
18
17
  @migration = Migration.new(@dir)
19
18
  @migration.analyze_project!
19
+
20
+ init_logger(main_log_path(@dir, run_id))
20
21
 
21
- Migration::ACTIONS.each do |action|
22
- run_action_and_wait(action)
22
+ log "* [starting]"
23
+ catch(:rollback) do
24
+ each_action do |action|
25
+ log "[step #{action}]"
26
+ run_action_and_wait(action)
27
+ end
28
+ return true
23
29
  end
24
-
25
- rescue ActionFailedException
26
30
  run_rollback_and_wait
27
31
  end
28
32
 
29
- private
30
-
31
- def run_rollback_and_wait
32
- rollbacks = @migration.roles_for_action("rollback") & @runned_roles
33
- rollbacks .each do |role|
34
- start_role_action(role, "rollback")
35
- end
36
-
37
- wait
38
- end
39
-
40
33
  def run_id
41
34
  @run_id ||= Time.now.strftime("%Y-%m-%d-%H:%M:%S")
42
35
  end
43
36
 
44
- def run_action_and_wait(action)
45
- run_action(action)
46
- wait
37
+ private
38
+
39
+ def each_action
40
+ Migration::ACTIONS.each do |action|
41
+ yield action
42
+ end
47
43
  end
48
44
 
49
- def run_action(action)
45
+ def each_role(action)
50
46
  @migration.roles_for_action(action).each do |role|
51
47
  @runned_roles << role # To prevent calling rollback on roles that
52
- # have not being executed
53
-
54
- start_role_action(role, action)
55
-
48
+ yield role
56
49
  end
57
50
  @runned_roles.uniq!
58
51
  end
59
52
 
60
- def start_role_action(role, action)
61
- script_path = find_script(role, action)
62
- log_path = log_path(@dir,run_id,role, action)
53
+ def run_rollback_and_wait
54
+ script_pool = ScriptPool.new
55
+ each_role("rollback") do |role|
56
+ next unless @runned_roles.include?(role)
57
+ script_path = find_script(role, action)
58
+ log_path = log_path(@dir,run_id,role, action)
59
+
60
+ log("[running #{action} for #{role}]")
61
+
62
+ script_pool.add_script(script_path,log_path)
63
+ end
64
+ script_pool.run_and_wait
65
+ end
66
+
67
+ def run_action_and_wait(action)
68
+ script_pool = ScriptPool.new
69
+
70
+ each_role(action) do |role|
71
+ script_path = find_script(role, action)
72
+ log_path = log_path(@dir,run_id,role, action)
73
+
74
+ log("[running #{action} for #{role}]")
63
75
 
64
- run(script_path,log_path)
76
+ script_pool.add_script(script_path,log_path)
77
+ end
78
+
79
+ script_pool.run_and_wait or throw :rollback
80
+
65
81
  end
66
82
 
67
83
  def find_script(role, action)
@@ -0,0 +1,78 @@
1
+
2
+
3
+ module Themigrator
4
+ class Script
5
+ def initialize(script, log_file)
6
+ @script = script
7
+ @log_file = File.open(log_file, "w", 0600)
8
+ @wd_dir = File.dirname(script)
9
+ @pid = nil
10
+ @thread = nil
11
+ end
12
+
13
+ def run
14
+ @thread = Thread.new do
15
+ @pid = Process.spawn(@script,
16
+ err: @log_file,
17
+ out: @log_file,
18
+ chdir: @wd_dir)
19
+ pid, status = Process.wait2(@pid)
20
+ if status.signaled?
21
+ signal = Signal.list.find{|k,v|
22
+ v == status.termsig
23
+ }
24
+ signal.nil? ? :unknown_signal : signal[0].downcase.to_sym
25
+ else
26
+ status.exitstatus
27
+ end
28
+ end
29
+ sleep 0
30
+ end
31
+
32
+ # Waits for the process to be over
33
+ def wait(seconds = nil)
34
+ @thread.join(seconds)
35
+ end
36
+
37
+ def exitcode
38
+ @thread.value
39
+ end
40
+
41
+ def stop
42
+ if running?
43
+ send_int
44
+ if wait(5) == nil
45
+ send_kill
46
+ end
47
+ wait
48
+ end
49
+ end
50
+
51
+ def success?
52
+ exitcode == 0
53
+ end
54
+
55
+ private
56
+
57
+ def running?
58
+ @thread and @thread.alive?
59
+ end
60
+
61
+ def send_signal(signal)
62
+ Process.kill(signal.to_s.upcase,@pid)
63
+ end
64
+
65
+ def send_int
66
+ send_signal(:int)
67
+ end
68
+
69
+ def send_kill
70
+ send_signal(:kill)
71
+ end
72
+
73
+ def close
74
+ @log_file.close
75
+ end
76
+
77
+ end
78
+ end
@@ -0,0 +1,64 @@
1
+ require 'themigrator/script'
2
+
3
+
4
+ module Themigrator
5
+ class ScriptPool
6
+ def initialize
7
+ @queue = Queue.new
8
+ @lock = Mutex.new
9
+ @scripts = []
10
+ end
11
+
12
+ def add_script(script,log_file)
13
+ s = Script.new(script, log_file)
14
+ @lock.synchronize do
15
+ @scripts << s
16
+ end
17
+ s
18
+ end
19
+
20
+ # Run the scripts
21
+ # returns:
22
+ # * true: All scripts returned 0
23
+ # * false: Some of the scripts fail
24
+ def run_and_wait
25
+ @lock.synchronize do
26
+ start_scripts
27
+ collect_result
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def start_scripts
34
+ @scripts.each do |s|
35
+ Thread.new {
36
+ s.run
37
+ s.wait
38
+ @queue << s
39
+ }
40
+ end
41
+ end
42
+
43
+ def collect_result
44
+ running_scripts = @scripts.size
45
+ success = true
46
+ while running_scripts != 0
47
+ s = @queue.pop
48
+ if !s.success?
49
+ stop_and_kill
50
+ success = false
51
+ end
52
+ running_scripts -= 1
53
+ end
54
+ success
55
+ end
56
+
57
+ def stop_and_kill
58
+ @scripts.each {|s|
59
+ s.stop
60
+ }
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,12 @@
1
+ require 'curses'
2
+
3
+ module Themigrator
4
+ module UI
5
+
6
+ def render
7
+ puts "hello"
8
+
9
+ end
10
+
11
+ end
12
+ end
@@ -1,3 +1,3 @@
1
1
  module Themigrator
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
data/lib/themigrator.rb CHANGED
@@ -1,7 +1,10 @@
1
1
  require "themigrator/version"
2
2
  require "themigrator/logger"
3
- require "themigrator/runner"
4
3
  require "themigrator/migration"
4
+ require "themigrator/migrator"
5
+ require "themigrator/script_pool"
6
+ require "themigrator/script"
7
+ require "themigrator/migration_progress"
5
8
 
6
9
  module Themigrator
7
10
 
data/themigrator.gemspec CHANGED
@@ -23,4 +23,5 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency "minitest", "~> 5.0"
24
24
 
25
25
  spec.add_dependency "thor", "~> 0.19"
26
+ spec.add_dependency "curses", "~> 1.0"
26
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: themigrator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Guillermo Álvarez
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-08-23 00:00:00.000000000 Z
11
+ date: 2016-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0.19'
69
+ - !ruby/object:Gem::Dependency
70
+ name: curses
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.0'
69
83
  description: The migrator is a program that eases and automates data migrations.
70
84
  email:
71
85
  - guillermo@cientifico.net
@@ -88,8 +102,11 @@ files:
88
102
  - lib/themigrator/helper.rb
89
103
  - lib/themigrator/logger.rb
90
104
  - lib/themigrator/migration.rb
105
+ - lib/themigrator/migration_progress.rb
91
106
  - lib/themigrator/migrator.rb
92
- - lib/themigrator/runner.rb
107
+ - lib/themigrator/script.rb
108
+ - lib/themigrator/script_pool.rb
109
+ - lib/themigrator/ui.rb
93
110
  - lib/themigrator/version.rb
94
111
  - test.sh
95
112
  - themigrator.gemspec
@@ -1,58 +0,0 @@
1
- require 'themigrator/logger'
2
-
3
-
4
- module Themigrator
5
- module Runner
6
- include Logger
7
-
8
- class ActionFailedException < Exception; end
9
-
10
-
11
- class Script
12
- def initialize(script, log_file)
13
- @script = script
14
- @log_file = File.open(log_file, "w", 0600)
15
- end
16
-
17
- def close
18
- @log_file.close
19
- end
20
- end
21
-
22
-
23
- def run(script, log_file)
24
- wd_dir = File.dirname(script)
25
- log_fd = File.open(log_file, "w", 0600)
26
- pid = Process.spawn(script, err: log_fd, out: log_fd, chdir: wd_dir)
27
- add_pid(pid)
28
- end
29
-
30
- def wait
31
- processes.each do |pid|
32
- pid, status = Process.wait2(pid)
33
- return_code = status.exitstatus
34
- remove_pid(pid)
35
-
36
- if return_code != 0
37
- raise ActionFailedException.new(pid)
38
- end
39
- end
40
- end
41
-
42
- private
43
-
44
- def processes
45
- @processes || []
46
- end
47
-
48
- def add_pid(pid)
49
- @processes ||= []
50
- @processes << pid
51
- end
52
-
53
- def remove_pid(pid)
54
- @processes.delete(pid)
55
- end
56
-
57
- end
58
- end