tasks_scheduler 0.2.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +3 -1
  3. data/app/assets/stylesheets/tasks_scheduler.scss +4 -0
  4. data/app/controllers/scheduled_tasks_controller.rb +5 -4
  5. data/app/controllers/tasks_scheduler_daemon_controller.rb +8 -23
  6. data/app/controllers/tasks_scheduler_daemon_controller/_download_log.rb +42 -0
  7. data/app/helpers/scheduled_tasks_helper.rb +2 -0
  8. data/app/models/scheduled_task.rb +30 -15
  9. data/app/models/scheduled_task/checker.rb +20 -6
  10. data/app/models/scheduled_task/log.rb +8 -2
  11. data/app/models/scheduled_task/runner.rb +9 -5
  12. data/app/models/scheduled_task/status.rb +8 -4
  13. data/app/views/scheduled_tasks/status_content.html.erb +1 -0
  14. data/app/views/tasks_scheduler_daemon/_daemon.html.erb +11 -0
  15. data/app/views/tasks_scheduler_daemon/_logs.html.erb +12 -0
  16. data/app/views/tasks_scheduler_daemon/_results.html.erb +9 -0
  17. data/app/views/tasks_scheduler_daemon/_running_status.html.erb +0 -1
  18. data/app/views/tasks_scheduler_daemon/index.html.erb +3 -20
  19. data/config/initializers/assets.rb +3 -1
  20. data/config/routes.rb +4 -2
  21. data/db/migrate/20161122123828_create_scheduled_tasks.rb +5 -1
  22. data/db/migrate/20161123130153_add_status_attributes_to_scheduled_tasks.rb +5 -1
  23. data/db/migrate/20161124200712_add_pid_to_scheduled_tasks.rb +5 -1
  24. data/db/migrate/20161128163702_add_args_to_scheduled_tasks.rb +5 -1
  25. data/db/migrate/20180223155025_add_last_fail_status_to_scheduled_tasks.rb +5 -1
  26. data/db/migrate/20180302170138_add_enabled_to_scheduled_tasks.rb +5 -1
  27. data/exe/tasks_scheduler +3 -1
  28. data/exe/tasks_scheduler_run_task +3 -1
  29. data/lib/tasks_scheduler.rb +4 -8
  30. data/lib/tasks_scheduler/app_gem.rb +18 -0
  31. data/lib/tasks_scheduler/checker.rb +23 -4
  32. data/lib/tasks_scheduler/checker/log.rb +34 -0
  33. data/lib/tasks_scheduler/cron_parser_patch.rb +5 -1
  34. data/lib/tasks_scheduler/cron_scheduling_validator.rb +3 -0
  35. data/lib/tasks_scheduler/daemon.rb +20 -13
  36. data/lib/tasks_scheduler/engine.rb +5 -0
  37. data/lib/tasks_scheduler/version.rb +3 -1
  38. data/test/dummy/Rakefile +3 -1
  39. data/test/dummy/app/controllers/application_controller.rb +2 -0
  40. data/test/dummy/app/helpers/application_helper.rb +2 -0
  41. data/test/dummy/bin/bundle +3 -1
  42. data/test/dummy/bin/rails +3 -1
  43. data/test/dummy/bin/rake +2 -0
  44. data/test/dummy/bin/setup +3 -1
  45. data/test/dummy/config.ru +2 -0
  46. data/test/dummy/config/application.rb +3 -1
  47. data/test/dummy/config/boot.rb +4 -2
  48. data/test/dummy/config/environment.rb +3 -1
  49. data/test/dummy/config/environments/development.rb +2 -0
  50. data/test/dummy/config/environments/production.rb +2 -0
  51. data/test/dummy/config/environments/test.rb +2 -0
  52. data/test/dummy/config/initializers/assets.rb +2 -0
  53. data/test/dummy/config/initializers/backtrace_silencers.rb +1 -0
  54. data/test/dummy/config/initializers/cookies_serializer.rb +2 -0
  55. data/test/dummy/config/initializers/filter_parameter_logging.rb +2 -0
  56. data/test/dummy/config/initializers/inflections.rb +1 -0
  57. data/test/dummy/config/initializers/mime_types.rb +1 -0
  58. data/test/dummy/config/initializers/session_store.rb +2 -0
  59. data/test/dummy/config/initializers/wrap_parameters.rb +2 -0
  60. data/test/dummy/config/routes.rb +2 -0
  61. data/test/fixtures/scheduled_tasks.yml +2 -0
  62. data/test/models/scheduled_task_test.rb +6 -4
  63. data/test/test_helper.rb +6 -4
  64. metadata +91 -32
