toro 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +7 -0
  3. data/Appraisals +7 -0
  4. data/Gemfile +3 -0
  5. data/app/assets/javascripts/toro/monitor/abstract_jobs_table.js.coffee +188 -0
  6. data/app/assets/javascripts/toro/monitor/application.js.coffee +14 -0
  7. data/app/assets/javascripts/toro/monitor/chart.js.coffee +203 -0
  8. data/app/assets/javascripts/toro/monitor/initialize.js.coffee.erb +25 -0
  9. data/app/assets/javascripts/toro/monitor/jobs_table.js.coffee +63 -0
  10. data/app/assets/javascripts/toro/monitor/processes_table.js.coffee +96 -0
  11. data/app/assets/javascripts/toro/monitor/queue_jobs_table.js.coffee +91 -0
  12. data/app/assets/stylesheets/toro/monitor/application.css.sass +5 -0
  13. data/app/assets/stylesheets/toro/monitor/jobs_table.css.sass +69 -0
  14. data/app/assets/stylesheets/toro/monitor/layout.css.sass +5 -0
  15. data/app/controllers/toro/monitor/api/jobs_controller.rb +65 -0
  16. data/app/controllers/toro/monitor/api/processes_controller.rb +13 -0
  17. data/app/controllers/toro/monitor/api/queues_controller.rb +24 -0
  18. data/app/controllers/toro/monitor/base_controller.rb +11 -0
  19. data/app/controllers/toro/monitor/jobs_controller.rb +11 -0
  20. data/app/controllers/toro/monitor/processes_controller.rb +8 -0
  21. data/app/controllers/toro/monitor/queues_controller.rb +9 -0
  22. data/app/datatables/toro/monitor/abstract_datatable.rb +71 -0
  23. data/app/datatables/toro/monitor/jobs_datatable.rb +60 -0
  24. data/app/datatables/toro/monitor/processes_datatable.rb +60 -0
  25. data/app/helpers/toro/monitor/toro_monitor_helper.rb +13 -0
  26. data/app/views/toro/monitor/jobs/_jobs.slim +14 -0
  27. data/app/views/toro/monitor/jobs/chart.slim +1 -0
  28. data/app/views/toro/monitor/jobs/index.slim +1 -0
  29. data/app/views/toro/monitor/layouts/application.slim +32 -0
  30. data/app/views/toro/monitor/processes/index.slim +14 -0
  31. data/app/views/toro/monitor/queues/_jobs.slim +14 -0
  32. data/app/views/toro/monitor/queues/index.slim +5 -0
  33. data/config/routes.rb +16 -0
  34. data/examples/chart.png +0 -0
  35. data/examples/job.png +0 -0
  36. data/examples/jobs.png +0 -0
  37. data/examples/processes.png +0 -0
  38. data/examples/queues.png +0 -0
  39. data/gemfiles/rails_3.gemfile +7 -0
  40. data/gemfiles/rails_3.gemfile.lock +146 -0
  41. data/gemfiles/rails_4.gemfile +7 -0
  42. data/gemfiles/rails_4.gemfile.lock +147 -0
  43. data/lib/toro/version.rb +1 -1
  44. data/spec/config/database.yml.example +6 -0
  45. data/spec/lib/cli_spec.rb +28 -0
  46. data/spec/lib/client_spec.rb +26 -0
  47. data/spec/lib/fetcher_spec.rb +105 -0
  48. data/spec/lib/job_spec.rb +17 -0
  49. data/spec/lib/listener_spec.rb +72 -0
  50. data/spec/lib/manager_spec.rb +78 -0
  51. data/spec/lib/middleware/server/error_spec.rb +18 -0
  52. data/spec/lib/middleware/server/error_storage_spec.rb +22 -0
  53. data/spec/lib/middleware/server/properties_spec.rb +18 -0
  54. data/spec/lib/middleware/server/retry_spec.rb +38 -0
  55. data/spec/lib/processor_spec.rb +33 -0
  56. data/spec/lib/worker_spec.rb +50 -0
  57. data/spec/spec_helper.rb +31 -0
  58. data/spec/support/active_record_spec_helper.rb +18 -0
  59. data/spec/support/jobs_helper.rb +4 -0
  60. data/spec/support/workers_helper.rb +56 -0
  61. data/toro.gemspec +29 -0
  62. data/vendor/assets/javascripts/toro/monitor/bootstrap-select.min.js +1 -0
  63. data/vendor/assets/javascripts/toro/monitor/bootstrap.min.js +6 -0
  64. data/vendor/assets/javascripts/toro/monitor/d3.js +8795 -0
  65. data/vendor/assets/javascripts/toro/monitor/datatables.bootstrap.js +96 -0
  66. data/vendor/assets/javascripts/toro/monitor/datatables.js +256 -0
  67. data/vendor/assets/javascripts/toro/monitor/datatables.standing_redraw.js.coffee +5 -0
  68. data/vendor/assets/javascripts/toro/monitor/jquery.timeago.js +27 -0
  69. data/vendor/assets/stylesheets/toro/monitor/bootstrap-select.min.css +1 -0
  70. data/vendor/assets/stylesheets/toro/monitor/bootstrap.min.css +9 -0
  71. metadata +103 -5
