marty 2.7.3 → 2.8.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.
- checksums.yaml +4 -4
- data/Gemfile.lock +4 -1
- data/README.md +7 -0
- data/app/components/marty/background_job_schedule_view.rb +94 -0
- data/app/components/marty/main_auth_app.rb +46 -23
- data/app/jobs/marty/cron_job.rb +41 -0
- data/app/models/marty/background_job.rb +4 -0
- data/app/models/marty/background_job/schedule.rb +27 -0
- data/app/services/marty/background_job/update_schedule.rb +34 -0
- data/app/services/marty/jobs/schedule.rb +17 -0
- data/db/migrate/505_add_cron_to_delayed_jobs.rb +9 -0
- data/db/migrate/506_create_marty_delayed_job_schedules.rb +13 -0
- data/lib/marty.rb +1 -0
- data/lib/marty/version.rb +1 -1
- data/lib/tasks/marty_jobs.rake +8 -0
- data/make-dummy.mk +4 -2
- data/marty.gemspec +2 -1
- data/spec/dummy/app/jobs/test_job.rb +4 -0
- data/spec/dummy/app/jobs/test_job2.rb +4 -0
- data/spec/dummy/config/application.rb +2 -0
- data/spec/features/background_job_schedule_spec.rb +112 -0
- data/spec/models/background_job/schedule.rb +43 -0
- data/spec/support/chromedriver.rb +11 -1
- metadata +31 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e99ecbf41a6cda553cf318fb21bbe9c3150ec13e46b074171eaa1bd1ea12aed
|
4
|
+
data.tar.gz: c6dcdf2a95d456e27189c1369ff54de3d62ce4cd58b5d7125bf8f83d57ba8d57
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a43ae65fe90a06f4c1c35652aaba4627431ea449fedc6c262aa37a384d5d4e02d879a47c145b9dab56c756025d42e92d2c49e1a9658301ba50598164dc3e514b
|
7
|
+
data.tar.gz: ef2702ad5285cb59f777faa7b1ecceecd570945e490100e6542cd3fe7e237e597d491e3b9e7f7b9de32149645959b9142481efc3bf8614330a344a234f9c2397
|
data/Gemfile.lock
CHANGED
@@ -6,8 +6,9 @@ PATH
|
|
6
6
|
axlsx (= 3.0.0pre)
|
7
7
|
coderay
|
8
8
|
daemons (~> 1.3.1)
|
9
|
+
delayed_cron_job
|
9
10
|
delayed_job_active_record
|
10
|
-
delorean_lang (~> 0.6
|
11
|
+
delorean_lang (~> 0.6)
|
11
12
|
json-schema
|
12
13
|
mcfly (~> 0.0.20)
|
13
14
|
net-ldap (~> 0.16.1)
|
@@ -89,6 +90,8 @@ GEM
|
|
89
90
|
crass (1.0.4)
|
90
91
|
daemons (1.3.1)
|
91
92
|
database_cleaner (1.7.0)
|
93
|
+
delayed_cron_job (0.7.2)
|
94
|
+
delayed_job (>= 4.1)
|
92
95
|
delayed_job (4.1.5)
|
93
96
|
activesupport (>= 3.0, < 5.3)
|
94
97
|
delayed_job_active_record (4.1.3)
|
data/README.md
CHANGED
@@ -50,6 +50,13 @@ To delete scripts:
|
|
50
50
|
```
|
51
51
|
$ rake marty:delete_scripts
|
52
52
|
```
|
53
|
+
# Scheduled Job
|
54
|
+
|
55
|
+
To use scheduled backgroud jobs, add to `config/application.rb`:
|
56
|
+
|
57
|
+
```
|
58
|
+
config.active_job.queue_adapter = :delayed_job
|
59
|
+
```
|
53
60
|
|
54
61
|
# Dummy Application & Testing
|
55
62
|
|
@@ -0,0 +1,94 @@
|
|
1
|
+
class Marty::BackgroundJobScheduleView < Marty::Grid
|
2
|
+
ACCESSIBLE_BY = [:admin]
|
3
|
+
|
4
|
+
has_marty_permissions(
|
5
|
+
read: ACCESSIBLE_BY,
|
6
|
+
create: ACCESSIBLE_BY,
|
7
|
+
update: ACCESSIBLE_BY,
|
8
|
+
delete: ACCESSIBLE_BY,
|
9
|
+
destroy: ACCESSIBLE_BY,
|
10
|
+
edit_window__edit_form__submit: ACCESSIBLE_BY,
|
11
|
+
add_window__add_form__submit: ACCESSIBLE_BY
|
12
|
+
)
|
13
|
+
|
14
|
+
def configure(c)
|
15
|
+
super
|
16
|
+
|
17
|
+
c.title ||= I18n.t('delayed_jobs_schedule_view_title', default: 'Background Jobs Schedule')
|
18
|
+
c.model = 'Marty::BackgroundJob::Schedule'
|
19
|
+
c.paging = :buffered
|
20
|
+
c.editing = :in_form
|
21
|
+
|
22
|
+
c.attributes = [
|
23
|
+
:job_class,
|
24
|
+
:cron,
|
25
|
+
:state
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
def default_context_menu
|
30
|
+
[]
|
31
|
+
end
|
32
|
+
|
33
|
+
attribute :job_class do |c|
|
34
|
+
c.width = 400
|
35
|
+
end
|
36
|
+
|
37
|
+
attribute :cron do |c|
|
38
|
+
c.width = 400
|
39
|
+
end
|
40
|
+
|
41
|
+
attribute :state do |c|
|
42
|
+
c.width = 150
|
43
|
+
editor_config = {
|
44
|
+
trigger_action: :all,
|
45
|
+
xtype: :combo,
|
46
|
+
store: Marty::BackgroundJob::Schedule::ALL_STATES,
|
47
|
+
forceSelection: true,
|
48
|
+
}
|
49
|
+
|
50
|
+
c.column_config = { editor: editor_config }
|
51
|
+
c.field_config = editor_config
|
52
|
+
end
|
53
|
+
|
54
|
+
endpoint :edit_window__edit_form__submit do |params|
|
55
|
+
result = super(params)
|
56
|
+
next result if result.empty?
|
57
|
+
|
58
|
+
obj_hash = result.first
|
59
|
+
Marty::BackgroundJob::UpdateSchedule.call(id: obj_hash['id'], job_class: obj_hash['job_class'])
|
60
|
+
|
61
|
+
result
|
62
|
+
end
|
63
|
+
|
64
|
+
endpoint :add_window__add_form__submit do |params|
|
65
|
+
result = super(params)
|
66
|
+
next result if result.empty?
|
67
|
+
|
68
|
+
obj_hash = result.first
|
69
|
+
Marty::BackgroundJob::UpdateSchedule.call(id: obj_hash['id'], job_class: obj_hash['job_class'])
|
70
|
+
|
71
|
+
result
|
72
|
+
end
|
73
|
+
|
74
|
+
endpoint :multiedit_window__multiedit_form__submit do |_params|
|
75
|
+
client.netzke_notify 'Multiediting is disabled for cron schedules'
|
76
|
+
end
|
77
|
+
|
78
|
+
endpoint :destroy do |params|
|
79
|
+
res = params.each_with_object({}) do |id, hash|
|
80
|
+
job_class = model.find_by(id: id)&.job_class
|
81
|
+
result = super([id])
|
82
|
+
|
83
|
+
# Do nothing If it wasn't destroyed
|
84
|
+
next hash.merge(result) unless result[id.to_i] == 'ok'
|
85
|
+
|
86
|
+
Marty::BackgroundJob::UpdateSchedule.call(id: id, job_class: job_class)
|
87
|
+
hash.merge(result)
|
88
|
+
end
|
89
|
+
|
90
|
+
res
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
BackgroundJobScheduleView = Marty::BackgroundJobScheduleView
|
@@ -1,16 +1,17 @@
|
|
1
|
-
require 'marty/scripting'
|
2
|
-
require 'marty/reporting'
|
3
|
-
require 'marty/posting_window'
|
4
|
-
require 'marty/new_posting_window'
|
5
|
-
require 'marty/import_type_view'
|
6
|
-
require 'marty/user_view'
|
7
|
-
require 'marty/event_view'
|
8
|
-
require 'marty/promise_view'
|
9
1
|
require 'marty/api_auth_view'
|
10
2
|
require 'marty/api_config_view'
|
11
3
|
require 'marty/api_log_view'
|
12
4
|
require 'marty/config_view'
|
13
5
|
require 'marty/data_grid_view'
|
6
|
+
require 'marty/background_job_schedule_view'
|
7
|
+
require 'marty/event_view'
|
8
|
+
require 'marty/import_type_view'
|
9
|
+
require 'marty/new_posting_window'
|
10
|
+
require 'marty/posting_window'
|
11
|
+
require 'marty/promise_view'
|
12
|
+
require 'marty/reporting'
|
13
|
+
require 'marty/scripting'
|
14
|
+
require 'marty/user_view'
|
14
15
|
|
15
16
|
class Marty::MainAuthApp < Marty::AuthApp
|
16
17
|
extend ::Marty::Permissions
|
@@ -112,6 +113,7 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
112
113
|
:bg_status,
|
113
114
|
:bg_stop,
|
114
115
|
:bg_restart,
|
116
|
+
:background_job_schedule_view,
|
115
117
|
]
|
116
118
|
},
|
117
119
|
]
|
@@ -276,6 +278,14 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
276
278
|
a.disabled = !self.class.has_admin_perm?
|
277
279
|
end
|
278
280
|
|
281
|
+
action :background_job_schedule_view do |a|
|
282
|
+
a.text = 'Schedule Background Jobs'
|
283
|
+
a.tooltip = 'Edit Delayed Jobs Cron schedules'
|
284
|
+
a.icon_cls = 'fa fa-cog glyph'
|
285
|
+
a.disabled = !self.class.has_admin_perm?
|
286
|
+
a.handler = :netzke_load_component_by_action
|
287
|
+
end
|
288
|
+
|
279
289
|
action :log_view do |a|
|
280
290
|
a.text = 'View Log'
|
281
291
|
a.tooltip = 'View Log'
|
@@ -365,31 +375,44 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
365
375
|
end
|
366
376
|
|
367
377
|
######################################################################
|
368
|
-
|
369
|
-
component :scripting do |c|
|
370
|
-
c.allow_edit = self.class.has_scripting_perm?
|
371
|
-
end
|
372
|
-
component :reporting
|
373
|
-
component :promise_view
|
374
|
-
component :posting_window
|
375
|
-
component :new_posting_window do |c|
|
376
|
-
c.disabled = Marty::Util.warped? || !self.class.has_posting_perm?
|
377
|
-
end
|
378
|
-
component :import_type_view
|
379
|
-
component :user_view
|
380
|
-
component :event_view
|
381
|
-
component :config_view
|
382
|
-
component :data_grid_view
|
383
378
|
component :api_auth_view do |c|
|
384
379
|
c.disabled = Marty::Util.warped?
|
385
380
|
end
|
381
|
+
|
386
382
|
component :api_log_view
|
383
|
+
|
387
384
|
component :api_config_view
|
388
385
|
|
386
|
+
component :background_job_schedule_view
|
387
|
+
|
388
|
+
component :config_view
|
389
|
+
|
390
|
+
component :data_grid_view
|
391
|
+
|
392
|
+
component :event_view
|
393
|
+
|
394
|
+
component :import_type_view
|
395
|
+
|
389
396
|
component :log_view do |c|
|
390
397
|
c.klass = Marty::LogView
|
391
398
|
end
|
392
399
|
|
400
|
+
component :new_posting_window do |c|
|
401
|
+
c.disabled = Marty::Util.warped? || !self.class.has_posting_perm?
|
402
|
+
end
|
403
|
+
|
404
|
+
component :posting_window
|
405
|
+
|
406
|
+
component :promise_view
|
407
|
+
|
408
|
+
component :reporting
|
409
|
+
|
410
|
+
component :scripting do |c|
|
411
|
+
c.allow_edit = self.class.has_scripting_perm?
|
412
|
+
end
|
413
|
+
|
414
|
+
component :user_view
|
415
|
+
|
393
416
|
endpoint :reload_scripts do |_params|
|
394
417
|
Marty::Script.load_scripts
|
395
418
|
client.netzke_notify 'Scripts have been reloaded'
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class Marty::CronJob < ActiveJob::Base
|
2
|
+
class << self
|
3
|
+
def schedule
|
4
|
+
return reschedule if scheduled?
|
5
|
+
|
6
|
+
cron = cron_expression
|
7
|
+
|
8
|
+
return if cron.blank?
|
9
|
+
|
10
|
+
set(cron: cron).perform_later
|
11
|
+
end
|
12
|
+
|
13
|
+
def reschedule
|
14
|
+
dj = delayed_job
|
15
|
+
return dj.update(cron: cron_expression) if dj.locked_by?
|
16
|
+
|
17
|
+
remove
|
18
|
+
schedule
|
19
|
+
end
|
20
|
+
|
21
|
+
def remove
|
22
|
+
delayed_job.destroy if scheduled?
|
23
|
+
end
|
24
|
+
|
25
|
+
alias remove_schedule remove
|
26
|
+
|
27
|
+
def scheduled?
|
28
|
+
delayed_job.present?
|
29
|
+
end
|
30
|
+
|
31
|
+
def delayed_job
|
32
|
+
Delayed::Job.
|
33
|
+
where('handler LIKE ?', "%job_class: #{name}\n%").
|
34
|
+
first
|
35
|
+
end
|
36
|
+
|
37
|
+
def cron_expression
|
38
|
+
::Marty::BackgroundJob::Schedule.on.find_by(job_class: name)&.cron
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Marty
|
2
|
+
module BackgroundJob
|
3
|
+
class Schedule < Marty::Base
|
4
|
+
self.table_name = 'marty_background_job_schedules'
|
5
|
+
|
6
|
+
# Copied and adjusted:
|
7
|
+
# https://github.com/javan/whenever/blob/e4507e2ed2158c603f0c334a8b0a957711db343a/lib/whenever/cron.rb
|
8
|
+
REGEX = %r{\A(((\*?[\d/,\-]*)\s){3}(\*?([\d/,\-])*\s)(\*?([\d/,\-])*))\z}i
|
9
|
+
|
10
|
+
validates :job_class, :cron, :state, presence: true
|
11
|
+
validates :job_class, uniqueness: true
|
12
|
+
validates :cron, format: { with: REGEX }
|
13
|
+
|
14
|
+
validate :job_class_validation
|
15
|
+
|
16
|
+
ALL_STATES = %w[on off].freeze
|
17
|
+
enum state: ALL_STATES.zip(ALL_STATES).to_h
|
18
|
+
|
19
|
+
def job_class_validation
|
20
|
+
job_class.constantize.respond_to?(:schedule)
|
21
|
+
rescue NameError
|
22
|
+
errors.add(:job_class, "doesn't exist")
|
23
|
+
false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Marty
|
2
|
+
module BackgroundJob
|
3
|
+
module UpdateSchedule
|
4
|
+
def self.call(id:, job_class:)
|
5
|
+
model = Marty::BackgroundJob::Schedule.find_by(id: id)
|
6
|
+
|
7
|
+
return remove_schedule(job_class: job_class) unless model.present?
|
8
|
+
return remove_schedule(job_class: job_class) if model.off?
|
9
|
+
return schedule(job_class: job_class) if model.on?
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.remove_schedule(job_class:)
|
13
|
+
klass = job_class.constantize
|
14
|
+
klass.remove_schedule if klass.respond_to?(:remove_schedule)
|
15
|
+
|
16
|
+
true
|
17
|
+
rescue NameError
|
18
|
+
false
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.schedule(job_class:)
|
22
|
+
klass = job_class.constantize
|
23
|
+
|
24
|
+
return false unless klass.respond_to?(:schedule)
|
25
|
+
|
26
|
+
klass.schedule
|
27
|
+
|
28
|
+
true
|
29
|
+
rescue NameError
|
30
|
+
false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Marty
|
2
|
+
module Jobs
|
3
|
+
module Schedule
|
4
|
+
extend Delorean::Functions
|
5
|
+
|
6
|
+
delorean_fn :call, sig: 0 do
|
7
|
+
glob = Rails.root.join('app', 'jobs', '**', '*_job.rb')
|
8
|
+
Dir.glob(glob).each { |f| require f }
|
9
|
+
|
10
|
+
Marty::CronJob.subclasses.map do |klass|
|
11
|
+
klass.schedule
|
12
|
+
[klass.name, klass.cron_expression]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class CreateMartyDelayedJobSchedules < ActiveRecord::Migration[5.1]
|
2
|
+
def change
|
3
|
+
create_table :marty_background_job_schedules do |t|
|
4
|
+
t.string :job_class, null: false
|
5
|
+
t.string :cron, null: false
|
6
|
+
t.string :state, null: false
|
7
|
+
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
|
11
|
+
add_index :marty_background_job_schedules, :job_class, unique: true
|
12
|
+
end
|
13
|
+
end
|
data/lib/marty.rb
CHANGED
data/lib/marty/version.rb
CHANGED
data/make-dummy.mk
CHANGED
@@ -2,10 +2,12 @@ dummy-app-build:
|
|
2
2
|
docker-compose --file=docker-compose.dummy.yml build
|
3
3
|
|
4
4
|
dummy-app:
|
5
|
-
docker-compose --file=docker-compose.dummy.yml up
|
5
|
+
docker-compose --file=docker-compose.dummy.yml up -d app
|
6
|
+
docker attach marty_app_1
|
6
7
|
|
7
8
|
dummy-app-start:
|
8
|
-
docker-compose --file=docker-compose.dummy.yml up app
|
9
|
+
docker-compose --file=docker-compose.dummy.yml up -d app
|
10
|
+
docker attach marty_app_1
|
9
11
|
|
10
12
|
dummy-app-stop:
|
11
13
|
docker-compose --file=docker-compose.dummy.yml stop
|
data/marty.gemspec
CHANGED
@@ -33,7 +33,7 @@ Gem::Specification.new do |s|
|
|
33
33
|
|
34
34
|
s.add_dependency 'axlsx', '3.0.0pre'
|
35
35
|
|
36
|
-
s.add_dependency 'delorean_lang', '~> 0.6
|
36
|
+
s.add_dependency 'delorean_lang', '~> 0.6'
|
37
37
|
s.add_dependency 'mcfly', '~> 0.0.20'
|
38
38
|
|
39
39
|
s.add_dependency 'coderay'
|
@@ -46,5 +46,6 @@ Gem::Specification.new do |s|
|
|
46
46
|
s.add_dependency 'aws-sigv4', '~> 1.0', '>= 1.0.2'
|
47
47
|
|
48
48
|
s.add_dependency 'daemons', '~> 1.3.1'
|
49
|
+
s.add_dependency 'delayed_cron_job'
|
49
50
|
s.add_dependency 'delayed_job_active_record'
|
50
51
|
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
feature 'Background jobs schedule view', js: true do
|
4
|
+
before do
|
5
|
+
Delayed::Job.delete_all
|
6
|
+
populate_test_users
|
7
|
+
end
|
8
|
+
|
9
|
+
context 'as dev' do
|
10
|
+
before do
|
11
|
+
log_in_as('dev1')
|
12
|
+
wait_for_ajax
|
13
|
+
press('System')
|
14
|
+
press('Background Jobs')
|
15
|
+
press('Schedule Background Jobs')
|
16
|
+
wait_for_ajax
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'access denied' do
|
20
|
+
expect(page).to_not have_content 'Background Jobs Schedule'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'as admin' do
|
25
|
+
let(:schedule_view) { netzke_find('background_job_schedule_view') }
|
26
|
+
|
27
|
+
let!(:schedule) do
|
28
|
+
Marty::BackgroundJob::Schedule.create(
|
29
|
+
job_class: 'TestJob2',
|
30
|
+
cron: '0 0 * * *',
|
31
|
+
state: 'on'
|
32
|
+
).tap do |job|
|
33
|
+
Marty::BackgroundJob::UpdateSchedule.call(
|
34
|
+
id: job.id,
|
35
|
+
job_class: job.job_class
|
36
|
+
)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
before do
|
41
|
+
expect(TestJob2.scheduled?).to be true
|
42
|
+
|
43
|
+
log_in_as('admin1')
|
44
|
+
wait_for_ajax
|
45
|
+
press('System')
|
46
|
+
press('Background Jobs')
|
47
|
+
press('Schedule Background Jobs')
|
48
|
+
|
49
|
+
wait_for_ajax
|
50
|
+
|
51
|
+
expect(page).to have_content 'Background Jobs Schedule'
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'creates new schedule' do
|
55
|
+
expect(TestJob.scheduled?).to be false
|
56
|
+
|
57
|
+
press('Add')
|
58
|
+
|
59
|
+
fill_in('Job class', with: 'TestJob')
|
60
|
+
fill_in('cron', with: '1 1 * * *')
|
61
|
+
fill_in('state', with: 'on')
|
62
|
+
|
63
|
+
press 'OK'
|
64
|
+
wait_for_ajax
|
65
|
+
|
66
|
+
find('.x-tool-refresh').click
|
67
|
+
crons = schedule_view.get_col_vals('cron', 2, 0)
|
68
|
+
|
69
|
+
expect(crons).to include('1 1 * * *')
|
70
|
+
expect(crons).to include('0 0 * * *')
|
71
|
+
|
72
|
+
expect(TestJob.scheduled?).to be true
|
73
|
+
expect(TestJob.delayed_job.cron).to eq '1 1 * * *'
|
74
|
+
|
75
|
+
expect(TestJob2.scheduled?).to be true
|
76
|
+
expect(TestJob2.delayed_job.cron).to eq '0 0 * * *'
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'deletes schedule' do
|
80
|
+
find('.x-grid-item', text: 'TestJob2').click
|
81
|
+
press 'Delete'
|
82
|
+
press 'Yes'
|
83
|
+
|
84
|
+
wait_for_ajax
|
85
|
+
|
86
|
+
expect(TestJob2.scheduled?).to be false
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'turns the schedule off' do
|
90
|
+
find('.x-grid-item', text: 'TestJob2').click
|
91
|
+
press 'Edit'
|
92
|
+
fill_in('state', with: 'off')
|
93
|
+
|
94
|
+
press 'OK'
|
95
|
+
wait_for_ajax
|
96
|
+
expect(TestJob2.scheduled?).to be false
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'shows validation errors' do
|
100
|
+
press('Add')
|
101
|
+
|
102
|
+
fill_in('Job class', with: 'TestJob2')
|
103
|
+
fill_in('state', with: 'on')
|
104
|
+
fill_in('cron', with: '1')
|
105
|
+
|
106
|
+
press 'OK'
|
107
|
+
wait_for_ajax
|
108
|
+
expect(page).to have_content('Job class has already been taken')
|
109
|
+
expect(page).to have_content('Cron is invalid')
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'marty/background_job/schedule'
|
3
|
+
|
4
|
+
module Marty
|
5
|
+
module BackgroundJob
|
6
|
+
describe Schedule do
|
7
|
+
let(:subject) do
|
8
|
+
described_class.new(job_class: 'TestJob', cron: '* * * * *', state: 'on')
|
9
|
+
end
|
10
|
+
|
11
|
+
VALID_CRONS = [
|
12
|
+
'* * * * *',
|
13
|
+
'45 23 * * 6',
|
14
|
+
'0 7,17 * * *',
|
15
|
+
'0 17 * * 6',
|
16
|
+
'*/10 * * * *',
|
17
|
+
'30 10 * * *',
|
18
|
+
'0 * * * *',
|
19
|
+
'0 * * * *',
|
20
|
+
].freeze
|
21
|
+
|
22
|
+
INVALID_CRONS = [
|
23
|
+
'text 23 * * 6',
|
24
|
+
'1',
|
25
|
+
'* * *'
|
26
|
+
].freeze
|
27
|
+
|
28
|
+
it 'valid with valid cron expression' do
|
29
|
+
VALID_CRONS.each do |cron|
|
30
|
+
subject.cron = cron
|
31
|
+
expect(subject).to be_valid
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'invalid with valid cron expression' do
|
36
|
+
INVALID_CRONS.each do |cron|
|
37
|
+
subject.cron = cron
|
38
|
+
expect(subject).to_not be_valid
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -12,10 +12,20 @@ module Marty; module RSpec; module Chromedriver
|
|
12
12
|
pageLoadStrategy: 'none',
|
13
13
|
}
|
14
14
|
|
15
|
+
options = ::Selenium::WebDriver::Chrome::Options.new
|
16
|
+
|
17
|
+
# Add arguments to the driver using the Options interface
|
18
|
+
if opts[:args]
|
19
|
+
opts[:args].each do |arg|
|
20
|
+
options.add_argument("--#{arg}")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
15
24
|
caps = Selenium::WebDriver::Remote::Capabilities.chrome(copts)
|
16
25
|
driver = Capybara::Selenium::Driver.new(app,
|
17
26
|
browser: :chrome,
|
18
|
-
desired_capabilities: caps
|
27
|
+
desired_capabilities: caps,
|
28
|
+
options: options)
|
19
29
|
yield driver if block_given?
|
20
30
|
driver
|
21
31
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: marty
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arman Bostani
|
@@ -14,7 +14,7 @@ authors:
|
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
|
-
date: 2019-06-
|
17
|
+
date: 2019-06-12 00:00:00.000000000 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: pg
|
@@ -64,14 +64,14 @@ dependencies:
|
|
64
64
|
requirements:
|
65
65
|
- - "~>"
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version: 0.6
|
67
|
+
version: '0.6'
|
68
68
|
type: :runtime
|
69
69
|
prerelease: false
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
72
|
- - "~>"
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version: 0.6
|
74
|
+
version: '0.6'
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
76
|
name: mcfly
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -190,6 +190,20 @@ dependencies:
|
|
190
190
|
- - "~>"
|
191
191
|
- !ruby/object:Gem::Version
|
192
192
|
version: 1.3.1
|
193
|
+
- !ruby/object:Gem::Dependency
|
194
|
+
name: delayed_cron_job
|
195
|
+
requirement: !ruby/object:Gem::Requirement
|
196
|
+
requirements:
|
197
|
+
- - ">="
|
198
|
+
- !ruby/object:Gem::Version
|
199
|
+
version: '0'
|
200
|
+
type: :runtime
|
201
|
+
prerelease: false
|
202
|
+
version_requirements: !ruby/object:Gem::Requirement
|
203
|
+
requirements:
|
204
|
+
- - ">="
|
205
|
+
- !ruby/object:Gem::Version
|
206
|
+
version: '0'
|
193
207
|
- !ruby/object:Gem::Dependency
|
194
208
|
name: delayed_job_active_record
|
195
209
|
requirement: !ruby/object:Gem::Requirement
|
@@ -240,6 +254,7 @@ files:
|
|
240
254
|
- app/components/marty/api_log_view.rb
|
241
255
|
- app/components/marty/auth_app.rb
|
242
256
|
- app/components/marty/auth_app/client/auth_app.js
|
257
|
+
- app/components/marty/background_job_schedule_view.rb
|
243
258
|
- app/components/marty/base_rule_view.rb
|
244
259
|
- app/components/marty/config_view.rb
|
245
260
|
- app/components/marty/data_grid_view.rb
|
@@ -302,8 +317,11 @@ files:
|
|
302
317
|
- app/helpers/marty/application_helper.rb
|
303
318
|
- app/helpers/marty/enum_helper.rb
|
304
319
|
- app/helpers/marty/script_set.rb
|
320
|
+
- app/jobs/marty/cron_job.rb
|
305
321
|
- app/models/marty/api_auth.rb
|
306
322
|
- app/models/marty/api_config.rb
|
323
|
+
- app/models/marty/background_job.rb
|
324
|
+
- app/models/marty/background_job/schedule.rb
|
307
325
|
- app/models/marty/base.rb
|
308
326
|
- app/models/marty/base_rule.rb
|
309
327
|
- app/models/marty/config.rb
|
@@ -333,6 +351,8 @@ files:
|
|
333
351
|
- app/models/marty/user.rb
|
334
352
|
- app/models/marty/user_role.rb
|
335
353
|
- app/models/marty/vw_promise.rb
|
354
|
+
- app/services/marty/background_job/update_schedule.rb
|
355
|
+
- app/services/marty/jobs/schedule.rb
|
336
356
|
- app/services/marty/promises/delorean.rb
|
337
357
|
- app/services/marty/promises/delorean/create.rb
|
338
358
|
- app/services/marty/promises/ruby.rb
|
@@ -385,6 +405,8 @@ files:
|
|
385
405
|
- db/migrate/502_add_promise_type_enum.rb
|
386
406
|
- db/migrate/503_add_promise_type_to_promises.rb
|
387
407
|
- db/migrate/504_remove_plv8_extension.rb
|
408
|
+
- db/migrate/505_add_cron_to_delayed_jobs.rb
|
409
|
+
- db/migrate/506_create_marty_delayed_job_schedules.rb
|
388
410
|
- db/seeds.rb
|
389
411
|
- db/sql/lookup_grid_distinct_v1.sql
|
390
412
|
- db/sql/query_grid_dir_v1.sql
|
@@ -428,6 +450,7 @@ files:
|
|
428
450
|
- lib/pyxll/gemini.py
|
429
451
|
- lib/pyxll/pyxll.cfg
|
430
452
|
- lib/pyxll/sample.xlsx
|
453
|
+
- lib/tasks/marty_jobs.rake
|
431
454
|
- lib/tasks/marty_tasks.rake
|
432
455
|
- lib/tasks/scripts_tasks.rake
|
433
456
|
- make-dummy.mk
|
@@ -464,6 +487,8 @@ files:
|
|
464
487
|
- spec/dummy/app/controllers/application_controller.rb
|
465
488
|
- spec/dummy/app/controllers/components_controller.rb
|
466
489
|
- spec/dummy/app/helpers/application_helper.rb
|
490
|
+
- spec/dummy/app/jobs/test_job.rb
|
491
|
+
- spec/dummy/app/jobs/test_job2.rb
|
467
492
|
- spec/dummy/app/mailers/.gitkeep
|
468
493
|
- spec/dummy/app/models/.gitkeep
|
469
494
|
- spec/dummy/app/models/gemini/amortization_type.rb
|
@@ -1557,6 +1582,7 @@ files:
|
|
1557
1582
|
- spec/dummy/spec/features/javascripts
|
1558
1583
|
- spec/dummy/tmp/.gitkeep
|
1559
1584
|
- spec/features/auth_app_spec.rb
|
1585
|
+
- spec/features/background_job_schedule_spec.rb
|
1560
1586
|
- spec/features/data_import_spec.rb
|
1561
1587
|
- spec/features/endpoint_access.rb
|
1562
1588
|
- spec/features/enum_spec.rb
|
@@ -1592,6 +1618,7 @@ files:
|
|
1592
1618
|
- spec/lib/xl_spec.rb
|
1593
1619
|
- spec/lib/xl_styles_spec.rb
|
1594
1620
|
- spec/models/api_auth_spec.rb
|
1621
|
+
- spec/models/background_job/schedule.rb
|
1595
1622
|
- spec/models/config_spec.rb
|
1596
1623
|
- spec/models/data_grid_spec.rb
|
1597
1624
|
- spec/models/event_spec.rb
|