crono 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (170) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE +2 -3
  3. data/Rakefile +3 -4
  4. data/app/assets/javascripts/crono/materialize.min.js +6 -0
  5. data/app/assets/stylesheets/crono/application.css +26 -0
  6. data/app/assets/stylesheets/crono/materialize.min.css +31 -0
  7. data/app/controllers/crono/application_controller.rb +5 -0
  8. data/app/controllers/crono/jobs_controller.rb +11 -0
  9. data/app/models/crono/application_record.rb +5 -0
  10. data/{lib/crono/orm/active_record → app/models/crono}/crono_job.rb +1 -2
  11. data/app/views/crono/jobs/index.html.erb +50 -0
  12. data/app/views/crono/jobs/show.html.erb +16 -0
  13. data/app/views/layouts/crono/application.html.erb +31 -0
  14. data/{exe → bin}/crono +0 -0
  15. data/config/routes.rb +4 -0
  16. data/lib/crono/cli.rb +3 -20
  17. data/lib/crono/config.rb +2 -3
  18. data/lib/crono/engine.rb +15 -0
  19. data/lib/crono/job.rb +12 -8
  20. data/lib/crono/performer_proxy.rb +2 -2
  21. data/lib/crono/period.rb +6 -5
  22. data/lib/crono/time_of_day.rb +2 -2
  23. data/lib/crono/version.rb +1 -1
  24. data/lib/crono.rb +3 -3
  25. data/lib/generators/crono/install/install_generator.rb +12 -1
  26. data/lib/generators/crono/install/templates/migrations/create_crono_jobs.rb +3 -7
  27. data/spec/assets/bad_cronotab.rb +12 -0
  28. data/spec/assets/good_cronotab.rb +9 -0
  29. data/spec/cli_spec.rb +109 -0
  30. data/spec/config_spec.rb +47 -0
  31. data/spec/crono_spec.rb +7 -0
  32. data/spec/cronotab_spec.rb +20 -0
  33. data/spec/internal/:memory +0 -0
  34. data/{log/.keep → spec/internal/app/assets/config/manifest.js} +0 -0
  35. data/spec/internal/app/controllers/application_controller.rb +3 -0
  36. data/spec/internal/app/controllers/pages_controller.rb +5 -0
  37. data/spec/internal/app/views/pages/index.html.erb +1 -0
  38. data/spec/internal/config/application.rb +22 -0
  39. data/spec/internal/config/boot.rb +5 -0
  40. data/spec/internal/config/database.yml +3 -0
  41. data/spec/internal/config/environment.rb +2 -0
  42. data/spec/internal/config/routes.rb +3 -0
  43. data/spec/internal/config/storage.yml +3 -0
  44. data/spec/internal/db/crono_test.sqlite +0 -0
  45. data/spec/internal/db/schema.rb +10 -0
  46. data/spec/internal/log/test.log +3868 -0
  47. data/{tmp/.gitkeep → spec/internal/public/favicon.ico} +0 -0
  48. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/-5/-5qRtN26mFn5ud6yyw5E5MpFhT61YcDJPMTlAoDLkEs.cache +2 -0
  49. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/-C/-C4fFLLfC1HB9flvtZbgPTj9oNiDtq1bvp8LPbnRv1k.cache +0 -0
  50. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/01/01tpm-y3svQKpsPvOHFWMxWBaG_35EVrgmnB5HKppZw.cache +1 -0
  51. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/0K/0KEVKDTACcfyL6Fl5QZ6qSNOeswfd6FloUlWXQvwsHg.cache +0 -0
  52. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/1F/1FwwOzgRWJEUxIctLIsrhuh9z3QKl1XWDCcdfRhgKPk.cache +2 -0
  53. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/1n/1n5Wp1qC4BYhgEaXBnkRpO1N0oVAwLVdn47Ebk5nduY.cache +1 -0
  54. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/22/22NEh4OGcNmK5Qh9ss73s622T6309DH8zv5ABF6-6Uk.cache +0 -0
  55. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/2n/2nEu77IGZHZPjlliLtJofREUZgmt-DGEhQnGIDMd0vA.cache +1 -0
  56. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/2q/2qyBEUowJIKm_1EF_tbDWLjGDvVCbTjiHtRX_PEVn-U.cache +1 -0
  57. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/3k/3khLNNSEoPg-2idoNmihX2Ba1loklzJsXvSRXujPaRk.cache +1 -0
  58. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/7A/7A_YhyGyNk4Me5J0-p-XwK0qelTclb_2WX5pq0eY9dY.cache +1 -0
  59. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/8d/8daZARHc9PDr5TZ5fqfR-_vJ5kCRzsZQKhQxFkrg_XI.cache +0 -0
  60. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/90/90vzKM32bOX3CR_IP7i2_AHgZSmn82XN_9gLyqidtUc.cache +2 -0
  61. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/9V/9V7dOKixQfEwAEIweL7rD4CUSL51MqiMeB67I5xhwXs.cache +0 -0
  62. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/9a/9aYqlHyIyZYckdfIJ3GbxrCRrsRgbc0wfZBCfd1lVWE.cache +0 -0
  63. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Ac/AcdbxQ2RjSGjrVJSdCjS-HN_RI3GZbW86dZGhSD8Ots.cache +0 -0
  64. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Cj/Cjzu7j1PyqHJD0alH5TiAYfJDN0Zbxhg4zFZegEzuYM.cache +3 -0
  65. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/DC/DC_euXbiKWPXx4qSkPGLNU4C2RIvjMBWliBrTgl6Mqo.cache +1 -0
  66. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Db/DboywI_AoqjU7aQB5p90ZP76JW8sinmm4tMgjEG8Iu8.cache +1 -0
  67. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Dz/DzN3uO_usT53JAsXp4Td8TcNu4kjXPgqTUbLJUG7220.cache +0 -0
  68. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/F3/F3BxEXMKcd4KO0HPnLrN1g6pJIJ_iQXCz9vW--uEixY.cache +1 -0
  69. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/FE/FEVuJQTU_YF19u2IzUvuuYlUOoKsyk4JA9kX5UCIelU.cache +2 -0
  70. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/GG/GGT27f9SL2RsHpi8_pEJ1NHNgLBqDui3sDZOTgeD8z0.cache +0 -0
  71. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Gj/Gj2Go21wf2SZAnyJXKNSGfiGzYXAtrIdSHB2wuGrB6k.cache +0 -0
  72. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Hi/HicniSJ1JdM-SmZBY-KtuXL6pubtiugbtOJ-qF07hfk.cache +1 -0
  73. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Hm/HmvhHkuG82Y4O19j_mfQOw9Q4VEq5hW1Ny0Pzh3gY00.cache +3 -0
  74. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Ic/IcQIS6wTKG3ZKN6foQYUMxNU4dNQRhrAdwVrAi8u11k.cache +0 -0
  75. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Kz/KzqcEtJH4QmChDeq7W5WHCOe_NOjqNrAWOzOI0b0RrU.cache +0 -0
  76. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/LE/LE5Is_h8o9DKajRisizRsovSfpVc8T-Z_xScq0YxBMg.cache +1 -0
  77. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Mc/Mcvqw-yzpBv2GpUMmKfPZed-6wXUYd8rDdGJ12xAEsA.cache +0 -0
  78. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Nn/NneCOb3TsKS1FT6ImmBbFe5UuI_LxAmaYyk5o3st8jc.cache +1 -0
  79. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/Ro/RogqNsDfrMolvoqWLn8lCbweCzxIhN-fgXnLfBMFo8A.cache +0 -0
  80. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/T9/T9uigSdiu4wxaUieqeBq4uQYRdwGsT2acN15p0osfMU.cache +3 -0
  81. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/TH/THqp0Tr7zg3pz3WISBe0_u-QcPXHIesH0WlH_6zKzco.cache +1 -0
  82. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/VF/VFaPzl3--nBqsNzvUgJUt2TjANPLzaelSx_eOc_J090.cache +1 -0
  83. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/XG/XG0dD9kx-qBYVC-WwhzECOTsSICqvnAqLOCq1JWWrRI.cache +2 -0
  84. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/ZT/ZTJFqWngu6gOr5GuiqAV52YNHRuJeuwQelNDhtm8pKU.cache +1 -0
  85. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/ZT/zT_x9gWE8eLO9s8Ul_dtwvAqzekg3DpeuSRkQepkKJ4.cache +2 -0
  86. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/aW/aWSe6QsJ8Dk7ZAuTOYgjegrAoC2XYQtCCeo9KVzVVQs.cache +2 -0
  87. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/at/ataSdIHBESkY5GN7sMG-XyOftCkIWDK0QaKEewVkqIU.cache +2 -0
  88. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/au/aukwvh3eZhFFGyc5qZWT9KMJQHxFrTDEqfjXr4VM4dc.cache +3 -0
  89. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/bu/bu6XdfzbXfiTnSQ_6Shml3tpB7ovoUAcuCGNs-eYehI.cache +3 -0
  90. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/c2/c2yubRDZmdi6tFc__QitGtUTkpKt0Goc7FNKhRNw0Uk.cache +2 -0
  91. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/fu/fuVeiMpLNyElLwjOR6EBQP7-ZUwuJTsQe_Ie11TlX7Y.cache +3 -0
  92. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/hY/hY9drCAzyxN-KBhXav5VLmk4-AFlKT2yguKNLm7wGsA.cache +3 -0
  93. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/hg/hgkvHB4OV3E0Gq-Ud_lH2ljTzyb-8nGquMAFTBr4O0o.cache +2 -0
  94. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/jV/jVXcSpsjtyBHtJaFkxwLVcVm79OT5CVEA9XuzV01O2o.cache +2 -0
  95. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/kK/kKAy2xIb8ozBaCVqr7LkIsO3-78l5U08uq1Ot7JvES0.cache +0 -0
  96. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/kU/kUed8S8DBmWvnTdMtg0PzTYj51Rbq9R9yfr6bhPzp2I.cache +1 -0
  97. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/kw/kwNFhW24nxXy_HfVKYdXJyRqhu7ljgl9wR2DcJUo-nA.cache +3 -0
  98. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/ls/ls-nV5B50MgpIYfcYZWWWjiNsU2tD2DrEbiiEmGtArk.cache +0 -0
  99. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/m4/m47fbWgjCvvfU0XLMaGJE1zb9zh2STuMZFp7umYjLTA.cache +1 -0
  100. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/m_/m_VPZpr_Dhvko_jzP2-4VRhDpknOtciX8pqAq3jY4P8.cache +3 -0
  101. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/n5/n5rslESPawJxj7Ii3QNWxFl-2sUJE4leiEyzbuFE9Mc.cache +1 -0
  102. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/nz/nzkJWHKhKCtwI9w3TBcwyGzKEik4UFYwulf2jO7xPXc.cache +2 -0
  103. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/o4/o42lMuA3eKF-eY5RsJO4kHIGfba2QHOCO0b9rz5iNIU.cache +0 -0
  104. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/oF/oFrXjOEKX9hseSPY19vWwGHfET4QpdjGD5UdFIEN8mo.cache +0 -0
  105. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/od/od3K7nGVNq7YsrTVF7ItWWkHs8F_XEGn_BlCD5wW_gc.cache +1 -0
  106. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/qo/qoEv51qzi0h4mpNP5B4vQydW2FmhC_vbbx6vWJ99Jls.cache +1 -0
  107. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/tQ/tQ-nAfm23F-ckwkWPuftbJS6tumDQhNxQgPIZSrfPM0.cache +1 -0
  108. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/tr/trn1zjMZoBOIgSYgI84OzddhfICB2KnU4XbV8axLVGo.cache +1 -0
  109. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/u3/u3VRW5zPBM7BcNRi3G4B8M6CdscKSLJ3xYmp44ekmjU.cache +0 -0
  110. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/uG/UgcLSZ8AKbE1AYf75cSUXI6uefPECNfBcVQ7L0BDzHg.cache +3 -0
  111. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/uG/uGhNDzX7DxymN3xqHLHTndSae3bN0A-MlTk05m6wV4A.cache +1 -0
  112. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/wF/wFT7zoeQQwz-V8syWaS01xr7xgZWr3UNQLWbYSKXirw.cache +1 -0
  113. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/wN/wNw4kAG0E_RrvLeFAizMmTp_0jh-HGw1ONLtRyw92z0.cache +2 -0
  114. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/x-/x-qCUFpNxK1jTHH2qV_VgVk_KrGKdHzNGOnDMVFstuQ.cache +1 -0
  115. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/yk/ykU9I1MzGh7clO4pu853ZKl4LtMlDtyr8BjpiozFQ8E.cache +2 -0
  116. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/yk/ykWLbyEuqa0JHcwHJ-SdVxv4ImwnymlVxvbPKtk6HUM.cache +1 -0
  117. data/spec/internal/tmp/cache/assets/sprockets/v4.0.0/zO/zOr1jCikukgv8-bNHvK43vGLa3CSjtmiwf2K7dUjTnw.cache +0 -0
  118. data/spec/job_spec.rb +183 -0
  119. data/spec/models/crono/crono_job_spec.rb +31 -0
  120. data/spec/performer_proxy_spec.rb +39 -0
  121. data/spec/period_spec.rb +141 -0
  122. data/spec/rails_helper.rb +89 -0
  123. data/spec/scheduler_spec.rb +62 -0
  124. data/spec/spec_helper.rb +19 -0
  125. data/spec/tasks/crono_tasks_spec.rb +23 -0
  126. data/spec/web_spec.rb +61 -0
  127. metadata +233 -68
  128. data/.gitignore +0 -10
  129. data/.rspec +0 -2
  130. data/.travis.yml +0 -14
  131. data/Changes.md +0 -88
  132. data/Gemfile +0 -4
  133. data/Gemfile.lock +0 -78
  134. data/NOTICE +0 -2
  135. data/README.md +0 -218
  136. data/bin/console +0 -14
  137. data/bin/setup +0 -7
  138. data/crono.gemspec +0 -34
  139. data/examples/crono_web_ui.png +0 -0
  140. data/examples/cronotab.rb +0 -14
  141. data/examples/monitrc.conf +0 -6
  142. data/lib/crono/web.rb +0 -22
  143. data/web/assets/css/custom.css +0 -19
  144. data/web/assets/css/materialize.min.css +0 -16
  145. data/web/assets/font/material-design-icons/LICENSE.txt +0 -428
  146. data/web/assets/font/material-design-icons/Material-Design-Icons.eot +0 -0
  147. data/web/assets/font/material-design-icons/Material-Design-Icons.svg +0 -751
  148. data/web/assets/font/material-design-icons/Material-Design-Icons.ttf +0 -0
  149. data/web/assets/font/material-design-icons/Material-Design-Icons.woff +0 -0
  150. data/web/assets/font/material-design-icons/Material-Design-Icons.woff2 +0 -0
  151. data/web/assets/font/roboto/Roboto-Bold.ttf +0 -0
  152. data/web/assets/font/roboto/Roboto-Bold.woff +0 -0
  153. data/web/assets/font/roboto/Roboto-Bold.woff2 +0 -0
  154. data/web/assets/font/roboto/Roboto-Light.ttf +0 -0
  155. data/web/assets/font/roboto/Roboto-Light.woff +0 -0
  156. data/web/assets/font/roboto/Roboto-Light.woff2 +0 -0
  157. data/web/assets/font/roboto/Roboto-Medium.ttf +0 -0
  158. data/web/assets/font/roboto/Roboto-Medium.woff +0 -0
  159. data/web/assets/font/roboto/Roboto-Medium.woff2 +0 -0
  160. data/web/assets/font/roboto/Roboto-Regular.ttf +0 -0
  161. data/web/assets/font/roboto/Roboto-Regular.woff +0 -0
  162. data/web/assets/font/roboto/Roboto-Regular.woff2 +0 -0
  163. data/web/assets/font/roboto/Roboto-Thin.ttf +0 -0
  164. data/web/assets/font/roboto/Roboto-Thin.woff +0 -0
  165. data/web/assets/font/roboto/Roboto-Thin.woff2 +0 -0
  166. data/web/assets/js/jquery-2.1.3.min.js +0 -4
  167. data/web/assets/js/materialize.min.js +0 -10
  168. data/web/views/dashboard.haml +0 -36
  169. data/web/views/job.haml +0 -15
  170. data/web/views/layout.haml +0 -29
