crono 1.1.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/LICENSE +2 -3
- data/Rakefile +3 -4
- data/app/assets/javascripts/crono/materialize.min.js +6 -0
- data/app/assets/stylesheets/crono/application.css +26 -0
- data/app/assets/stylesheets/crono/materialize.min.css +31 -0
- data/app/controllers/crono/application_controller.rb +5 -0
- data/app/controllers/crono/jobs_controller.rb +11 -0
- data/app/models/crono/application_record.rb +5 -0
- data/{lib/crono/orm/active_record → app/models/crono}/crono_job.rb +1 -2
- data/app/views/crono/jobs/index.html.erb +50 -0
- data/app/views/crono/jobs/show.html.erb +16 -0
- data/app/views/layouts/crono/application.html.erb +31 -0
- data/{exe → bin}/crono +0 -0
- data/config/routes.rb +4 -0
- data/lib/crono/cli.rb +3 -20
- data/lib/crono/config.rb +2 -3
- data/lib/crono/engine.rb +15 -0
- data/lib/crono/job.rb +10 -6
- data/lib/crono/performer_proxy.rb +2 -2
- data/lib/crono/period.rb +6 -5
- data/lib/crono/time_of_day.rb +2 -2
- data/lib/crono/version.rb +1 -1
- data/lib/crono.rb +3 -3
- data/lib/generators/crono/install/install_generator.rb +12 -1
- data/lib/generators/crono/install/templates/migrations/create_crono_jobs.rb +2 -6
- data/spec/assets/bad_cronotab.rb +12 -0
- data/spec/assets/good_cronotab.rb +9 -0
- data/spec/cli_spec.rb +109 -0
- data/spec/config_spec.rb +47 -0
- data/spec/crono_spec.rb +7 -0
- data/spec/cronotab_spec.rb +20 -0
- data/spec/internal/:memory +0 -0
- data/{log/.keep → spec/internal/app/assets/config/manifest.js} +0 -0
- data/spec/internal/app/controllers/application_controller.rb +3 -0
- data/spec/internal/app/controllers/pages_controller.rb +5 -0
- data/spec/internal/app/views/pages/index.html.erb +1 -0
- data/spec/internal/config/application.rb +22 -0
- data/spec/internal/config/boot.rb +5 -0
- data/spec/internal/config/database.yml +3 -0
- data/spec/internal/config/environment.rb +2 -0
- data/spec/internal/config/routes.rb +3 -0
- data/spec/internal/config/storage.yml +3 -0
- data/spec/internal/db/crono_test.sqlite +0 -0
- data/spec/internal/db/schema.rb +10 -0
- data/spec/internal/log/test.log +3868 -0
- data/{tmp/.gitkeep → spec/internal/public/favicon.ico} +0 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/-5/-5qRtN26mFn5ud6yyw5E5MpFhT61YcDJPMTlAoDLkEs.cache +2 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/-C/-C4fFLLfC1HB9flvtZbgPTj9oNiDtq1bvp8LPbnRv1k.cache +0 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/01/01tpm-y3svQKpsPvOHFWMxWBaG_35EVrgmnB5HKppZw.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/0K/0KEVKDTACcfyL6Fl5QZ6qSNOeswfd6FloUlWXQvwsHg.cache +0 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/1F/1FwwOzgRWJEUxIctLIsrhuh9z3QKl1XWDCcdfRhgKPk.cache +2 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/1n/1n5Wp1qC4BYhgEaXBnkRpO1N0oVAwLVdn47Ebk5nduY.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/22/22NEh4OGcNmK5Qh9ss73s622T6309DH8zv5ABF6-6Uk.cache +0 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/2n/2nEu77IGZHZPjlliLtJofREUZgmt-DGEhQnGIDMd0vA.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/2q/2qyBEUowJIKm_1EF_tbDWLjGDvVCbTjiHtRX_PEVn-U.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/3k/3khLNNSEoPg-2idoNmihX2Ba1loklzJsXvSRXujPaRk.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/7A/7A_YhyGyNk4Me5J0-p-XwK0qelTclb_2WX5pq0eY9dY.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/8d/8daZARHc9PDr5TZ5fqfR-_vJ5kCRzsZQKhQxFkrg_XI.cache +0 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/90/90vzKM32bOX3CR_IP7i2_AHgZSmn82XN_9gLyqidtUc.cache +2 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/9V/9V7dOKixQfEwAEIweL7rD4CUSL51MqiMeB67I5xhwXs.cache +0 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/9a/9aYqlHyIyZYckdfIJ3GbxrCRrsRgbc0wfZBCfd1lVWE.cache +0 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Ac/AcdbxQ2RjSGjrVJSdCjS-HN_RI3GZbW86dZGhSD8Ots.cache +0 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Cj/Cjzu7j1PyqHJD0alH5TiAYfJDN0Zbxhg4zFZegEzuYM.cache +3 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/DC/DC_euXbiKWPXx4qSkPGLNU4C2RIvjMBWliBrTgl6Mqo.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Db/DboywI_AoqjU7aQB5p90ZP76JW8sinmm4tMgjEG8Iu8.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Dz/DzN3uO_usT53JAsXp4Td8TcNu4kjXPgqTUbLJUG7220.cache +0 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/F3/F3BxEXMKcd4KO0HPnLrN1g6pJIJ_iQXCz9vW--uEixY.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/FE/FEVuJQTU_YF19u2IzUvuuYlUOoKsyk4JA9kX5UCIelU.cache +2 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/GG/GGT27f9SL2RsHpi8_pEJ1NHNgLBqDui3sDZOTgeD8z0.cache +0 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Gj/Gj2Go21wf2SZAnyJXKNSGfiGzYXAtrIdSHB2wuGrB6k.cache +0 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Hi/HicniSJ1JdM-SmZBY-KtuXL6pubtiugbtOJ-qF07hfk.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Hm/HmvhHkuG82Y4O19j_mfQOw9Q4VEq5hW1Ny0Pzh3gY00.cache +3 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Ic/IcQIS6wTKG3ZKN6foQYUMxNU4dNQRhrAdwVrAi8u11k.cache +0 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Kz/KzqcEtJH4QmChDeq7W5WHCOe_NOjqNrAWOzOI0b0RrU.cache +0 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/LE/LE5Is_h8o9DKajRisizRsovSfpVc8T-Z_xScq0YxBMg.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Mc/Mcvqw-yzpBv2GpUMmKfPZed-6wXUYd8rDdGJ12xAEsA.cache +0 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Nn/NneCOb3TsKS1FT6ImmBbFe5UuI_LxAmaYyk5o3st8jc.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Ro/RogqNsDfrMolvoqWLn8lCbweCzxIhN-fgXnLfBMFo8A.cache +0 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/T9/T9uigSdiu4wxaUieqeBq4uQYRdwGsT2acN15p0osfMU.cache +3 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/TH/THqp0Tr7zg3pz3WISBe0_u-QcPXHIesH0WlH_6zKzco.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/VF/VFaPzl3--nBqsNzvUgJUt2TjANPLzaelSx_eOc_J090.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/XG/XG0dD9kx-qBYVC-WwhzECOTsSICqvnAqLOCq1JWWrRI.cache +2 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/ZT/ZTJFqWngu6gOr5GuiqAV52YNHRuJeuwQelNDhtm8pKU.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/ZT/zT_x9gWE8eLO9s8Ul_dtwvAqzekg3DpeuSRkQepkKJ4.cache +2 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/aW/aWSe6QsJ8Dk7ZAuTOYgjegrAoC2XYQtCCeo9KVzVVQs.cache +2 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/at/ataSdIHBESkY5GN7sMG-XyOftCkIWDK0QaKEewVkqIU.cache +2 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/au/aukwvh3eZhFFGyc5qZWT9KMJQHxFrTDEqfjXr4VM4dc.cache +3 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/bu/bu6XdfzbXfiTnSQ_6Shml3tpB7ovoUAcuCGNs-eYehI.cache +3 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/c2/c2yubRDZmdi6tFc__QitGtUTkpKt0Goc7FNKhRNw0Uk.cache +2 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/fu/fuVeiMpLNyElLwjOR6EBQP7-ZUwuJTsQe_Ie11TlX7Y.cache +3 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/hY/hY9drCAzyxN-KBhXav5VLmk4-AFlKT2yguKNLm7wGsA.cache +3 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/hg/hgkvHB4OV3E0Gq-Ud_lH2ljTzyb-8nGquMAFTBr4O0o.cache +2 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/jV/jVXcSpsjtyBHtJaFkxwLVcVm79OT5CVEA9XuzV01O2o.cache +2 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/kK/kKAy2xIb8ozBaCVqr7LkIsO3-78l5U08uq1Ot7JvES0.cache +0 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/kU/kUed8S8DBmWvnTdMtg0PzTYj51Rbq9R9yfr6bhPzp2I.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/kw/kwNFhW24nxXy_HfVKYdXJyRqhu7ljgl9wR2DcJUo-nA.cache +3 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/ls/ls-nV5B50MgpIYfcYZWWWjiNsU2tD2DrEbiiEmGtArk.cache +0 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/m4/m47fbWgjCvvfU0XLMaGJE1zb9zh2STuMZFp7umYjLTA.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/m_/m_VPZpr_Dhvko_jzP2-4VRhDpknOtciX8pqAq3jY4P8.cache +3 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/n5/n5rslESPawJxj7Ii3QNWxFl-2sUJE4leiEyzbuFE9Mc.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/nz/nzkJWHKhKCtwI9w3TBcwyGzKEik4UFYwulf2jO7xPXc.cache +2 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/o4/o42lMuA3eKF-eY5RsJO4kHIGfba2QHOCO0b9rz5iNIU.cache +0 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/oF/oFrXjOEKX9hseSPY19vWwGHfET4QpdjGD5UdFIEN8mo.cache +0 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/od/od3K7nGVNq7YsrTVF7ItWWkHs8F_XEGn_BlCD5wW_gc.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/qo/qoEv51qzi0h4mpNP5B4vQydW2FmhC_vbbx6vWJ99Jls.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/tQ/tQ-nAfm23F-ckwkWPuftbJS6tumDQhNxQgPIZSrfPM0.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/tr/trn1zjMZoBOIgSYgI84OzddhfICB2KnU4XbV8axLVGo.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/u3/u3VRW5zPBM7BcNRi3G4B8M6CdscKSLJ3xYmp44ekmjU.cache +0 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/uG/UgcLSZ8AKbE1AYf75cSUXI6uefPECNfBcVQ7L0BDzHg.cache +3 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/uG/uGhNDzX7DxymN3xqHLHTndSae3bN0A-MlTk05m6wV4A.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/wF/wFT7zoeQQwz-V8syWaS01xr7xgZWr3UNQLWbYSKXirw.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/wN/wNw4kAG0E_RrvLeFAizMmTp_0jh-HGw1ONLtRyw92z0.cache +2 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/x-/x-qCUFpNxK1jTHH2qV_VgVk_KrGKdHzNGOnDMVFstuQ.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/yk/ykU9I1MzGh7clO4pu853ZKl4LtMlDtyr8BjpiozFQ8E.cache +2 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/yk/ykWLbyEuqa0JHcwHJ-SdVxv4ImwnymlVxvbPKtk6HUM.cache +1 -0
- data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/zO/zOr1jCikukgv8-bNHvK43vGLa3CSjtmiwf2K7dUjTnw.cache +0 -0
- data/spec/job_spec.rb +183 -0
- data/spec/models/crono/crono_job_spec.rb +31 -0
- data/spec/performer_proxy_spec.rb +39 -0
- data/spec/period_spec.rb +141 -0
- data/spec/rails_helper.rb +89 -0
- data/spec/scheduler_spec.rb +62 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/tasks/crono_tasks_spec.rb +23 -0
- data/spec/web_spec.rb +61 -0
- metadata +233 -68
- data/.gitignore +0 -10
- data/.rspec +0 -2
- data/.travis.yml +0 -14
- data/Changes.md +0 -88
- data/Gemfile +0 -4
- data/Gemfile.lock +0 -78
- data/NOTICE +0 -2
- data/README.md +0 -218
- data/bin/console +0 -14
- data/bin/setup +0 -7
- data/crono.gemspec +0 -34
- data/examples/crono_web_ui.png +0 -0
- data/examples/cronotab.rb +0 -14
- data/examples/monitrc.conf +0 -6
- data/lib/crono/web.rb +0 -22
- data/web/assets/css/custom.css +0 -19
- data/web/assets/css/materialize.min.css +0 -16
- data/web/assets/font/material-design-icons/LICENSE.txt +0 -428
- data/web/assets/font/material-design-icons/Material-Design-Icons.eot +0 -0
- data/web/assets/font/material-design-icons/Material-Design-Icons.svg +0 -751
- data/web/assets/font/material-design-icons/Material-Design-Icons.ttf +0 -0
- data/web/assets/font/material-design-icons/Material-Design-Icons.woff +0 -0
- data/web/assets/font/material-design-icons/Material-Design-Icons.woff2 +0 -0
- data/web/assets/font/roboto/Roboto-Bold.ttf +0 -0
- data/web/assets/font/roboto/Roboto-Bold.woff +0 -0
- data/web/assets/font/roboto/Roboto-Bold.woff2 +0 -0
- data/web/assets/font/roboto/Roboto-Light.ttf +0 -0
- data/web/assets/font/roboto/Roboto-Light.woff +0 -0
- data/web/assets/font/roboto/Roboto-Light.woff2 +0 -0
- data/web/assets/font/roboto/Roboto-Medium.ttf +0 -0
- data/web/assets/font/roboto/Roboto-Medium.woff +0 -0
- data/web/assets/font/roboto/Roboto-Medium.woff2 +0 -0
- data/web/assets/font/roboto/Roboto-Regular.ttf +0 -0
- data/web/assets/font/roboto/Roboto-Regular.woff +0 -0
- data/web/assets/font/roboto/Roboto-Regular.woff2 +0 -0
- data/web/assets/font/roboto/Roboto-Thin.ttf +0 -0
- data/web/assets/font/roboto/Roboto-Thin.woff +0 -0
- data/web/assets/font/roboto/Roboto-Thin.woff2 +0 -0
- data/web/assets/js/jquery-2.1.3.min.js +0 -4
- data/web/assets/js/materialize.min.js +0 -10
- data/web/views/dashboard.haml +0 -36
- data/web/views/job.haml +0 -15
- data/web/views/layout.haml +0 -29
data/lib/crono/job.rb
CHANGED
@@ -12,7 +12,7 @@ module Crono
|
|
12
12
|
def initialize(performer, period, job_args, job_options = nil)
|
13
13
|
self.execution_interval = 0.minutes
|
14
14
|
self.performer, self.period = performer, period
|
15
|
-
self.job_args = JSON.generate(job_args)
|
15
|
+
self.job_args = JSON.generate(job_args)
|
16
16
|
self.job_log = StringIO.new
|
17
17
|
self.job_logger = Logger.new(job_log)
|
18
18
|
self.job_options = job_options || {}
|
@@ -22,7 +22,7 @@ module Crono
|
|
22
22
|
|
23
23
|
def next
|
24
24
|
return next_performed_at if next_performed_at.future?
|
25
|
-
Time.now
|
25
|
+
Time.zone.now
|
26
26
|
end
|
27
27
|
|
28
28
|
def description
|
@@ -37,7 +37,7 @@ module Crono
|
|
37
37
|
return Thread.new {} if perform_before_interval?
|
38
38
|
|
39
39
|
log "Perform #{performer}"
|
40
|
-
self.last_performed_at = Time.now
|
40
|
+
self.last_performed_at = Time.zone.now
|
41
41
|
self.next_performed_at = period.next(since: last_performed_at)
|
42
42
|
|
43
43
|
Thread.new { perform_job }
|
@@ -76,7 +76,11 @@ module Crono
|
|
76
76
|
end
|
77
77
|
|
78
78
|
def perform_job
|
79
|
-
|
79
|
+
if job_args
|
80
|
+
performer.new.perform(JSON.parse(job_args))
|
81
|
+
else
|
82
|
+
performer.new.perform
|
83
|
+
end
|
80
84
|
rescue StandardError => e
|
81
85
|
handle_job_fail(e)
|
82
86
|
else
|
@@ -86,7 +90,7 @@ module Crono
|
|
86
90
|
end
|
87
91
|
|
88
92
|
def handle_job_fail(exception)
|
89
|
-
finished_time_sec = format('%.2f', Time.now - last_performed_at)
|
93
|
+
finished_time_sec = format('%.2f', Time.zone.now - last_performed_at)
|
90
94
|
self.healthy = false
|
91
95
|
log_error "Finished #{performer} in #{finished_time_sec} seconds"\
|
92
96
|
" with error: #{exception.message}"
|
@@ -94,7 +98,7 @@ module Crono
|
|
94
98
|
end
|
95
99
|
|
96
100
|
def handle_job_success
|
97
|
-
finished_time_sec = format('%.2f', Time.now - last_performed_at)
|
101
|
+
finished_time_sec = format('%.2f', Time.zone.now - last_performed_at)
|
98
102
|
self.healthy = true
|
99
103
|
log "Finished #{performer} in #{finished_time_sec} seconds"
|
100
104
|
end
|
@@ -7,8 +7,8 @@ module Crono
|
|
7
7
|
@job_args = job_args
|
8
8
|
end
|
9
9
|
|
10
|
-
def every(period,
|
11
|
-
@job = Job.new(@performer, Period.new(period,
|
10
|
+
def every(period, **options)
|
11
|
+
@job = Job.new(@performer, Period.new(period, **options), @job_args, @options)
|
12
12
|
@scheduler.add_job(@job)
|
13
13
|
self
|
14
14
|
end
|
data/lib/crono/period.rb
CHANGED
@@ -27,7 +27,7 @@ module Crono
|
|
27
27
|
@next = @next.beginning_of_week.advance(days: @on) if @on
|
28
28
|
@next = @next.change(time_atts)
|
29
29
|
return @next if @next.future?
|
30
|
-
Time.now
|
30
|
+
Time.zone.now
|
31
31
|
end
|
32
32
|
|
33
33
|
def description
|
@@ -47,8 +47,8 @@ module Crono
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def initial_day
|
50
|
-
return Time.now unless @on
|
51
|
-
day = Time.now.beginning_of_week.advance(days: @on)
|
50
|
+
return Time.zone.now unless @on
|
51
|
+
day = Time.zone.now.beginning_of_week.advance(days: @on)
|
52
52
|
day = day.change(time_atts)
|
53
53
|
return day if day.future?
|
54
54
|
@period.from_now.beginning_of_week.advance(days: @on)
|
@@ -68,7 +68,7 @@ module Crono
|
|
68
68
|
|
69
69
|
case at
|
70
70
|
when String
|
71
|
-
time = Time.parse(at)
|
71
|
+
time = Time.zone.parse(at)
|
72
72
|
return time.hour, time.min
|
73
73
|
when Hash
|
74
74
|
return at[:hour], at[:min]
|
@@ -78,7 +78,8 @@ module Crono
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def time_atts
|
81
|
-
{ hour: @at_hour, min: @at_min }
|
81
|
+
atts = { hour: @at_hour, min: @at_min }
|
82
|
+
atts.respond_to?(:compact) ? atts.compact : atts.select { |_, value| !value.nil? }
|
82
83
|
end
|
83
84
|
end
|
84
85
|
end
|
data/lib/crono/time_of_day.rb
CHANGED
@@ -8,8 +8,8 @@ module Crono
|
|
8
8
|
def self.parse(value)
|
9
9
|
time =
|
10
10
|
case value
|
11
|
-
when String then Time.parse(value).utc
|
12
|
-
when Hash then Time.now.change(value).utc
|
11
|
+
when String then Time.zone.parse(value).utc
|
12
|
+
when Hash then Time.zone.now.change(value).utc
|
13
13
|
when Time then value.utc
|
14
14
|
else
|
15
15
|
fail "Unknown TimeOfDay format: #{value.inspect}"
|
data/lib/crono/version.rb
CHANGED
data/lib/crono.rb
CHANGED
@@ -2,8 +2,11 @@
|
|
2
2
|
module Crono
|
3
3
|
end
|
4
4
|
|
5
|
+
require 'rails'
|
6
|
+
require 'sprockets/railtie'
|
5
7
|
require 'active_support/all'
|
6
8
|
require 'crono/version'
|
9
|
+
require 'crono/engine'
|
7
10
|
require 'crono/logging'
|
8
11
|
require 'crono/period'
|
9
12
|
require 'crono/time_of_day'
|
@@ -13,7 +16,4 @@ require 'crono/scheduler'
|
|
13
16
|
require 'crono/config'
|
14
17
|
require 'crono/performer_proxy'
|
15
18
|
require 'crono/cronotab'
|
16
|
-
require 'crono/orm/active_record/crono_job'
|
17
19
|
require 'crono/railtie' if defined?(Rails)
|
18
|
-
|
19
|
-
Crono.autoload :Web, 'crono/web'
|
@@ -21,7 +21,18 @@ module Crono
|
|
21
21
|
|
22
22
|
def create_migrations
|
23
23
|
migration_template 'migrations/create_crono_jobs.rb',
|
24
|
-
'db/migrate/create_crono_jobs.rb'
|
24
|
+
'db/migrate/create_crono_jobs.rb',
|
25
|
+
migration_version: migration_version
|
26
|
+
end
|
27
|
+
|
28
|
+
def rails5?
|
29
|
+
Rails.version.start_with? '5'
|
30
|
+
end
|
31
|
+
|
32
|
+
def migration_version
|
33
|
+
if rails5?
|
34
|
+
"[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
|
35
|
+
end
|
25
36
|
end
|
26
37
|
end
|
27
38
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
class CreateCronoJobs < ActiveRecord::Migration
|
2
|
-
def
|
1
|
+
class CreateCronoJobs < ActiveRecord::Migration[6.1]
|
2
|
+
def change
|
3
3
|
create_table :crono_jobs do |t|
|
4
4
|
t.string :job_id, null: false
|
5
5
|
t.text :log, limit: 1073741823 # LONGTEXT for MySQL
|
@@ -9,8 +9,4 @@ class CreateCronoJobs < ActiveRecord::Migration
|
|
9
9
|
end
|
10
10
|
add_index :crono_jobs, [:job_id], unique: true
|
11
11
|
end
|
12
|
-
|
13
|
-
def self.down
|
14
|
-
drop_table :crono_jobs
|
15
|
-
end
|
16
12
|
end
|
data/spec/cli_spec.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'crono/cli'
|
3
|
+
|
4
|
+
describe Crono::CLI do
|
5
|
+
let(:cli) { Crono::CLI.instance }
|
6
|
+
|
7
|
+
describe '#run' do
|
8
|
+
it 'should initialize rails with #load_rails and start working loop' do
|
9
|
+
expect(cli).to receive(:load_rails)
|
10
|
+
expect(cli).to receive(:have_jobs?).and_return(true)
|
11
|
+
expect(cli).to receive(:start_working_loop)
|
12
|
+
expect(cli).to receive(:parse_options)
|
13
|
+
expect(cli).to receive(:parse_command)
|
14
|
+
expect(cli).to receive(:write_pid)
|
15
|
+
expect(Crono::Cronotab).to receive(:process)
|
16
|
+
cli.run
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'should run as daemon' do
|
20
|
+
before { cli.config.daemonize = true }
|
21
|
+
|
22
|
+
it 'should initialize rails with #load_rails and start working loop' do
|
23
|
+
expect(cli).to receive(:load_rails)
|
24
|
+
expect(cli).to receive(:have_jobs?).and_return(true)
|
25
|
+
expect(cli).to receive(:start_working_loop_in_daemon)
|
26
|
+
expect(cli).to receive(:parse_options)
|
27
|
+
expect(cli).to receive(:parse_command)
|
28
|
+
expect(cli).not_to receive(:write_pid)
|
29
|
+
expect(Crono::Cronotab).to receive(:process)
|
30
|
+
cli.run
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#parse_options' do
|
36
|
+
it 'should set cronotab' do
|
37
|
+
cli.send(:parse_options, ['--cronotab', '/tmp/cronotab.rb'])
|
38
|
+
expect(cli.config.cronotab).to be_eql '/tmp/cronotab.rb'
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should set logfile' do
|
42
|
+
cli.send(:parse_options, ['--logfile', 'log/crono.log'])
|
43
|
+
expect(cli.config.logfile).to be_eql 'log/crono.log'
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should set pidfile' do
|
47
|
+
cli.send(:parse_options, ['--pidfile', 'tmp/pids/crono.0.log'])
|
48
|
+
expect(cli.config.pidfile).to be_eql 'tmp/pids/crono.0.log'
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should set piddir' do
|
52
|
+
cli.send(:parse_options, ['--piddir', 'tmp/pids'])
|
53
|
+
expect(cli.config.piddir).to be_eql 'tmp/pids'
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should set process_name' do
|
57
|
+
cli.send(:parse_options, ['--process_name', 'crono0'])
|
58
|
+
expect(cli.config.process_name).to be_eql 'crono0'
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should set monitor' do
|
62
|
+
cli.send(:parse_options, ['--monitor'])
|
63
|
+
expect(cli.config.monitor).to be true
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should set environment' do
|
67
|
+
cli.send(:parse_options, ['--environment', 'production'])
|
68
|
+
expect(cli.config.environment).to be_eql('production')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#parse_command' do
|
73
|
+
|
74
|
+
it 'should set daemonize on start' do
|
75
|
+
cli.send(:parse_command, ['start'])
|
76
|
+
expect(cli.config.daemonize).to be true
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should set daemonize on stop' do
|
80
|
+
cli.send(:parse_command, ['stop'])
|
81
|
+
expect(cli.config.daemonize).to be true
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should set daemonize on restart' do
|
85
|
+
cli.send(:parse_command, ['restart'])
|
86
|
+
expect(cli.config.daemonize).to be true
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should set daemonize on run' do
|
90
|
+
cli.send(:parse_command, ['run'])
|
91
|
+
expect(cli.config.daemonize).to be true
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'should set daemonize on zap' do
|
95
|
+
cli.send(:parse_command, ['zap'])
|
96
|
+
expect(cli.config.daemonize).to be true
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should set daemonize on reload' do
|
100
|
+
cli.send(:parse_command, ['reload'])
|
101
|
+
expect(cli.config.daemonize).to be true
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should set daemonize on status' do
|
105
|
+
cli.send(:parse_command, ['status'])
|
106
|
+
expect(cli.config.daemonize).to be true
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/spec/config_spec.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Crono::Config do
|
4
|
+
let(:config) { Crono::Config.new }
|
5
|
+
describe '#initialize' do
|
6
|
+
it 'should initialize with default configuration options' do
|
7
|
+
ENV['RAILS_ENV'] = 'test'
|
8
|
+
@config = Crono::Config.new
|
9
|
+
expect(@config.cronotab).to be Crono::Config::CRONOTAB
|
10
|
+
expect(@config.logfile).to be Crono::Config::LOGFILE
|
11
|
+
expect(@config.piddir).to be Crono::Config::PIDDIR
|
12
|
+
expect(@config.process_name).to be Crono::Config::PROCESS_NAME
|
13
|
+
expect(@config.daemonize).to be false
|
14
|
+
expect(@config.monitor).to be false
|
15
|
+
expect(@config.environment).to be_eql ENV['RAILS_ENV']
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#pidfile" do
|
19
|
+
subject(:pidfile) { config.pidfile }
|
20
|
+
|
21
|
+
context "not explicity configured" do
|
22
|
+
context "daemonize is false" do
|
23
|
+
before { config.daemonize = false }
|
24
|
+
|
25
|
+
specify { expect(pidfile).to be_nil }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "explicity configured" do
|
30
|
+
let(:path) { "foo/bar/pid.pid" }
|
31
|
+
|
32
|
+
before { config.pidfile = path }
|
33
|
+
|
34
|
+
specify { expect(pidfile).to eq path }
|
35
|
+
|
36
|
+
it "trys to set piddir" do
|
37
|
+
expect(config.piddir).to eq "foo/bar"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "trys to set process_name" do
|
41
|
+
expect(config.process_name).to eq "pid"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/spec/crono_spec.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Crono::Cronotab do
|
4
|
+
describe '#process' do
|
5
|
+
it 'should load cronotab file' do
|
6
|
+
cronotab_path = File.expand_path('../assets/good_cronotab.rb', __FILE__)
|
7
|
+
expect(Crono.scheduler).to receive(:add_job).with(kind_of(Crono::Job))
|
8
|
+
expect {
|
9
|
+
Crono::Cronotab.process(cronotab_path)
|
10
|
+
}.to_not raise_error
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should raise error when cronotab is invalid' do
|
14
|
+
cronotab_path = File.expand_path('../assets/bad_cronotab.rb', __FILE__)
|
15
|
+
expect {
|
16
|
+
Crono::Cronotab.process(cronotab_path)
|
17
|
+
}.to raise_error
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
Binary file
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
<p>Hello World</p>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative 'boot'
|
2
|
+
|
3
|
+
require 'rails/all'
|
4
|
+
|
5
|
+
# Require the gems listed in Gemfile, including any gems
|
6
|
+
# you've limited to :test, :development, or :production.
|
7
|
+
Bundler.require(*Rails.groups)
|
8
|
+
require 'crono'
|
9
|
+
|
10
|
+
module Dummy
|
11
|
+
class Application < Rails::Application
|
12
|
+
config.load_defaults Rails::VERSION::STRING.to_f
|
13
|
+
|
14
|
+
# Configuration for the application, engines, and railties goes here.
|
15
|
+
#
|
16
|
+
# These settings can be overridden in specific environments using the files
|
17
|
+
# in config/environments, which are processed later.
|
18
|
+
#
|
19
|
+
# config.time_zone = "Central Time (US & Canada)"
|
20
|
+
# config.eager_load_paths << Rails.root.join("extras")
|
21
|
+
end
|
22
|
+
end
|
Binary file
|
@@ -0,0 +1,10 @@
|
|
1
|
+
ActiveRecord::Schema.define do
|
2
|
+
create_table :crono_jobs do |t|
|
3
|
+
t.string :job_id, null: false
|
4
|
+
t.text :log, limit: 1_073_741_823 # LONGTEXT for MySQL
|
5
|
+
t.datetime :last_performed_at
|
6
|
+
t.boolean :healthy
|
7
|
+
t.timestamps null: false
|
8
|
+
end
|
9
|
+
add_index :crono_jobs, [:job_id], unique: true
|
10
|
+
end
|