Module: Flydata::Command::ExclusiveRunnable::ClassMethods

Defined in:
lib/flydata/command/exclusive_runnable.rb

Constant Summary collapse

COMMAND_IS_ALREADY_RUNNING =

messages

<<EOT
Command `%s` is already running or terminated abnormally. (pid:%s)
Wait until the command completes or stop the command.
EOT
DATA_INCONSISTENCY_MAY_OCCUR =
<<EOT

!! Command `%s` is still running. (pid:%s)
We highly recommend to *stop the process* before run a new command.
If two commands run concurrently, DATA INCONSISTENCY MAY OCCUR.

EOT
CONCURRENT_RUN =
<<EOT
Run command:"%s" while a process for the previous command:"%s" still exists (pid:%s)
EOT

Instance Method Summary collapse

Instance Method Details

#command(subcommand, options = {}) ⇒ Object



99
100
101
102
103
104
105
106
# File 'lib/flydata/command/exclusive_runnable.rb', line 99

def command(subcommand, options = {})
  return options[:command] if options[:command]

  modules = self.name.split('::')

  cmd = modules.last.downcase
  subcommand == :run ? cmd : "#{cmd}:#{subcommand}"
end

#command_process_exist?Boolean

Returns:

  • (Boolean)


107
108
109
110
111
112
113
114
# File 'lib/flydata/command/exclusive_runnable.rb', line 107

def command_process_exist?
  exclusive_run_info = load_exclusive_run_info
  if exclusive_run_info
    process_exist?(exclusive_run_info['pid'])
  else
    false
  end
end

#delete_exclusive_run_infoObject



88
89
90
91
# File 'lib/flydata/command/exclusive_runnable.rb', line 88

def delete_exclusive_run_info
  path = exclusive_run_info_path
  File.delete(path) if File.exists?(path)
end

#exclusive_run_homeObject



66
67
68
# File 'lib/flydata/command/exclusive_runnable.rb', line 66

def exclusive_run_home
  @@exclusive_run_home
end

#exclusive_run_home=(value) ⇒ Object



69
70
71
# File 'lib/flydata/command/exclusive_runnable.rb', line 69

def exclusive_run_home=(value)
  @@exclusive_run_home = value
end

#exclusive_run_info_pathObject



72
73
74
# File 'lib/flydata/command/exclusive_runnable.rb', line 72

def exclusive_run_info_path
  File.join(exclusive_run_home, "exclusive_run.info")
end

#load_exclusive_run_infoObject



76
77
78
79
80
81
# File 'lib/flydata/command/exclusive_runnable.rb', line 76

def load_exclusive_run_info
  path = exclusive_run_info_path
  return nil unless File.exists?(path)

  JSON.parse(File.open(path){|f| f.read})
end

#process_exist?(pid) ⇒ Boolean

Returns:

  • (Boolean)


92
93
94
95
96
97
98
# File 'lib/flydata/command/exclusive_runnable.rb', line 92

def process_exist?(pid)
  # Returns true if the process is running.
  Process.getpgid(pid.to_i)
  true
rescue Errno::ESRCH
  false
end

#run_exclusive(method, options = {}) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/flydata/command/exclusive_runnable.rb', line 29

def run_exclusive(method, options = {})
  saved_method = :"__#{method}"
  alias_method saved_method, method

  define_method(method) do |*args|
    result = nil
    exclusive_run_info = nil
    begin
      new_command = self.class.command(method, options)
      new_pid = Process.pid
      old_exclusive_run_info = self.class.load_exclusive_run_info
      if old_exclusive_run_info
        old_command = old_exclusive_run_info['command']
        old_pid = old_exclusive_run_info['pid']

        raise COMMAND_IS_ALREADY_RUNNING % [ old_command, old_pid ] if !opts.force_run?

        #`force-run` option is specified.
        #Override old `exclusive_run.info` file and run a command.
        if self.class.process_exist?(old_pid)
          log_warn_stderr DATA_INCONSISTENCY_MAY_OCCUR % [ old_command, old_pid ]
          exit unless ask_yes_no("Do you proceed?", false)
        end
        $log.info CONCURRENT_RUN % [ new_command, old_command, old_pid ]
        self.class.delete_exclusive_run_info
      end

      #Run a command
      exclusive_run_info = { command: new_command, pid: new_pid }
      self.class.save_exclusive_run_info(exclusive_run_info)
      result = send(saved_method, *args)
    ensure
      self.class.delete_exclusive_run_info if exclusive_run_info
    end
    result
  end
end

#save_exclusive_run_info(info) ⇒ Object



83
84
85
86
# File 'lib/flydata/command/exclusive_runnable.rb', line 83

def save_exclusive_run_info(info)
  path = exclusive_run_info_path
  File.open(path, "w"){|f| f.write(info.to_json)}
end