@@ -0,0 +1,12 @@
1
+ <h3>Logs</h3>
2
+ <ul>
3
+ <% ::TasksScheduler::Checker.instance.logs.each do |log| %>
4
+ <li>
5
+ <% if log.exist? %>
6
+ <%= link_to log.key, download_log_tasks_scheduler_daemon_path(log.key) %>
7
+ <% else %>
8
+ <span style="color: grey" title='Log "<%= log.key %>" does not exist.'><%= log.key %></span>
9
+ <% end %>
10
+ </li>
11
+ <% end %>
12
+ </ul>
@@ -0,0 +1,9 @@
1
+ <% if @result %>
2
+ <h3>Results</h3>
3
+ <dl>
4
+ <% @result.each do |k, v| %>
5
+ <dt><%= k %></dt>
6
+ <dd><%= v.present? ? v : '-' %></dd>
7
+ <% end %>
8
+ </dl>
9
+ <% end %>
@@ -1,4 +1,3 @@
1
- <strong>Daemon status: </strong>
2
1
  <% if TasksScheduler::Daemon.running? %>
3
2
  <span class="tasks_scheduler_daemon_status_up">UP</span>
4
3
  <% else %>
@@ -1,22 +1,5 @@
1
1
  <%= render partial: '/tasks_scheduler/navbar' %>
2
2
  <h2><%= I18n.t(:tasks_scheduler_daemon) %></h2>
3
- <p>
4
- <%= render partial: '/tasks_scheduler_daemon/running_status' %>
5
- <br/>
6
- <strong>Actions: </strong>
7
- <%= safe_join(::TasksScheduler::Daemon::ACTIONS.map do |action|
8
- link_to action, execute_tasks_scheduler_daemon_path(action), method: :post
9
- end, ' | ') %>
10
- <br/>
11
- <strong>Log: </strong>
12
- <%= link_to 'download', download_log_tasks_scheduler_daemon_path %>
13
- </p>
14
- <% if @result %>
15
- <h3>Results</h3>
16
- <dl>
17
- <% @result.each do |k, v| %>
18
- <dt><%= k %></dt>
19
- <dd><%= v.present? ? v : '-' %></dd>
20
- <% end %>
21
- </dl>
22
- <% end %>
3
+ <%= render partial: 'daemon', locals: {status_label: 'Status:'} %>
4
+ <%= render partial: 'logs' %>
5
+ <%= render partial: 'results' %>
@@ -1 +1,3 @@
1
- Rails.application.config.assets.precompile += %w( active_scaffold/indicator.gif )
1
+ # frozen_string_literal: true
2
+
3
+ Rails.application.config.assets.precompile += %w[active_scaffold/indicator.gif]
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Rails.application.routes.draw do
2
4
  resources(:scheduled_tasks) do
3
5
  as_routes
@@ -15,6 +17,6 @@ Rails.application.routes.draw do
15
17
  to: 'tasks_scheduler_daemon#execute', as: :execute_tasks_scheduler_daemon
16
18
  get '/tasks_scheduler_daemon/status', to: 'tasks_scheduler_daemon#status',
17
19
  as: :status_tasks_scheduler_daemon
18
- get '/tasks_scheduler_daemon/download_log', to: 'tasks_scheduler_daemon#download_log',
19
- as: :download_log_tasks_scheduler_daemon
20
+ get '/tasks_scheduler_daemon/download_log/:log_key', to: 'tasks_scheduler_daemon#download_log',
21
+ as: :download_log_tasks_scheduler_daemon
20
22
  end