File without changes
@@ -0,0 +1,2 @@
1
+ [o:Set:
2
+ @hash} I"environment-version:ETTI"environment-paths;TTI"rails-env;TTI"Lprocessors:type=application/javascript&file_type=application/javascript;TTI"xfile-digest:///Users/dima/.rvm/gems/ruby-3.1.2/gems/activestorage-7.0.3/app/assets/javascripts/activestorage.esm.js;TTI"Zprocessors:type=application/javascript&file_type=application/javascript&pipeline=self;TTF
@@ -0,0 +1 @@
1
+ "%{T{ᘁ�Z�M�'��4�n��D��z�`�.#(�
@@ -0,0 +1,2 @@
1
+ [o:Set:
2
+ @hash} I"environment-version:ETTI"environment-paths;TTI"rails-env;TTI"Lprocessors:type=application/javascript&file_type=application/javascript;TTI"tfile-digest:///Users/dima/.rvm/gems/ruby-3.1.2/gems/actioncable-7.0.3/app/assets/javascripts/actioncable.esm.js;TTI"Zprocessors:type=application/javascript&file_type=application/javascript&pipeline=self;TTF
@@ -0,0 +1 @@
1
+ I"�/Users/dima/.rvm/gems/ruby-3.1.2/gems/actioncable-7.0.3/app/assets/javascripts/actioncable.js?type=application/javascript&pipeline=self&id=f91071b6a4c79e14ff93fcd0b92e1660c6cdf72debb94aa99429b105d266dc02:ET
@@ -0,0 +1 @@
1
+ I"�/Users/dima/.rvm/gems/ruby-3.1.2/gems/actioncable-7.0.3/app/assets/javascripts/actioncable.esm.js?type=application/javascript&pipeline=self&id=0457315ba2f976b566b13534e531a29b43f1316304060f5c423679d861561b07:ET
@@ -0,0 +1 @@
1
+ I"�/Users/dima/dev/crono/app/assets/stylesheets/crono/materialize.min.css?type=text/css&pipeline=self&id=497a14534751eceafd8f67bd15ec1ee578b5ca22cf0eb4e6e8a5e3a599d0e548:ET
@@ -0,0 +1 @@
1
+ "%�x�i�{MŮ'qO�=���M��.�r�#
@@ -0,0 +1 @@
1
+ I"�/Users/dima/.rvm/gems/ruby-3.1.2/gems/activestorage-7.0.3/app/assets/javascripts/activestorage.esm.js?type=application/javascript&id=2f6f62c0d14f6695a40a1b471a7f46d38f4b0d7d1d7739ab41fb433341893a9e:ET
@@ -0,0 +1,2 @@
1
+ "%�غ�0��Fedz
2
+ �9���+�9x�d�=a
@@ -0,0 +1,3 @@
1
+ [o:Set:
2
+ @hash}
3
+ I"environment-version:ETTI"environment-paths;TTI"rails-env;TTI">processors:type=text/css&file_type=text/css&pipeline=self;TTI"Yfile-digest:///Users/dima/dev/crono/app/assets/stylesheets/crono/materialize.min.css;TTF
@@ -0,0 +1 @@
1
+ I"�/Users/dima/.rvm/gems/ruby-3.1.2/gems/activestorage-7.0.3/app/assets/javascripts/activestorage.esm.js?type=application/javascript&pipeline=self&id=b445e35495ac53f0e268a73b396ad931b6efff0a52c99384b78fd1b4695079c3:ET
@@ -0,0 +1 @@
1
+ I"�/Users/dima/.rvm/gems/ruby-3.1.2/gems/actiontext-7.0.3/app/assets/stylesheets/trix.css?type=text/css&pipeline=self&id=b8e6351ffce6adee58c7930aa2dca9e2d88830cae36df9212e15d734eea0818c:ET
@@ -0,0 +1 @@
1
+ I"�/Users/dima/.rvm/gems/ruby-3.1.2/gems/actiontext-7.0.3/app/assets/javascripts/actiontext.js?type=application/javascript&id=a4cd777a3f3676ee7b07dfb1acac24a30ecbcd24ef0647cbf0e81d93e32313ed:ET
@@ -0,0 +1,2 @@
1
+ [o:Set:
2
+ @hash} I"environment-version:ETTI"environment-paths;TTI"rails-env;TTI"0processors:type=text/css&file_type=text/css;TTI"ifile-digest:///Users/dima/.rvm/gems/ruby-3.1.2/gems/actiontext-7.0.3/app/assets/stylesheets/trix.css;TTI">processors:type=text/css&file_type=text/css&pipeline=self;TTF
@@ -0,0 +1 @@
1
+ I"�/Users/dima/.rvm/gems/ruby-3.1.2/gems/actiontext-7.0.3/app/assets/stylesheets/trix.css?type=text/css&id=c00e71b60d87c5927af183d0431615222be6a36409ba33141b5cc89223843b39:ET
@@ -0,0 +1,3 @@
1
+ [o:Set:
2
+ @hash}
3
+ I"environment-version:ETTI"environment-paths;TTI"rails-env;TTI"Zprocessors:type=application/javascript&file_type=application/javascript&pipeline=self;TTI"hfile-digest:///Users/dima/.rvm/gems/ruby-3.1.2/gems/actiontext-7.0.3/app/assets/javascripts/trix.js;TTF
@@ -0,0 +1 @@
1
+ I"�/Users/dima/.rvm/gems/ruby-3.1.2/gems/actiontext-7.0.3/app/assets/javascripts/trix.js?type=application/javascript&pipeline=self&id=d6bc34488bca91fea0c866e168353a8be90d487a217694ef8b8791415f447b5f:ET
@@ -0,0 +1 @@
1
+ I"�/Users/dima/.rvm/gems/ruby-3.1.2/gems/activestorage-7.0.3/app/assets/javascripts/activestorage.js?type=application/javascript&pipeline=self&id=ce361f016e39573f2ab9cffb7648f6e47b83467087b5c8a71c18e4d86f7ba98f:ET
@@ -0,0 +1,3 @@
1
+ [o:Set:
2
+ @hash}
3
+ I"environment-version:ETTI"environment-paths;TTI"rails-env;TTI"Zprocessors:type=application/javascript&file_type=application/javascript&pipeline=self;TTI"xfile-digest:///Users/dima/.rvm/gems/ruby-3.1.2/gems/activestorage-7.0.3/app/assets/javascripts/activestorage.esm.js;TTF
@@ -0,0 +1 @@
1
+ "%� ���f�b`�9f�o/�︰<tF4ؿ �^�T�
@@ -0,0 +1 @@
1
+ I"�/Users/dima/dev/crono/app/assets/stylesheets/crono/materialize.min.css?type=text/css&id=6eb62d3283b7708b5537c79fd39f6adfd03fe6178ef18a0198e62dcdaf667027:ET
@@ -0,0 +1,2 @@
1
+ "%k/�M�EF�ƹ/
2
+ 7�kUP ������N�
@@ -0,0 +1 @@
1
+ I"�/Users/dima/dev/crono/app/assets/stylesheets/crono/application.css?type=text/css&id=a0fea8e02c4498d39cb1991a99a34a1f902902e3d35f9247a980283073788c58:ET
@@ -0,0 +1,2 @@
1
+ [o:Set:
2
+ @hash} I"environment-version:ETTI"environment-paths;TTI"rails-env;TTI"Lprocessors:type=application/javascript&file_type=application/javascript;TTI"tfile-digest:///Users/dima/.rvm/gems/ruby-3.1.2/gems/activestorage-7.0.3/app/assets/javascripts/activestorage.js;TTI"Zprocessors:type=application/javascript&file_type=application/javascript&pipeline=self;TTF
@@ -0,0 +1,2 @@
1
+ [o:Set:
2
+ @hash} I"environment-version:ETTI"environment-paths;TTI"rails-env;TTI"0processors:type=text/css&file_type=text/css;TTI"Yfile-digest:///Users/dima/dev/crono/app/assets/stylesheets/crono/materialize.min.css;TTI">processors:type=text/css&file_type=text/css&pipeline=self;TTF
@@ -0,0 +1,2 @@
1
+ [o:Set:
2
+ @hash} I"environment-version:ETTI"environment-paths;TTI"rails-env;TTI"0processors:type=text/css&file_type=text/css;TTI"Ufile-digest:///Users/dima/dev/crono/app/assets/stylesheets/crono/application.css;TTI">processors:type=text/css&file_type=text/css&pipeline=self;TTF
@@ -0,0 +1,3 @@
1
+ [o:Set:
2
+ @hash}
3
+ I"environment-version:ETTI"environment-paths;TTI"rails-env;TTI"Zprocessors:type=application/javascript&file_type=application/javascript&pipeline=self;TTI"pfile-digest:///Users/dima/.rvm/gems/ruby-3.1.2/gems/actioncable-7.0.3/app/assets/javascripts/actioncable.js;TTF
@@ -0,0 +1,3 @@
1
+ [o:Set:
2
+ @hash}
3
+ I"environment-version:ETTI"environment-paths;TTI"rails-env;TTI"Zprocessors:type=application/javascript&file_type=application/javascript&pipeline=self;TTI"tfile-digest:///Users/dima/.rvm/gems/ruby-3.1.2/gems/actioncable-7.0.3/app/assets/javascripts/actioncable.esm.js;TTF
@@ -0,0 +1,2 @@
1
+ [o:Set:
2
+ @hash} I"environment-version:ETTI"environment-paths;TTI"rails-env;TTI"Lprocessors:type=application/javascript&file_type=application/javascript;TTI"pfile-digest:///Users/dima/.rvm/gems/ruby-3.1.2/gems/actioncable-7.0.3/app/assets/javascripts/actioncable.js;TTI"Zprocessors:type=application/javascript&file_type=application/javascript&pipeline=self;TTF
@@ -0,0 +1,3 @@
1
+ [o:Set:
2
+ @hash}
3
+ I"environment-version:ETTI"environment-paths;TTI"rails-env;TTI">processors:type=text/css&file_type=text/css&pipeline=self;TTI"Ufile-digest:///Users/dima/dev/crono/app/assets/stylesheets/crono/application.css;TTF
@@ -0,0 +1,3 @@
1
+ [o:Set:
2
+ @hash}
3
+ I"environment-version:ETTI"environment-paths;TTI"rails-env;TTI">processors:type=text/css&file_type=text/css&pipeline=self;TTI"ifile-digest:///Users/dima/.rvm/gems/ruby-3.1.2/gems/actiontext-7.0.3/app/assets/stylesheets/trix.css;TTF
@@ -0,0 +1,2 @@
1
+ [o:Set:
2
+ @hash} I"environment-version:ETTI"environment-paths;TTI"rails-env;TTI"Lprocessors:type=application/javascript&file_type=application/javascript;TTI"nfile-digest:///Users/dima/.rvm/gems/ruby-3.1.2/gems/actiontext-7.0.3/app/assets/javascripts/actiontext.js;TTI"Zprocessors:type=application/javascript&file_type=application/javascript&pipeline=self;TTF
@@ -0,0 +1,2 @@
1
+ [o:Set:
2
+ @hash} I"environment-version:ETTI"environment-paths;TTI"rails-env;TTI"Lprocessors:type=application/javascript&file_type=application/javascript;TTI"hfile-digest:///Users/dima/.rvm/gems/ruby-3.1.2/gems/actiontext-7.0.3/app/assets/javascripts/trix.js;TTI"Zprocessors:type=application/javascript&file_type=application/javascript&pipeline=self;TTF
@@ -0,0 +1 @@
1
+ I"�app/assets/config/manifest.js?type=application/javascript&pipeline=self&id=a7a372ac8e8a9fea274aaf94166a0cd3e2eb1ca25fb0ae96ee3191095dfe3aa4:ET
@@ -0,0 +1,3 @@
1
+ [o:Set:
2
+ @hash}
3
+ I"environment-version:ETTI"environment-paths;TTI"rails-env;TTI"Zprocessors:type=application/javascript&file_type=application/javascript&pipeline=self;TTI"0file-digest://app/assets/config/manifest.js;TTF
@@ -0,0 +1 @@
1
+ "%��B�����șo�$'�A�d��L���xR�U
@@ -0,0 +1,3 @@
1
+ [o:Set:
2
+ @hash}
3
+ I"environment-version:ETTI"environment-paths;TTI"rails-env;TTI"Zprocessors:type=application/javascript&file_type=application/javascript&pipeline=self;TTI"tfile-digest:///Users/dima/.rvm/gems/ruby-3.1.2/gems/activestorage-7.0.3/app/assets/javascripts/activestorage.js;TTF
@@ -0,0 +1 @@
1
+ I"}app/assets/config/manifest.js?type=application/javascript&id=3efef18dbd3a6eebf3206d8a735d7e6c3b93ecf3ab34771bfedc2614b3f604f6:ET
@@ -0,0 +1,2 @@
1
+ "%�q5*�����0���o�
2
+ �'��o��TG�p�
@@ -0,0 +1 @@
1
+ I"�/Users/dima/.rvm/gems/ruby-3.1.2/gems/actioncable-7.0.3/app/assets/javascripts/actioncable.esm.js?type=application/javascript&id=183f74bf94fdc9198dfba2b4a70ea9c03f22a660e8347a2ec70eb5ec331277d9:ET
@@ -0,0 +1 @@
1
+ I"�/Users/dima/dev/crono/app/assets/stylesheets/crono/application.css?type=text/css&pipeline=self&id=c3a7c628efefdbb6fc055e8ffbf3ef6cff7faf75db6ed03226bc13f5cf0dbea3:ET
@@ -0,0 +1 @@
1
+ I"�/Users/dima/.rvm/gems/ruby-3.1.2/gems/activestorage-7.0.3/app/assets/javascripts/activestorage.js?type=application/javascript&id=50f51faaf3d30e75288cc1a239145d0fc43c916db356cb5f9e94c9acf801cc79:ET
@@ -0,0 +1 @@
1
+ I"�/Users/dima/.rvm/gems/ruby-3.1.2/gems/actiontext-7.0.3/app/assets/javascripts/trix.js?type=application/javascript&id=647d61696a2f00f03c097daf8276ec1abef825ec7435e9e4866a683f8e27954d:ET
@@ -0,0 +1,3 @@
1
+ [o:Set:
2
+ @hash}
3
+ I"environment-version:ETTI"environment-paths;TTI"rails-env;TTI"Zprocessors:type=application/javascript&file_type=application/javascript&pipeline=self;TTI"nfile-digest:///Users/dima/.rvm/gems/ruby-3.1.2/gems/actiontext-7.0.3/app/assets/javascripts/actiontext.js;TTF
@@ -0,0 +1 @@
1
+ "%q�;w7CQ�qu�i�=��%*� ��������
@@ -0,0 +1 @@
1
+ I"�/Users/dima/.rvm/gems/ruby-3.1.2/gems/actiontext-7.0.3/app/assets/javascripts/actiontext.js?type=application/javascript&pipeline=self&id=6dc77b6c4b09c05ec6fe5bf24e67e5e82e0b919eec5a0cda17f32052b7ded055:ET
@@ -0,0 +1,2 @@
1
+ [o:Set:
2
+ @hash} I"environment-version:ETTI"environment-paths;TTI"rails-env;TTI"Lprocessors:type=application/javascript&file_type=application/javascript;TTI"0file-digest://app/assets/config/manifest.js;TTI"Zprocessors:type=application/javascript&file_type=application/javascript&pipeline=self;TTF
@@ -0,0 +1 @@
1
+ I"�/Users/dima/.rvm/gems/ruby-3.1.2/gems/actioncable-7.0.3/app/assets/javascripts/actioncable.js?type=application/javascript&id=2d383e1c6ce81048db29407b6155db80bb64c746a133856679c31126f3df034e:ET
@@ -0,0 +1,2 @@
1
+ "%��=��v�
2
+ �ć�H�P�9�=m�-�B�{
@@ -0,0 +1 @@
1
+ "%�ɝQh݋6�d���)��^�I�{Hk����
data/spec/job_spec.rb ADDED
@@ -0,0 +1,183 @@
1
+ require 'spec_helper'
2
+
3
+ class TestJob
4
+ def perform(args)
5
+ puts 'Test!'
6
+ end
7
+ end
8
+
9
+ class TestFailingJob
10
+ def perform(args)
11
+ raise 'Some error'
12
+ end
13
+ end
14
+
15
+ describe Crono::Job do
16
+ let(:period) { Crono::Period.new(2.day, at: '15:00') }
17
+ let(:job_args) {[{some: 'data'}]}
18
+ let(:job) { Crono::Job.new(TestJob, period, []) }
19
+ let(:job_with_args) { Crono::Job.new(TestJob, period, job_args) }
20
+ let(:failing_job) { Crono::Job.new(TestFailingJob, period, []) }
21
+
22
+ it 'should contain performer and period' do
23
+ expect(job.performer).to be TestJob
24
+ expect(job.period).to be period
25
+ end
26
+
27
+ it 'should contain data as JSON String' do
28
+ expect(job_with_args.job_args).to eq '[{"some":"data"}]'
29
+ end
30
+
31
+ describe '#next' do
32
+ it 'should return next performing time according to period' do
33
+ expect(job.next).to be_eql period.next
34
+ end
35
+ end
36
+
37
+ describe '#perform' do
38
+ after { job.send(:model).destroy }
39
+
40
+ it 'should run performer in separate thread' do
41
+ expect(job).to receive(:save)
42
+ thread = job.perform.join
43
+ expect(thread).to be_stop
44
+ end
45
+
46
+ it 'should save performin errors to log' do
47
+ thread = failing_job.perform.join
48
+ expect(thread).to be_stop
49
+ saved_log = Crono::CronoJob.find_by(job_id: failing_job.job_id).log
50
+ expect(saved_log).to include 'Some error'
51
+ end
52
+
53
+ it 'should set Job#healthy to false if perform with error' do
54
+ failing_job.perform.join
55
+ expect(failing_job.healthy).to be false
56
+ end
57
+
58
+ it 'should execute one' do
59
+ job.execution_interval = 5.minutes
60
+
61
+ expect(job).to receive(:perform_job).once
62
+ job.perform.join
63
+ thread = job.perform.join
64
+ expect(thread).to be_stop
65
+ end
66
+
67
+ it 'should execute twice' do
68
+ job.execution_interval = 0.minutes
69
+
70
+ test_preform_job_twice
71
+ end
72
+
73
+ it 'should execute twice without initialize execution_interval' do
74
+ test_preform_job_twice
75
+ end
76
+
77
+ it 'should call perform of performer' do
78
+ expect(TestJob).to receive(:new).with(no_args)
79
+ thread = job.perform.join
80
+ expect(thread).to be_stop
81
+ end
82
+
83
+ it 'should call perform of performer with data' do
84
+ test_job = double()
85
+ expect(TestJob).to receive(:new).and_return(test_job)
86
+ expect(test_job).to receive(:perform).with([{ 'some' => 'data' }])
87
+ thread = job_with_args.perform.join
88
+ expect(thread).to be_stop
89
+ end
90
+
91
+ def test_preform_job_twice
92
+ expect(job).to receive(:perform_job).twice
93
+ job.perform.join
94
+ thread = job.perform.join
95
+ expect(thread).to be_stop
96
+ end
97
+ end
98
+
99
+ describe '#description' do
100
+ it 'should return job identificator' do
101
+ expect(job.description).to be_eql('Perform TestJob every 2 days at 15:00')
102
+ end
103
+ end
104
+
105
+ describe '#save' do
106
+ it 'should save new job to DB' do
107
+ expect(Crono::CronoJob.where(job_id: job.job_id)).to_not exist
108
+ job.save
109
+ expect(Crono::CronoJob.where(job_id: job.job_id)).to exist
110
+ end
111
+
112
+ it 'should update saved job' do
113
+ job.last_performed_at = Time.zone.now
114
+ job.healthy = true
115
+ job.job_args = JSON.generate([{some: 'data'}])
116
+ job.save
117
+ @crono_job = Crono::CronoJob.find_by(job_id: job.job_id)
118
+ expect(@crono_job.last_performed_at.utc.to_s).to be_eql job.last_performed_at.utc.to_s
119
+ expect(@crono_job.healthy).to be true
120
+ end
121
+
122
+ it 'should save log' do
123
+ message = 'test message'
124
+ job.send(:log, message)
125
+ job.save
126
+ expect(job.send(:model).reload.log).to include message
127
+ expect(job.job_log.string).to be_empty
128
+ end
129
+
130
+ it 'should not truncate log if not specified' do
131
+ log = (1..100).map {|n| "line #{n}" }.join("\n")
132
+ job = Crono::Job.new(TestJob, period, [])
133
+ job.send(:log, log)
134
+ job.save
135
+ expect(job.send(:model).reload.log.lines.size).to be >= log.lines.size
136
+ end
137
+
138
+ it 'should truncate log if specified' do
139
+ log = (1..100).map {|n| "line #{n}" }.join("\n")
140
+ job = Crono::Job.new(TestJob, period, [], truncate_log: 50)
141
+ job.send(:log, log)
142
+ job.save
143
+ expect(job.send(:model).reload.log.lines.size).to be 50
144
+ end
145
+ end
146
+
147
+ describe '#load' do
148
+ before do
149
+ @saved_last_performed_at = job.last_performed_at = Time.zone.now
150
+ job.save
151
+ end
152
+
153
+ it 'should load last_performed_at from DB' do
154
+ @job = Crono::Job.new(TestJob, period, job_args)
155
+ @job.load
156
+ expect(@job.last_performed_at.utc.to_s).to be_eql @saved_last_performed_at.utc.to_s
157
+ end
158
+ end
159
+
160
+ describe '#log' do
161
+ it 'should write log messages to both common and job log' do
162
+ message = 'Test message'
163
+ job.logfile = "/dev/null"
164
+ expect(job.logger).to receive(:log).with(Logger::INFO, message)
165
+ expect(job.job_logger).to receive(:log).with(Logger::INFO, message)
166
+ job.send(:log, message)
167
+ end
168
+
169
+ it 'should write job log to Job#job_log' do
170
+ message = 'Test message'
171
+ job.send(:log, message)
172
+ expect(job.job_log.string).to include(message)
173
+ end
174
+ end
175
+
176
+ describe '#log_error' do
177
+ it 'should call log with ERROR severity' do
178
+ message = 'Test message'
179
+ expect(job).to receive(:log).with(message, Logger::ERROR)
180
+ job.send(:log_error, message)
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+ require 'rack/test'
3
+
4
+ module Crono
5
+ RSpec.describe Crono::CronoJob, type: :model do
6
+ let(:valid_attrs) do
7
+ {
8
+ job_id: 'Perform TestJob every 3 days'
9
+ }
10
+ end
11
+
12
+ it 'should validate presence of job_id' do
13
+ @crono_job = Crono::CronoJob.new
14
+ expect(@crono_job).not_to be_valid
15
+ expect(@crono_job.errors.added?(:job_id, :blank)).to be true
16
+ end
17
+
18
+ it 'should validate uniqueness of job_id' do
19
+ Crono::CronoJob.create!(job_id: 'TestJob every 2 days')
20
+ @crono_job = Crono::CronoJob.create(job_id: 'TestJob every 2 days')
21
+ expect(@crono_job).not_to be_valid
22
+ expect(@crono_job.errors.size).to be 1
23
+ end
24
+
25
+ it 'should save job_id to DB' do
26
+ Crono::CronoJob.create!(valid_attrs)
27
+ @crono_job = Crono::CronoJob.find_by(job_id: valid_attrs[:job_id])
28
+ expect(@crono_job).to be_present
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ class TestJob
4
+ def perform
5
+ puts 'Test!'
6
+ end
7
+ end
8
+
9
+ describe Crono::PerformerProxy do
10
+ it 'should add job to schedule' do
11
+ expect(Crono.scheduler).to receive(:add_job).with(kind_of(Crono::Job))
12
+ Crono.perform(TestJob).every(2.days, at: '15:30')
13
+ end
14
+
15
+ it 'should set execution interval' do
16
+ allow(Crono).to receive(:scheduler).and_return(Crono::Scheduler.new)
17
+ expect_any_instance_of(Crono::Job).to receive(:execution_interval=).with(0.minutes).once
18
+ expect_any_instance_of(Crono::Job).to receive(:execution_interval=).with(10.minutes).once
19
+ Crono.perform(TestJob).every(2.days, at: '15:30').once_per 10.minutes
20
+ end
21
+
22
+ it 'do nothing when job not initalized' do
23
+ expect_any_instance_of(Crono::Job).not_to receive(:execution_interval=)
24
+ expect_any_instance_of(described_class).to receive(:once_per)
25
+ Crono.perform(TestJob).once_per 10.minutes
26
+ end
27
+
28
+ it 'should add job with args to schedule' do
29
+ expect(Crono::Job).to receive(:new).with(TestJob, kind_of(Crono::Period), [:some, {some: 'data'}], nil)
30
+ allow(Crono.scheduler).to receive(:add_job)
31
+ Crono.perform(TestJob, :some, {some: 'data'}).every(2.days, at: '15:30')
32
+ end
33
+
34
+ it 'should add job with options to schedule' do
35
+ expect(Crono::Job).to receive(:new).with(TestJob, kind_of(Crono::Period), [], {some_option: true})
36
+ allow(Crono.scheduler).to receive(:add_job)
37
+ Crono.perform(TestJob).with_options(some_option: true).every(2.days, at: '15:30')
38
+ end
39
+ end