@@ -0,0 +1,11 @@
1
+ module Toro
2
+ module Monitor
3
+ class JobsController < BaseController
4
+ def index
5
+ end
6
+
7
+ def chart
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ module Toro
2
+ module Monitor
3
+ class ProcessesController < BaseController
4
+ def index
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ module Toro
2
+ module Monitor
3
+ class QueuesController < BaseController
4
+ def index
5
+ @queues = Job.select('DISTINCT queue').collect { |job| job.queue }.sort
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,71 @@
1
+ module Toro
2
+ module Monitor
3
+ class AbstractDatatable < RailsDatatables
4
+ class << self
5
+ attr_reader :search_filters
6
+
7
+ def add_search_filter(search_filter)
8
+ @search_filters << search_filter
9
+ end
10
+ end
11
+
12
+ protected
13
+
14
+ def records
15
+ @records ||= fetch_records
16
+ end
17
+
18
+ def get_duration(job)
19
+ if job.started_at
20
+ to_time = job.finished_at ? job.finished_at : Time.now
21
+ return Toro::Monitor::TimeFormatter.distance_of_time(job.started_at, to_time)
22
+ end
23
+ nil
24
+ end
25
+
26
+ def search_records(records)
27
+ if params[:sSearch].present?
28
+ records = apply_search_value_to_records(params[:sSearch], records)
29
+ end
30
+ conditions = @columns.each_with_index.map do |column, index|
31
+ value = params[:"sSearch_#{index}"]
32
+ search_condition(column, value) if value.present?
33
+ end
34
+ conditions = conditions.compact.reduce(:and)
35
+ records = records.where(conditions) if conditions.present?
36
+ records
37
+ end
38
+
39
+ def apply_search_value_to_records(search_value, records)
40
+ search_terms = []
41
+ search_value.split.each do |search_term|
42
+ filter_applied = false
43
+ self.class.search_filters.each do |search_filter|
44
+ if search_term =~ search_filter[:pattern]
45
+ records = search_filter[:filter].call(search_term, records)
46
+ filter_applied = true
47
+ break
48
+ end
49
+ end
50
+ search_terms << search_term unless filter_applied
51
+ end
52
+ value = search_terms.join(' ')
53
+ conditions = @searchable_columns.map do |column|
54
+ search_condition(column, value)
55
+ end
56
+ conditions = conditions.reduce(:or)
57
+ records = records.where(conditions)
58
+ records
59
+ end
60
+
61
+ def search_condition(column, value)
62
+ column = column.split('.').last
63
+ column_hash = @model_name.columns_hash[column]
64
+ if column_hash && [:string, :text].include?(column_hash.type)
65
+ return @model_name.arel_table[column].matches("%#{value}%")
66
+ end
67
+ @model_name.arel_table[column].eq(value)
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,60 @@
1
+ module Toro
2
+ module Monitor
3
+ class JobsDatatable < AbstractDatatable
4
+ @search_filters = []
5
+
6
+ def initialize(view)
7
+ @model_name = Toro::Job
8
+ @columns = [
9
+ 'toro_jobs.id',
10
+ 'toro_jobs.started_by',
11
+ 'toro_jobs.queue',
12
+ 'toro_jobs.class_name',
13
+ 'toro_jobs.name',
14
+ 'toro_jobs.created_at',
15
+ 'toro_jobs.started_at',
16
+ 'COALESCE(toro_jobs.finished_at, NOW()) - toro_jobs.started_at',
17
+ 'toro_jobs.status',
18
+ 'toro_jobs.properties',
19
+ 'toro_jobs.args'
20
+ ]
21
+ @searchable_columns = [
22
+ 'toro_jobs.started_by',
23
+ 'toro_jobs.queue',
24
+ 'toro_jobs.class_name',
25
+ 'toro_jobs.args',
26
+ 'toro_jobs.status',
27
+ 'toro_jobs.name'
28
+ ]
29
+ super(view)
30
+ end
31
+
32
+ protected
33
+
34
+ def data
35
+ records.map do |job|
36
+ [
37
+ job.id,
38
+ job.started_by,
39
+ job.queue,
40
+ job.class_name,
41
+ job.name || job.args.to_s,
42
+ job.created_at,
43
+ job.started_at,
44
+ get_duration(job),
45
+ job.properties.blank? ? nil : job.properties.values.map { |value| value.to_s }.join(', ')[0,30],
46
+ job.status,
47
+ job.properties,
48
+ job.args
49
+ ]
50
+ end
51
+ end
52
+
53
+ def get_raw_records
54
+ records = Toro::Job
55
+ records = records.where(queue: params[:queue]) unless params[:queue].blank?
56
+ records
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,60 @@
1
+ module Toro
2
+ module Monitor
3
+ class ProcessesDatatable < AbstractDatatable
4
+ @search_filters = []
5
+
6
+ def initialize(view)
7
+ @model_name = Toro::Job
8
+ @columns = [
9
+ 'toro_jobs.id',
10
+ 'toro_jobs.started_by',
11
+ 'toro_jobs.queue',
12
+ 'toro_jobs.class_name',
13
+ 'toro_jobs.name',
14
+ 'toro_jobs.created_at',
15
+ 'toro_jobs.started_at',
16
+ 'COALESCE(toro_jobs.finished_at, NOW()) - toro_jobs.started_at',
17
+ 'toro_jobs.status',
18
+ 'toro_jobs.properties',
19
+ 'toro_jobs.args'
20
+ ]
21
+ @searchable_columns = [
22
+ 'toro_jobs.started_by',
23
+ 'toro_jobs.queue',
24
+ 'toro_jobs.class_name',
25
+ 'toro_jobs.args',
26
+ 'toro_jobs.status',
27
+ 'toro_jobs.name'
28
+ ]
29
+ super(view)
30
+ end
31
+
32
+ protected
33
+
34
+ def data
35
+ records.map do |job|
36
+ [
37
+ job.id,
38
+ job.started_by,
39
+ job.queue,
40
+ job.class_name,
41
+ job.name || job.args.to_s,
42
+ job.created_at,
43
+ job.started_at,
44
+ get_duration(job),
45
+ job.properties.blank? ? nil : job.properties.values.map { |value| value.to_s }.join(', ')[0,30],
46
+ job.status,
47
+ job.properties,
48
+ job.args
49
+ ]
50
+ end
51
+ end
52
+
53
+ def get_raw_records
54
+ records = Toro::Job
55
+ records = records.where(status: 'running')
56
+ records
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,13 @@
1
+ module Toro
2
+ module Monitor
3
+ module ToroMonitorHelper
4
+ def app_name
5
+ 'Toro'
6
+ end
7
+
8
+ def root_path
9
+ Toro::Monitor.root_path
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ table class="jobs-table jobs table table-hover table-bordered table-striped table-white" data-source="#{root_path}api/jobs"
2
+ thead
3
+ th ID
4
+ th Process
5
+ th Queue
6
+ th Class
7
+ th Name
8
+ th Queued
9
+ th Started
10
+ th Duration
11
+ th Properties
12
+ th Status
13
+ th Error
14
+ th Args
@@ -0,0 +1 @@
1
+ div class="chart"
@@ -0,0 +1 @@
1
+ == render partial: 'jobs'
@@ -0,0 +1,32 @@
1
+ doctype html
2
+ html lang="en"
3
+ meta charset="utf-8"
4
+ meta name="viewport" content="width=device-width, initial-scale=1.0"
5
+ title= content_for?(:title) ? yield(:title) : app_name
6
+ = stylesheet_link_tag "toro/monitor/application"
7
+ = csrf_meta_tags
8
+
9
+ body
10
+ .navbar.navbar-fixed-top
11
+ .navbar-inner
12
+ .container
13
+ a.btn.btn-navbar data-toggle="collapse" data-target=".nav-collapse"
14
+ span.icon-bar
15
+ span.icon-bar
16
+ span.icon-bar
17
+
18
+ = link_to app_name, root_path, class: "brand"
19
+
20
+ .nav-collapse
21
+ ul.nav
22
+ li class=(params[:controller] == 'toro/monitor/jobs' && params[:action] != 'chart' ? 'active' : '') = link_to "Jobs", root_path
23
+ li class=(params[:controller] == 'toro/monitor/queues' ? 'active' : '') = link_to "Queues", "#{root_path}queues"
24
+ li class=(params[:controller] == 'toro/monitor/processes' ? 'active' : '') = link_to "Processes", "#{root_path}processes"
25
+ li class=(params[:controller] == 'toro/monitor/jobs' && params[:action] == 'chart' ? 'active' : '') = link_to "Chart", "#{root_path}chart"
26
+
27
+ .container
28
+ = yield
29
+
30
+ = javascript_include_tag "toro/monitor/application"
31
+ - Toro::Monitor.options[:javascripts].each do |javascript|
32
+ = javascript_include_tag javascript
@@ -0,0 +1,14 @@
1
+ table class="processes table table-hover table-bordered table-striped table-white" data-source="#{root_path}api/processes"
2
+ thead
3
+ th ID
4
+ th Process
5
+ th Queue
6
+ th Class
7
+ th Name
8
+ th Queued
9
+ th Started
10
+ th Duration
11
+ th Properties
12
+ th Status
13
+ th Error
14
+ th Args
@@ -0,0 +1,14 @@
1
+ table class="jobs-table queue-jobs table table-hover table-bordered table-striped table-white" data-source="#{root_path}api/jobs"
2
+ thead
3
+ th ID
4
+ th Process
5
+ th Queue
6
+ th Class
7
+ th Name
8
+ th Queued
9
+ th Started
10
+ th Duration
11
+ th Properties
12
+ th Status
13
+ th Error
14
+ th Args
@@ -0,0 +1,5 @@
1
+ .queue-stats
2
+ form.form-inline
3
+ =select_tag :queue_select, options_for_select(@queues), class: 'span2'
4
+
5
+ == render partial: 'jobs'
@@ -0,0 +1,16 @@
1
+ Toro::Monitor::Engine.routes.draw do
2
+ get '/', to: 'jobs#index', :as => 'toro_monitor'
3
+ get '/chart', to: 'jobs#chart'
4
+ get '/processes', to: 'processes#index'
5
+ get '/queues', to: 'queues#index'
6
+
7
+ namespace 'api' do
8
+ get '/jobs', to: 'jobs#index'
9
+ get '/jobs/custom_views/:id', to: 'jobs#custom_views'
10
+ get '/jobs/chart', to: 'jobs#chart'
11
+ get '/jobs/retry/:id', to: 'jobs#retry'
12
+ get '/jobs/statuses', to: 'jobs#statuses'
13
+ get '/processes', to: 'processes#index'
14
+ get '/queues/:queue', to: 'queues#show'
15
+ end
16
+ end
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "3.2.17"
6
+
7
+ gemspec :path => "../"
@@ -0,0 +1,146 @@
1
+ PATH
2
+ remote: ..
3
+ specs:
4
+ toro (0.2.2)
5
+ activerecord-postgres-hstore
6
+ celluloid (>= 0.15.2)
7
+ jquery-datatables-rails (>= 2.1.10.0.2)
8
+ nested-hstore
9
+ pg
10
+ rails (>= 3.0)
11
+ rails-datatables
12
+ slim
13
+
14
+ GEM
15
+ remote: https://rubygems.org/
16
+ specs:
17
+ actionmailer (3.2.17)
18
+ actionpack (= 3.2.17)
19
+ mail (~> 2.5.4)
20
+ actionpack (3.2.17)
21
+ activemodel (= 3.2.17)
22
+ activesupport (= 3.2.17)
23
+ builder (~> 3.0.0)
24
+ erubis (~> 2.7.0)
25
+ journey (~> 1.0.4)
26
+ rack (~> 1.4.5)
27
+ rack-cache (~> 1.2)
28
+ rack-test (~> 0.6.1)
29
+ sprockets (~> 2.2.1)
30
+ activemodel (3.2.17)
31
+ activesupport (= 3.2.17)
32
+ builder (~> 3.0.0)
33
+ activerecord (3.2.17)
34
+ activemodel (= 3.2.17)
35
+ activesupport (= 3.2.17)
36
+ arel (~> 3.0.2)
37
+ tzinfo (~> 0.3.29)
38
+ activerecord-postgres-hstore (0.7.7)
39
+ activerecord (>= 3.1)
40
+ pg-hstore (>= 1.1.5)
41
+ rake
42
+ activeresource (3.2.17)
43
+ activemodel (= 3.2.17)
44
+ activesupport (= 3.2.17)
45
+ activesupport (3.2.17)
46
+ i18n (~> 0.6, >= 0.6.4)
47
+ multi_json (~> 1.0)
48
+ appraisal (1.0.0)
49
+ bundler
50
+ rake
51
+ thor (>= 0.14.0)
52
+ arel (3.0.3)
53
+ builder (3.0.4)
54
+ celluloid (0.16.0)
55
+ timers (~> 4.0.0)
56
+ diff-lcs (1.2.5)
57
+ erubis (2.7.0)
58
+ hike (1.2.3)
59
+ hitimes (1.2.2)
60
+ i18n (0.6.9)
61
+ journey (1.0.4)
62
+ jquery-datatables-rails (3.1.1)
63
+ actionpack (>= 3.1)
64
+ jquery-rails
65
+ railties (>= 3.1)
66
+ sass-rails
67
+ jquery-rails (3.1.2)
68
+ railties (>= 3.0, < 5.0)
69
+ thor (>= 0.14, < 2.0)
70
+ json (1.8.1)
71
+ mail (2.5.4)
72
+ mime-types (~> 1.16)
73
+ treetop (~> 1.4.8)
74
+ mime-types (1.25.1)
75
+ multi_json (1.9.2)
76
+ nested-hstore (0.1.1)
77
+ activerecord
78
+ activesupport
79
+ pg (0.18.1)
80
+ pg-hstore (1.2.0)
81
+ polyglot (0.3.4)
82
+ rack (1.4.5)
83
+ rack-cache (1.2)
84
+ rack (>= 0.4)
85
+ rack-ssl (1.3.4)
86
+ rack
87
+ rack-test (0.6.2)
88
+ rack (>= 1.0)
89
+ rails (3.2.17)
90
+ actionmailer (= 3.2.17)
91
+ actionpack (= 3.2.17)
92
+ activerecord (= 3.2.17)
93
+ activeresource (= 3.2.17)
94
+ activesupport (= 3.2.17)
95
+ bundler (~> 1.0)
96
+ railties (= 3.2.17)
97
+ rails-datatables (0.0.2)
98
+ railties (3.2.17)
99
+ actionpack (= 3.2.17)
100
+ activesupport (= 3.2.17)
101
+ rack-ssl (~> 1.3.2)
102
+ rake (>= 0.8.7)
103
+ rdoc (~> 3.4)
104
+ thor (>= 0.14.6, < 2.0)
105
+ rake (10.3.1)
106
+ rdoc (3.12.2)
107
+ json (~> 1.4)
108
+ rspec (2.14.1)
109
+ rspec-core (~> 2.14.0)
110
+ rspec-expectations (~> 2.14.0)
111
+ rspec-mocks (~> 2.14.0)
112
+ rspec-core (2.14.8)
113
+ rspec-expectations (2.14.5)
114
+ diff-lcs (>= 1.1.3, < 2.0)
115
+ rspec-mocks (2.14.6)
116
+ sass (3.4.11)
117
+ sass-rails (3.2.6)
118
+ railties (~> 3.2.0)
119
+ sass (>= 3.1.10)
120
+ tilt (~> 1.3)
121
+ slim (3.0.1)
122
+ temple (~> 0.7.3)
123
+ tilt (>= 1.3.3, < 2.1)
124
+ sprockets (2.2.2)
125
+ hike (~> 1.2)
126
+ multi_json (~> 1.0)
127
+ rack (~> 1.0)
128
+ tilt (~> 1.1, != 1.3.0)
129
+ temple (0.7.5)
130
+ thor (0.19.1)
131
+ tilt (1.4.1)
132
+ timers (4.0.1)
133
+ hitimes
134
+ treetop (1.4.15)
135
+ polyglot
136
+ polyglot (>= 0.3.1)
137
+ tzinfo (0.3.39)
138
+
139
+ PLATFORMS
140
+ ruby
141
+
142
+ DEPENDENCIES
143
+ appraisal
144
+ rails (= 3.2.17)
145
+ rspec
146
+ toro!