@@ -1,4 +1,8 @@
1
- class CreateScheduledTasks < ActiveRecord::Migration
1
+ # frozen_string_literal: true
2
+
3
+ class CreateScheduledTasks < (
4
+ Rails.version < '5.2' ? ActiveRecord::Migration : ActiveRecord::Migration[4.2]
5
+ )
2
6
  def change
3
7
  create_table :scheduled_tasks do |t|
4
8
  t.string :scheduling
@@ -1,4 +1,8 @@
1
- class AddStatusAttributesToScheduledTasks < ActiveRecord::Migration
1
+ # frozen_string_literal: true
2
+
3
+ class AddStatusAttributesToScheduledTasks < (
4
+ Rails.version < '5.2' ? ActiveRecord::Migration : ActiveRecord::Migration[4.2]
5
+ )
2
6
  def change
3
7
  add_column :scheduled_tasks, :last_run_start, :datetime
4
8
  add_column :scheduled_tasks, :last_run_successful_start, :datetime
@@ -1,4 +1,8 @@
1
- class AddPidToScheduledTasks < ActiveRecord::Migration
1
+ # frozen_string_literal: true
2
+
3
+ class AddPidToScheduledTasks < (
4
+ Rails.version < '5.2' ? ActiveRecord::Migration : ActiveRecord::Migration[4.2]
5
+ )
2
6
  def change
3
7
  add_column :scheduled_tasks, :pid, :integer
4
8
  end
@@ -1,4 +1,8 @@
1
- class AddArgsToScheduledTasks < ActiveRecord::Migration
1
+ # frozen_string_literal: true
2
+
3
+ class AddArgsToScheduledTasks < (
4
+ Rails.version < '5.2' ? ActiveRecord::Migration : ActiveRecord::Migration[4.2]
5
+ )
2
6
  def change
3
7
  add_column :scheduled_tasks, :args, :string
4
8
  end
@@ -1,4 +1,8 @@
1
- class AddLastFailStatusToScheduledTasks < ActiveRecord::Migration
1
+ # frozen_string_literal: true
2
+
3
+ class AddLastFailStatusToScheduledTasks < (
4
+ Rails.version < '5.2' ? ActiveRecord::Migration : ActiveRecord::Migration[4.2]
5
+ )
2
6
  def change
3
7
  add_column :scheduled_tasks, :last_fail_status, :string
4
8
  end
@@ -1,4 +1,8 @@
1
- class AddEnabledToScheduledTasks < ActiveRecord::Migration
1
+ # frozen_string_literal: true
2
+
3
+ class AddEnabledToScheduledTasks < (
4
+ Rails.version < '5.2' ? ActiveRecord::Migration : ActiveRecord::Migration[4.2]
5
+ )
2
6
  def change
3
7
  add_column :scheduled_tasks, :enabled, :boolean, null: false, default: true
4
8
  end
@@ -1,12 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'rubygems'
4
5
  require 'daemons'
5
6
  require 'fileutils'
6
7
 
7
8
  def find_rails_root(dir = Dir.pwd)
8
- fail 'Rails root not found' if dir == '' || dir == '/' || dir == '.'
9
+ raise 'Rails root not found' if ['', '/', '.'].include?(dir)
9
10
  return dir if File.exist?(File.expand_path('config/environment.rb', dir))
11
+
10
12
  rails_root(File.dirname(dir))
11
13
  end
12
14
 
@@ -1,11 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'rubygems'
4
5
  require 'daemons'
5
6
 
6
7
  def find_rails_root(dir = Dir.pwd)
7
- fail 'Rails root not found' if dir == '' || dir == '/' || dir == '.'
8
+ raise 'Rails root not found' if ['', '/', '.'].include?(dir)
8
9
  return dir if File.exist?(File.expand_path('config/environment.rb', dir))
10
+
9
11
  rails_root(File.dirname(dir))
10
12
  end
11
13
 
@@ -1,11 +1,7 @@
1
- require 'tasks_scheduler/engine'
2
- require 'active_scaffold'
3
- require 'js-routes'
4
- require 'parse-cron'
5
- require 'tasks_scheduler/cron_scheduling_validator'
6
- require 'tasks_scheduler/cron_parser_patch'
7
- require 'tasks_scheduler/checker'
8
- require 'tasks_scheduler/daemon'
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/require_sub'
9
4
 
10
5
  module TasksScheduler
6
+ ::EacRubyUtils.require_sub __FILE__
11
7
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_gems_utils/gem'
4
+ require 'singleton'
5
+
6
+ module TasksScheduler
7
+ class AppGem < ::SimpleDelegator
8
+ include ::Singleton
9
+
10
+ def initialize
11
+ super(::EacRubyGemsUtils::Gem.new(::Rails.root))
12
+ end
13
+
14
+ def bundle(*args)
15
+ super(*args).chdir_root.envvar('RAILS_ENV', ::Rails.env)
16
+ end
17
+ end
18
+ end
@@ -1,9 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tasks_scheduler/checker/log'
4
+
1
5
  module TasksScheduler
2
6
  class Checker
3
7
  include Singleton
4
8
 
5
9
  CHECK_INTERVAL = 15
6
- LOG_ON_FILE_ENV_KEY = 'TASKS_SCHEDULER_LOG_ON_FILE'.freeze
10
+ LOG_ON_FILE_ENV_KEY = 'TASKS_SCHEDULER_LOG_ON_FILE'
11
+ LOGS_KEYS = %w[rails stdout stderr].freeze
7
12
 
8
13
  def run
9
14
  check_log
@@ -18,15 +23,29 @@ module TasksScheduler
18
23
  end
19
24
 
20
25
  def log_path
21
- ::Rails.root.join('log', 'tasks_scheduler', 'checker.log')
26
+ rais_log.path
27
+ end
28
+
29
+ def logs
30
+ LOGS_KEYS.map { |key| send("#{key}_log") }
31
+ end
32
+
33
+ LOGS_KEYS.each do |log_key|
34
+ class_eval <<CODE, __FILE__, __LINE__ + 1
35
+ def #{log_key}_log
36
+ @#{log_key}_log ||= ::TasksScheduler::Checker::Log.new('#{log_key}')
37
+ end
38
+ CODE
22
39
  end
23
40
 
24
41
  private
25
42
 
26
43
  def check_log
27
44
  return unless log_on_file?
28
- ::FileUtils.mkdir_p(File.dirname(log_path))
29
- ::Rails.logger = ::Logger.new(log_path)
45
+
46
+ ::Rails.logger = ::Logger.new(rails_log.path)
47
+ $stdout.reopen(stdout_log.path, 'w')
48
+ $stderr.reopen(stderr_log.path, 'w')
30
49
  end
31
50
 
32
51
  def log_on_file?
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+
5
+ module TasksScheduler
6
+ class Checker
7
+ class Log
8
+ class << self
9
+ def logs_directory
10
+ @logs_directory ||= ::Rails.root.join('log', 'tasks_scheduler', 'checker')
11
+ end
12
+ end
13
+
14
+ attr_reader :key
15
+
16
+ def initialize(key)
17
+ @key = key
18
+ ::FileUtils.mkdir_p(dirname)
19
+ end
20
+
21
+ def dirname
22
+ ::File.dirname(path)
23
+ end
24
+
25
+ def exist?
26
+ ::File.exist?(path)
27
+ end
28
+
29
+ def path
30
+ self.class.logs_directory.join("#{key}.log")
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,8 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'parse-cron'
4
+
1
5
  module TasksScheduler
2
6
  module CronParserPatch
3
7
  class TasksSchedulerTimeSource
4
8
  class << self
5
- def local(year, month, day, hour, min, second)
9
+ def local(year, month, day, hour, min, second) # rubocop:disable Metrics/ParameterLists
6
10
  Time.utc(year, month, day, hour, min, second)
7
11
  end
8
12
 
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module TasksScheduler
2
4
  class CronSchedulingValidator < ActiveModel::EachValidator
3
5
  def validate_each(record, attribute, value)
4
6
  return if value_valid?(value)
7
+
5
8
  record.errors[attribute] << (options[:message] ||
6
9
  I18n.translate(:cron_scheduling_validator_error_message))
7
10
  end
@@ -1,28 +1,35 @@
1
- require 'open3'
1
+ # frozen_string_literal: true
2
+
3
+ require 'tasks_scheduler/app_gem'
2
4
 
3
5
  module TasksScheduler
4
6
  class Daemon
5
- ACTIONS = %w(status start stop restart).freeze
7
+ ACTIONS = %w[status start stop restart].freeze
6
8
 
7
9
  class << self
8
- def execute(action)
10
+ def daemon_command(action)
9
11
  raise "Action not allowed: #{action} (Allowed: #{ACTIONS})" unless ACTIONS.include?(action)
10
- command = ['bundle', 'exec', 'tasks_scheduler', action]
11
- Dir.chdir(Rails.root) do
12
- Open3.popen3(env_args, *command) do |_stdin, stdout, stderr, wait_thr|
13
- { action: action, env_args: env_args.map { |k, v| "#{k}=#{v}" }.join(' | '),
14
- command: command.join(' '), status: wait_thr.value.to_i, stdout: stdout.read,
15
- stderr: stderr.read }
16
- end
17
- end
12
+
13
+ ::TasksScheduler::AppGem.instance.bundle('exec', 'tasks_scheduler', action)
14
+ .envvar(::TasksScheduler::Checker::LOG_ON_FILE_ENV_KEY, '1')
15
+ end
16
+
17
+ def execute(action)
18
+ command = daemon_command(action)
19
+ result = command.execute
20
+ {
21
+ action: action, env_args: env_args_to_s(command), command: command.to_s,
22
+ status: result.fetch(:exit_code), stdout: result.fetch(:stdout),
23
+ stderr: result.fetch(:stderr)
24
+ }
18
25
  end
19
26
 
20
27
  def running?
21
28
  execute('status')[:status].zero?
22
29
  end
23
30
 
24
- def env_args
25
- { 'RAILS_ENV' => Rails.env, ::TasksScheduler::Checker::LOG_ON_FILE_ENV_KEY => '1' }
31
+ def env_args_to_s(command)
32
+ command.send(:extra_options).fetch(:envvars).map { |k, v| "#{k}=#{v}" }.join(' | ')
26
33
  end
27
34
  end
28
35
  end
@@ -1,3 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_scaffold'
4
+ require 'js-routes'
5
+
1
6
  module TasksScheduler
2
7
  class Engine < ::Rails::Engine
3
8
  initializer :append_migrations do |app|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module TasksScheduler
2
- VERSION = '0.2.3'.freeze
4
+ VERSION = '0.5.0'
3
5
  end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Add your own tasks in files placed in lib/tasks ending in .rake,
2
4
  # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
5
 
4
- require File.expand_path('../config/application', __FILE__)
6
+ require File.expand_path('config/application', __dir__)
5
7
 
6
8
  Rails.application.load_tasks
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class ApplicationController < ActionController::Base
2
4
  # Prevent CSRF attacks by raising an exception.
3
5
  # For APIs, you may want to use :null_session instead.
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ApplicationHelper
2
4
  end
@@ -1,3 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
2
+ # frozen_string_literal: true
3
+
4
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
3
5
  load Gem.bin_path('bundler', 'bundle')
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
- APP_PATH = File.expand_path('../../config/application', __FILE__)
2
+ # frozen_string_literal: true
3
+
4
+ APP_PATH = File.expand_path('../config/application', __dir__)
3
5
  require_relative '../config/boot'
4
6
  require 'rails/commands'
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
2
4
  require_relative '../config/boot'
3
5
  require 'rake'
4
6
  Rake.application.run
@@ -1,8 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
2
4
  require 'pathname'
3
5
 
4
6
  # path to your application root.
5
- APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
7
+ APP_ROOT = Pathname.new File.expand_path('..', __dir__)
6
8
 
7
9
  Dir.chdir APP_ROOT do
8
10
  # This script is a starting point to setup your application.