naf 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (295) hide show
  1. data/.gitignore +16 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +17 -0
  4. data/Gemfile +17 -0
  5. data/LICENSE +2 -0
  6. data/README.rdoc +22 -0
  7. data/RELEASE_NOTES.rdoc +18 -0
  8. data/Rakefile +43 -0
  9. data/app/assets/images/bg-grad.png +0 -0
  10. data/app/assets/images/clock.png +0 -0
  11. data/app/assets/images/control_play_blue.png +0 -0
  12. data/app/assets/images/down_arrow.gif +0 -0
  13. data/app/assets/images/papertrail_job.png +0 -0
  14. data/app/assets/images/papertrail_machine.png +0 -0
  15. data/app/assets/images/papertrail_machine_runner.png +0 -0
  16. data/app/assets/images/terminate.png +0 -0
  17. data/app/assets/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  18. data/app/assets/images/ui-bg_flat_0_ffffff_40x100.png +0 -0
  19. data/app/assets/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  20. data/app/assets/images/ui-bg_glass_0_f4f4f4_1x400.png +0 -0
  21. data/app/assets/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  22. data/app/assets/images/ui-bg_glass_65_f4f4f4_1x400.png +0 -0
  23. data/app/assets/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  24. data/app/assets/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  25. data/app/assets/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  26. data/app/assets/images/ui-bg_glass_75_f4f4f4_1x400.png +0 -0
  27. data/app/assets/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  28. data/app/assets/images/ui-bg_highlight-soft_0_f4f4f4_1x100.png +0 -0
  29. data/app/assets/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  30. data/app/assets/images/ui-icons_222222_256x240.png +0 -0
  31. data/app/assets/images/ui-icons_2e83ff_256x240.png +0 -0
  32. data/app/assets/images/ui-icons_454545_256x240.png +0 -0
  33. data/app/assets/images/ui-icons_888888_256x240.png +0 -0
  34. data/app/assets/images/ui-icons_cd0a0a_256x240.png +0 -0
  35. data/app/assets/images/up_arrow.gif +0 -0
  36. data/app/assets/javascripts/dataTablesTemplates/applications.js +94 -0
  37. data/app/assets/javascripts/dataTablesTemplates/jobs.js +163 -0
  38. data/app/assets/javascripts/dataTablesTemplates/machine_runner_invocations.js +60 -0
  39. data/app/assets/javascripts/dataTablesTemplates/machine_runners.js +82 -0
  40. data/app/assets/javascripts/dataTablesTemplates/machines.js +93 -0
  41. data/app/assets/javascripts/date.js +104 -0
  42. data/app/assets/javascripts/iso8601.js +41 -0
  43. data/app/assets/javascripts/jquery.dataTables.custom.js +62 -0
  44. data/app/assets/javascripts/jquery.dataTables.js +6862 -0
  45. data/app/assets/javascripts/naf.js +30 -0
  46. data/app/assets/javascripts/underscore.js +713 -0
  47. data/app/assets/stylesheets/jquery_ui/jquery-ui-1.8.5.custom.css.erb +572 -0
  48. data/app/assets/stylesheets/min_naf.css +14 -0
  49. data/app/assets/stylesheets/min_naf/layout.css.scss +355 -0
  50. data/app/assets/stylesheets/naf.css +14 -0
  51. data/app/assets/stylesheets/naf/layout.css.scss +497 -0
  52. data/app/controllers/naf/affinities_controller.rb +61 -0
  53. data/app/controllers/naf/application_controller.rb +43 -0
  54. data/app/controllers/naf/application_schedule_affinity_tabs_controller.rb +75 -0
  55. data/app/controllers/naf/applications_controller.rb +153 -0
  56. data/app/controllers/naf/historical_job_affinity_tabs_controller.rb +65 -0
  57. data/app/controllers/naf/historical_jobs_controller.rb +159 -0
  58. data/app/controllers/naf/janitorial_assignments_controller.rb +77 -0
  59. data/app/controllers/naf/logger_names_controller.rb +58 -0
  60. data/app/controllers/naf/logger_styles_controller.rb +59 -0
  61. data/app/controllers/naf/machine_affinity_slots_controller.rb +69 -0
  62. data/app/controllers/naf/machine_runner_invocations_controller.rb +59 -0
  63. data/app/controllers/naf/machine_runners_controller.rb +26 -0
  64. data/app/controllers/naf/machines_controller.rb +95 -0
  65. data/app/helpers/naf/application_helper.rb +275 -0
  66. data/app/models/log4r/papertrail_outputter.rb +19 -0
  67. data/app/models/logical/naf/application.rb +183 -0
  68. data/app/models/logical/naf/construction_zone/ad_hoc_work_order.rb +22 -0
  69. data/app/models/logical/naf/construction_zone/application_schedule_work_order.rb +15 -0
  70. data/app/models/logical/naf/construction_zone/application_work_order.rb +25 -0
  71. data/app/models/logical/naf/construction_zone/boss.rb +123 -0
  72. data/app/models/logical/naf/construction_zone/foreman.rb +53 -0
  73. data/app/models/logical/naf/construction_zone/proletariat.rb +40 -0
  74. data/app/models/logical/naf/construction_zone/work_order.rb +100 -0
  75. data/app/models/logical/naf/create_infrastructure.rb +48 -0
  76. data/app/models/logical/naf/job.rb +357 -0
  77. data/app/models/logical/naf/job_creator.rb +155 -0
  78. data/app/models/logical/naf/job_fetcher.rb +167 -0
  79. data/app/models/logical/naf/job_statuses/errored.rb +27 -0
  80. data/app/models/logical/naf/job_statuses/finished.rb +26 -0
  81. data/app/models/logical/naf/job_statuses/finished_less_minute.rb +25 -0
  82. data/app/models/logical/naf/job_statuses/queued.rb +32 -0
  83. data/app/models/logical/naf/job_statuses/running.rb +34 -0
  84. data/app/models/logical/naf/job_statuses/terminated.rb +25 -0
  85. data/app/models/logical/naf/job_statuses/waiting.rb +43 -0
  86. data/app/models/logical/naf/machine.rb +85 -0
  87. data/app/models/logical/naf/machine_runner.rb +46 -0
  88. data/app/models/logical/naf/machine_runner_invocation.rb +50 -0
  89. data/app/models/logical/naf/pickler.rb +74 -0
  90. data/app/models/logical/naf/unpickler.rb +98 -0
  91. data/app/models/naf/affinity.rb +145 -0
  92. data/app/models/naf/affinity_classification.rb +44 -0
  93. data/app/models/naf/application.rb +100 -0
  94. data/app/models/naf/application_run_group_restriction.rb +39 -0
  95. data/app/models/naf/application_schedule.rb +181 -0
  96. data/app/models/naf/application_schedule_affinity_tab.rb +86 -0
  97. data/app/models/naf/application_schedule_prerequisite.rb +50 -0
  98. data/app/models/naf/application_type.rb +72 -0
  99. data/app/models/naf/by_historical_job_id.rb +86 -0
  100. data/app/models/naf/historical_job.rb +334 -0
  101. data/app/models/naf/historical_job_affinity_tab.rb +61 -0
  102. data/app/models/naf/historical_job_prerequisite.rb +19 -0
  103. data/app/models/naf/janitorial_archive_assignment.rb +36 -0
  104. data/app/models/naf/janitorial_assignment.rb +37 -0
  105. data/app/models/naf/janitorial_create_assignment.rb +36 -0
  106. data/app/models/naf/janitorial_drop_assignment.rb +36 -0
  107. data/app/models/naf/logger_level.rb +21 -0
  108. data/app/models/naf/logger_name.rb +23 -0
  109. data/app/models/naf/logger_style.rb +58 -0
  110. data/app/models/naf/logger_style_name.rb +28 -0
  111. data/app/models/naf/machine.rb +257 -0
  112. data/app/models/naf/machine_affinity_slot.rb +78 -0
  113. data/app/models/naf/machine_runner.rb +51 -0
  114. data/app/models/naf/machine_runner_invocation.rb +71 -0
  115. data/app/models/naf/naf_base.rb +9 -0
  116. data/app/models/naf/queued_job.rb +164 -0
  117. data/app/models/naf/running_job.rb +80 -0
  118. data/app/models/process/naf/application.rb +164 -0
  119. data/app/models/process/naf/janitor.rb +117 -0
  120. data/app/models/process/naf/machine_manager.rb +150 -0
  121. data/app/models/process/naf/machine_upgrader.rb +112 -0
  122. data/app/models/process/naf/runner.rb +539 -0
  123. data/app/views/naf/affinities/_form.html.erb +50 -0
  124. data/app/views/naf/affinities/edit.html.erb +11 -0
  125. data/app/views/naf/affinities/index.html.erb +57 -0
  126. data/app/views/naf/affinities/new.html.erb +15 -0
  127. data/app/views/naf/affinities/show.html.erb +48 -0
  128. data/app/views/naf/application_schedule_affinity_tabs/_form.html.erb +31 -0
  129. data/app/views/naf/application_schedule_affinity_tabs/edit.html.erb +12 -0
  130. data/app/views/naf/application_schedule_affinity_tabs/new.html.erb +11 -0
  131. data/app/views/naf/applications/_application_schedule.html.erb +80 -0
  132. data/app/views/naf/applications/_application_schedule_prerequisites.html.erb +14 -0
  133. data/app/views/naf/applications/_form.html.erb +109 -0
  134. data/app/views/naf/applications/_search_container.html.erb +94 -0
  135. data/app/views/naf/applications/_show.html.erb +34 -0
  136. data/app/views/naf/applications/edit.html.erb +11 -0
  137. data/app/views/naf/applications/index.html.erb +51 -0
  138. data/app/views/naf/applications/index.json.erb +11 -0
  139. data/app/views/naf/applications/new.html.erb +11 -0
  140. data/app/views/naf/applications/show.html.erb +203 -0
  141. data/app/views/naf/datatable.html.erb +49 -0
  142. data/app/views/naf/historical_job_affinity_tabs/_form.html.erb +36 -0
  143. data/app/views/naf/historical_job_affinity_tabs/edit.html.erb +11 -0
  144. data/app/views/naf/historical_job_affinity_tabs/new.html.erb +11 -0
  145. data/app/views/naf/historical_jobs/_form.html.erb +94 -0
  146. data/app/views/naf/historical_jobs/_runners.html.erb +22 -0
  147. data/app/views/naf/historical_jobs/_search_container.html.erb +140 -0
  148. data/app/views/naf/historical_jobs/edit.html.erb +11 -0
  149. data/app/views/naf/historical_jobs/index.html.erb +48 -0
  150. data/app/views/naf/historical_jobs/index.json.erb +26 -0
  151. data/app/views/naf/historical_jobs/new.html.erb +61 -0
  152. data/app/views/naf/historical_jobs/show.html.erb +201 -0
  153. data/app/views/naf/janitorial_assignments/_form.html.erb +38 -0
  154. data/app/views/naf/janitorial_assignments/_rows.html.erb +17 -0
  155. data/app/views/naf/janitorial_assignments/edit.html.erb +11 -0
  156. data/app/views/naf/janitorial_assignments/index.html.erb +56 -0
  157. data/app/views/naf/janitorial_assignments/index.js.erb +1 -0
  158. data/app/views/naf/janitorial_assignments/new.html.erb +11 -0
  159. data/app/views/naf/layouts/jquery_datatables.json.erb +6 -0
  160. data/app/views/naf/logger_names/_form.html.erb +18 -0
  161. data/app/views/naf/logger_names/edit.html.erb +11 -0
  162. data/app/views/naf/logger_names/new.html.erb +11 -0
  163. data/app/views/naf/logger_names/show.html.erb +44 -0
  164. data/app/views/naf/logger_styles/_form.html.erb +30 -0
  165. data/app/views/naf/logger_styles/_logger_style_names.html.erb +19 -0
  166. data/app/views/naf/logger_styles/edit.html.erb +11 -0
  167. data/app/views/naf/logger_styles/new.html.erb +11 -0
  168. data/app/views/naf/logger_styles/show.html.erb +48 -0
  169. data/app/views/naf/machine_affinity_slots/_form.html.erb +36 -0
  170. data/app/views/naf/machine_affinity_slots/edit.html.erb +11 -0
  171. data/app/views/naf/machine_affinity_slots/new.html.erb +11 -0
  172. data/app/views/naf/machine_runner_invocations/_filter.html.erb +21 -0
  173. data/app/views/naf/machine_runner_invocations/index.html.erb +36 -0
  174. data/app/views/naf/machine_runner_invocations/index.json.erb +16 -0
  175. data/app/views/naf/machine_runner_invocations/show.html.erb +91 -0
  176. data/app/views/naf/machine_runners/index.html.erb +82 -0
  177. data/app/views/naf/machine_runners/index.json.erb +16 -0
  178. data/app/views/naf/machine_runners/show.html.erb +113 -0
  179. data/app/views/naf/machines/_filter.html.erb +26 -0
  180. data/app/views/naf/machines/_form.html.erb +62 -0
  181. data/app/views/naf/machines/_show.html.erb +169 -0
  182. data/app/views/naf/machines/edit.html.erb +11 -0
  183. data/app/views/naf/machines/index.html.erb +51 -0
  184. data/app/views/naf/machines/index.json.erb +23 -0
  185. data/app/views/naf/machines/new.html.erb +11 -0
  186. data/app/views/naf/machines/show.html.erb +92 -0
  187. data/app/views/naf/record.html.erb +46 -0
  188. data/app/views/naf/shared/_application.html.erb +50 -0
  189. data/app/views/naf/shared/_information_container.html.erb +19 -0
  190. data/app/views/naf/shared/_select_per_page.html.erb +72 -0
  191. data/ci/test-build.sh +17 -0
  192. data/ci/travis.sh +26 -0
  193. data/config/initializers/naf.rb +3 -0
  194. data/config/routes.rb +38 -0
  195. data/db/migrate/20120820023848_naf_schema.rb +413 -0
  196. data/doc/README_FOR_APP +2 -0
  197. data/lib/generators/naf_generator.rb +45 -0
  198. data/lib/generators/templates/config/logging/af.yml +26 -0
  199. data/lib/generators/templates/config/logging/naf.yml +22 -0
  200. data/lib/generators/templates/config/logging/nafjob.yml +16 -0
  201. data/lib/generators/templates/config/logging/nafrunner.yml +17 -0
  202. data/lib/generators/templates/naf.rb +11 -0
  203. data/lib/generators/templates/naf_layout.html.erb +15 -0
  204. data/lib/naf.rb +48 -0
  205. data/lib/naf/configuration.rb +23 -0
  206. data/lib/naf/engine.rb +18 -0
  207. data/lib/naf/version.rb +3 -0
  208. data/lib/tasks/naf_tasks.rake +370 -0
  209. data/naf.gemspec +30 -0
  210. data/script/rails +10 -0
  211. data/spec/controllers/naf/affinities_controller_spec.rb +79 -0
  212. data/spec/controllers/naf/application_controller_spec.rb +10 -0
  213. data/spec/controllers/naf/application_schedule_affinity_tabs_controller_spec.rb +106 -0
  214. data/spec/controllers/naf/applications_controller_spec.rb +109 -0
  215. data/spec/controllers/naf/historical_job_affinity_tabs_controller_spec.rb +96 -0
  216. data/spec/controllers/naf/historical_jobs_controller_spec.rb +19 -0
  217. data/spec/controllers/naf/machine_affinity_slots_controller_spec.rb +109 -0
  218. data/spec/controllers/naf/machines_controller_spec.rb +74 -0
  219. data/spec/dummy/.gitignore +12 -0
  220. data/spec/dummy/README +19 -0
  221. data/spec/dummy/Rakefile +7 -0
  222. data/spec/dummy/app/assets/javascripts/application.js +16 -0
  223. data/spec/dummy/app/assets/stylesheets/application.css +14 -0
  224. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  225. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  226. data/spec/dummy/app/models/my_script.rb +8 -0
  227. data/spec/dummy/app/models/other/base.rb.sample +10 -0
  228. data/spec/dummy/app/views/layouts/application.html.erb +15 -0
  229. data/spec/dummy/app/views/layouts/naf_layout.html.erb +15 -0
  230. data/spec/dummy/config.ru +4 -0
  231. data/spec/dummy/config/application.rb +62 -0
  232. data/spec/dummy/config/boot.rb +10 -0
  233. data/spec/dummy/config/database-non_primary.yml +20 -0
  234. data/spec/dummy/config/database-primary.yml +16 -0
  235. data/spec/dummy/config/environment.rb +5 -0
  236. data/spec/dummy/config/environments/development.rb +37 -0
  237. data/spec/dummy/config/environments/production.rb +67 -0
  238. data/spec/dummy/config/environments/test.rb +37 -0
  239. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  240. data/spec/dummy/config/initializers/inflections.rb +15 -0
  241. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  242. data/spec/dummy/config/initializers/naf.rb.non_primary +4 -0
  243. data/spec/dummy/config/initializers/naf.rb.primary +3 -0
  244. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  245. data/spec/dummy/config/initializers/session_store.rb +8 -0
  246. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  247. data/spec/dummy/config/locales/en.yml +5 -0
  248. data/spec/dummy/config/logging/af.yml +26 -0
  249. data/spec/dummy/config/logging/naf.yml +22 -0
  250. data/spec/dummy/config/logging/nafjob.yml +16 -0
  251. data/spec/dummy/config/logging/nafrunner.yml +17 -0
  252. data/spec/dummy/config/routes.rb +5 -0
  253. data/spec/dummy/db/.gitignore +2 -0
  254. data/spec/dummy/lib/tasks/dummy.rake +60 -0
  255. data/spec/dummy/public/404.html +26 -0
  256. data/spec/dummy/public/422.html +26 -0
  257. data/spec/dummy/public/500.html +25 -0
  258. data/spec/dummy/public/favicon.ico +0 -0
  259. data/spec/dummy/script/rails +6 -0
  260. data/spec/factories/naf.rb +433 -0
  261. data/spec/helpers/naf/application_helper_spec.rb +0 -0
  262. data/spec/models/logical/naf/application_spec.rb +69 -0
  263. data/spec/models/logical/naf/job_creator_spec.rb +32 -0
  264. data/spec/models/logical/naf/job_fetcher_spec.rb +140 -0
  265. data/spec/models/logical/naf/job_spec.rb +282 -0
  266. data/spec/models/logical/naf/machine_spec.rb +61 -0
  267. data/spec/models/naf/affinity_classification_spec.rb +56 -0
  268. data/spec/models/naf/affinity_spec.rb +100 -0
  269. data/spec/models/naf/application_run_group_restriction_spec.rb +57 -0
  270. data/spec/models/naf/application_schedule_affinity_tab_spec.rb +85 -0
  271. data/spec/models/naf/application_schedule_prerequisite_spec.rb +35 -0
  272. data/spec/models/naf/application_schedule_spec.rb +166 -0
  273. data/spec/models/naf/application_spec.rb +128 -0
  274. data/spec/models/naf/application_type_spec.rb +104 -0
  275. data/spec/models/naf/historical_job_affinity_tab_spec.rb +59 -0
  276. data/spec/models/naf/historical_job_prerequisite_spec.rb +25 -0
  277. data/spec/models/naf/historical_job_spec.rb +334 -0
  278. data/spec/models/naf/logger_level_spec.rb +34 -0
  279. data/spec/models/naf/logger_name_spec.rb +35 -0
  280. data/spec/models/naf/logger_style_name_spec.rb +39 -0
  281. data/spec/models/naf/logger_style_spec.rb +89 -0
  282. data/spec/models/naf/machine_affinity_slot_spec.rb +77 -0
  283. data/spec/models/naf/machine_runner_invocation_spec.rb +38 -0
  284. data/spec/models/naf/machine_runner_spec.rb +37 -0
  285. data/spec/models/naf/machine_spec.rb +425 -0
  286. data/spec/models/naf/naf_base_spec.rb +14 -0
  287. data/spec/models/naf/queued_job_spec.rb +171 -0
  288. data/spec/models/naf/running_job_spec.rb +107 -0
  289. data/spec/models/process/naf/application_spec.rb +8 -0
  290. data/spec/models/process/naf/janitor_spec.rb +10 -0
  291. data/spec/models/process/naf/runner_spec.rb +10 -0
  292. data/spec/spec_helper.rb +32 -0
  293. data/spec/support/engine_routing.rb +27 -0
  294. data/spec/support/script_spec_helper.rb +58 -0
  295. metadata +590 -0
@@ -0,0 +1,155 @@
1
+ module Logical
2
+ module Naf
3
+ class JobCreator
4
+ def queue_application(application,
5
+ application_run_group_restriction,
6
+ application_run_group_name,
7
+ application_run_group_limit = 1,
8
+ priority = 0,
9
+ affinities = [],
10
+ prerequisites = [],
11
+ enqueue = false)
12
+
13
+ # Before adding a job to the queue, check whether the number of
14
+ # jobs (running/queued) is equal to or greater than the application
15
+ # run group limit, or if enqueue_backlogs is set to false. If so,
16
+ # do not add the job to the queue
17
+ running_jobs = ::Naf::RunningJob.
18
+ select('application_run_group_limit, MAX(created_at) AS created_at, count(*)').
19
+ where('command = ? AND application_run_group_name = ?',
20
+ application.command, application_run_group_name).
21
+ group('application_run_group_name, application_run_group_limit').first
22
+
23
+ queued_jobs = ::Naf::QueuedJob.
24
+ select('application_run_group_limit, MAX(created_at) AS created_at, count(*)').
25
+ where('command = ? AND application_run_group_name = ?',
26
+ application.command, application_run_group_name).
27
+ group('application_run_group_name, application_run_group_limit').first
28
+
29
+ if enqueue == false && (running_jobs.present? || queued_jobs.present?)
30
+ group_limit = running_jobs.try(:application_run_group_limit).to_i + queued_jobs.try(:application_run_group_limit).to_i
31
+ total_jobs = running_jobs.try(:count).to_i + queued_jobs.try(:count).to_i
32
+
33
+ return if group_limit <= total_jobs
34
+ end
35
+
36
+ ::Naf::HistoricalJob.transaction do
37
+ historical_job = ::Naf::HistoricalJob.create!(application_id: application.id,
38
+ application_type_id: application.application_type_id,
39
+ command: application.command,
40
+ application_run_group_restriction_id: application_run_group_restriction.id,
41
+ application_run_group_name: application_run_group_name,
42
+ application_run_group_limit: application_run_group_limit,
43
+ priority: priority,
44
+ log_level: application.log_level)
45
+ historical_job.add_tags([::Naf::HistoricalJob::SYSTEM_TAGS[:pre_work]])
46
+
47
+ # Create historical job affinity tabs for each affinity associated with the historical job
48
+ affinities.each do |affinity|
49
+ affinity_parameter = ::Naf::ApplicationScheduleAffinityTab.
50
+ where(affinity_id: affinity.id,
51
+ application_schedule_id: application.application_schedule.try(:id)).
52
+ first.try(:affinity_parameter)
53
+ ::Naf::HistoricalJobAffinityTab.create(historical_job_id: historical_job.id,
54
+ affinity_id: affinity.id,
55
+ affinity_parameter: affinity_parameter)
56
+ end
57
+
58
+ historical_job.verify_prerequisites(prerequisites)
59
+ # Create historical job prerequisites for each prerequisite associated with the historical job
60
+ prerequisites.each do |prerequisite|
61
+ ::Naf::HistoricalJobPrerequisite.create(historical_job_id: historical_job.id,
62
+ prerequisite_historical_job_id: prerequisite.id)
63
+ end
64
+
65
+ create_queue_job(historical_job)
66
+
67
+ return historical_job
68
+ end
69
+ end
70
+
71
+ def queue_application_schedule(application_schedule, schedules_queued_already = [])
72
+ prerequisite_jobs = []
73
+
74
+ # Check if schedule has been queued
75
+ if schedules_queued_already.include? application_schedule.id
76
+ raise ::Naf::HistoricalJob::JobPrerequisiteLoop.new(application_schedule)
77
+ end
78
+
79
+ # Keep track of queued schedules
80
+ schedules_queued_already << application_schedule.id
81
+ # Queue application schedule prerequisites
82
+ application_schedule.prerequisites.each do |application_schedule_prerequisite|
83
+ prerequisite_jobs << queue_application_schedule(application_schedule_prerequisite, schedules_queued_already)
84
+ end
85
+
86
+ # Queue the application
87
+ return queue_application(application_schedule.application,
88
+ application_schedule.application_run_group_restriction,
89
+ application_schedule.application_run_group_name,
90
+ application_schedule.application_run_group_limit,
91
+ application_schedule.priority,
92
+ application_schedule.affinities,
93
+ prerequisite_jobs,
94
+ application_schedule.enqueue_backlogs)
95
+ end
96
+
97
+ # This method act similar to queue_application but is used for testing purpose
98
+ def queue_rails_job(command,
99
+ application_run_group_restriction = ::Naf::ApplicationRunGroupRestriction.limited_per_all_machines,
100
+ application_run_group_name = :command,
101
+ application_run_group_limit = 1,
102
+ priority = 0,
103
+ affinities = [],
104
+ prerequisites = [])
105
+ application_run_group_name = command if application_run_group_name == :command
106
+ ::Naf::HistoricalJob.transaction do
107
+ historical_job = ::Naf::HistoricalJob.create!(application_type_id: 1,
108
+ command: command,
109
+ application_run_group_restriction_id: application_run_group_restriction.id,
110
+ application_run_group_name: application_run_group_name,
111
+ application_run_group_limit: application_run_group_limit,
112
+ priority: priority)
113
+ affinities.each do |affinity|
114
+ ::Naf::HistoricalJobAffinityTab.create(historical_job_id: historical_job.id, affinity_id: affinity.id)
115
+ end
116
+
117
+ historical_job.verify_prerequisites(prerequisites)
118
+ prerequisites.each do |prerequisite|
119
+ ::Naf::HistoricalJobPrerequisite.create(historical_job_id: historical_job.id,
120
+ prerequisite_historical_job_id: prerequisite.id)
121
+ end
122
+
123
+ create_queue_job(historical_job)
124
+
125
+ return historical_job
126
+ end
127
+ end
128
+
129
+ def create_queue_job(historical_job)
130
+ queued_job = ::Naf::QueuedJob.new(application_id: historical_job.application_id,
131
+ application_type_id: historical_job.application_type_id,
132
+ command: historical_job.command,
133
+ application_run_group_restriction_id: historical_job.application_run_group_restriction_id,
134
+ application_run_group_name: historical_job.application_run_group_name,
135
+ application_run_group_limit: historical_job.application_run_group_limit,
136
+ priority: historical_job.priority)
137
+ queued_job.id = historical_job.id
138
+ queued_job.save!
139
+ end
140
+
141
+ def queue_test
142
+ queue_rails_job("#{self.class.name}.test")
143
+ end
144
+
145
+ def self.test(*foo)
146
+ seconds = rand 120 + 15
147
+ puts "TEST CALLED: #{Time.zone.now}: #{foo.inspect}: sleeping for #{seconds} seconds"
148
+ sleep(seconds)
149
+ puts "TEST DONE: #{Time.zone.now}: #{foo.inspect}"
150
+ end
151
+ end
152
+
153
+ MiddleClass = JobCreator
154
+ end
155
+ end
@@ -0,0 +1,167 @@
1
+ module Logical
2
+ module Naf
3
+ class JobFetcher
4
+ include ::Af::Application::SafeProxy
5
+
6
+ attr_reader :machine
7
+
8
+ def initialize(machine)
9
+ @machine = machine
10
+ end
11
+
12
+ def fetch_next_job
13
+ fetch_possible_jobs.each do |possible_job|
14
+ running_job = nil
15
+ ::Naf::HistoricalJob.lock_for_job_queue do
16
+ running_job = start_job(possible_job)
17
+ end
18
+
19
+ if running_job.present?
20
+ # Update tags
21
+ running_job.historical_job.remove_tags([::Naf::HistoricalJob::SYSTEM_TAGS[:pre_work]])
22
+ running_job.historical_job.add_tags([::Naf::HistoricalJob::SYSTEM_TAGS[:work]])
23
+
24
+ # found a job
25
+ parse_log_level(running_job)
26
+
27
+ return running_job
28
+ end
29
+ end
30
+
31
+ # no jobs found
32
+ return nil
33
+ end
34
+
35
+ private
36
+
37
+ # This method fetches queued jobs that can be started. In order for a job to
38
+ # run on a machine, we need to check affinities for historical_job_affinity_tabs
39
+ # and machine_affinity_slots.
40
+ #
41
+ # A job without affinity tabs can be run on any machine
42
+ # A job with affinity tabs can only run on machines:
43
+ # - that have matching affinity slot(s)
44
+ #
45
+ # A machine with non-required affinity slots can run jobs:
46
+ # - that don't have any affinity tabs
47
+ # - that have affinity tab(s) that match affinity slot(s)
48
+ # A machine with required affinity slots can run jobs:
49
+ # - that have affinity tab(s) that match the required affinity slot(s)
50
+ # and if other affinity tabs are present, they also need to match
51
+ # afffinity slots
52
+ #
53
+ def fetch_possible_jobs
54
+ possible_jobs = nil
55
+ if machine.machine_affinity_slots.select(&:required).present?
56
+ # Retrieve the machine's required affinities in order to not
57
+ # compute it several times.
58
+ required_machine_affinities = ::Naf::Machine.
59
+ select("ARRAY(
60
+ SELECT affinity_id
61
+ FROM #{::Naf.schema_name}.machine_affinity_slots
62
+ WHERE machine_id = #{machine.id} AND required = true
63
+ ORDER BY affinity_id) AS required_affinities").
64
+ group("required_affinities").
65
+ first.required_affinities
66
+
67
+ # Choose queued jobs that can be run by the machine
68
+ possible_jobs = ::Naf::QueuedJob.
69
+ select("#{::Naf.schema_name}.queued_jobs.id, #{::Naf.schema_name}.queued_jobs.priority, #{::Naf.schema_name}.queued_jobs.created_at").
70
+ weight_available_on_machine(machine).
71
+ runnable_by_machine(machine).
72
+ is_not_restricted_by_run_group(machine).
73
+ prerequisites_finished.
74
+ group("#{::Naf.schema_name}.queued_jobs.id, #{::Naf.schema_name}.queued_jobs.priority, #{::Naf.schema_name}.queued_jobs.created_at").
75
+ having("array(
76
+ select affinity_id::integer
77
+ from #{::Naf.schema_name}.historical_job_affinity_tabs
78
+ where historical_job_id = queued_jobs.id and affinity_id in (
79
+ select affinity_id
80
+ from #{::Naf.schema_name}.machine_affinity_slots
81
+ where machine_id = #{machine.id} and required = true)
82
+ order by affinity_id) = '#{required_machine_affinities}'").
83
+ order_by_priority.
84
+ limit(100)
85
+ elsif machine.machine_affinity_slots.present?
86
+ # Choose queued jobs that can be run by the machine
87
+ possible_jobs = ::Naf::QueuedJob.
88
+ weight_available_on_machine(machine).
89
+ runnable_by_machine(machine).
90
+ is_not_restricted_by_run_group(machine).
91
+ prerequisites_finished.
92
+ order_by_priority.limit(100)
93
+ else
94
+ # Machine can run any queued job
95
+ possible_jobs = ::Naf::QueuedJob.
96
+ weight_available_on_machine(machine).
97
+ is_not_restricted_by_run_group(machine).
98
+ prerequisites_finished.
99
+ order_by_priority.limit(100)
100
+ end
101
+ end
102
+
103
+ def start_job(possible_job)
104
+ sql = <<-SQL
105
+ UPDATE
106
+ #{::Naf::HistoricalJob.partition_table_name(possible_job.id)}
107
+ SET
108
+ started_at = NOW(),
109
+ started_on_machine_id = ?
110
+ WHERE
111
+ id = ? AND started_at IS NULL
112
+ RETURNING
113
+ *
114
+ SQL
115
+
116
+ historical_job = ::Naf::HistoricalJob.find_by_sql([sql, machine.id, possible_job.id]).first
117
+ if historical_job.present?
118
+ ::Naf::QueuedJob.delete(historical_job.id)
119
+ running_job = ::Naf::RunningJob.new(application_id: historical_job.application_id,
120
+ application_type_id: historical_job.application_type_id,
121
+ command: historical_job.command,
122
+ application_run_group_restriction_id: historical_job.application_run_group_restriction_id,
123
+ application_run_group_name: historical_job.application_run_group_name,
124
+ application_run_group_limit: historical_job.application_run_group_limit,
125
+ started_on_machine_id: historical_job.started_on_machine_id,
126
+ started_at: historical_job.started_at,
127
+ log_level: historical_job.log_level)
128
+ running_job.id = historical_job.id
129
+ running_job.save!
130
+
131
+ running_job
132
+ else
133
+ nil
134
+ end
135
+ end
136
+
137
+ def logger
138
+ return af_logger(self.class.name)
139
+ end
140
+
141
+ def parse_log_level(running_job)
142
+ log_levels = {}
143
+ unless machine.log_level.blank?
144
+ begin
145
+ log_level_hash = JSON.parse(machine.log_level)
146
+ log_levels.merge!(log_level_hash)
147
+ rescue StandardError => e
148
+ logger.error "couldn't parse machine.log_level: #{machine.log_level}: (#{e.message})"
149
+ end
150
+ end
151
+
152
+ unless running_job.application.nil? || running_job.application.log_level.blank?
153
+ begin
154
+ log_level_hash = JSON.parse(running_job.application.log_level)
155
+ log_levels.merge!(log_level_hash)
156
+ rescue StandardError => e
157
+ logger.error "couldn't parse running_job.application.log_level: #{running_job.application.log_level}: (#{e.message})"
158
+ end
159
+ end
160
+
161
+ running_job.log_level = log_levels.to_json
162
+ running_job.save!
163
+ end
164
+
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,27 @@
1
+ module Logical
2
+ module Naf
3
+ module JobStatuses
4
+ class Errored
5
+
6
+ def self.all(conditions)
7
+ <<-SQL
8
+ (
9
+ SELECT
10
+ j.*, null AS "historical_job_id"
11
+ FROM
12
+ "#{::Naf.schema_name}"."historical_jobs" AS j
13
+ WHERE
14
+ j.finished_at IS NOT NULL AND
15
+ (j.exit_status > 0 OR
16
+ j.request_to_terminate = true)
17
+ #{conditions}
18
+ ORDER BY
19
+ finished_at desc
20
+ )
21
+ SQL
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ module Logical
2
+ module Naf
3
+ module JobStatuses
4
+ class Finished
5
+
6
+ def self.all(conditions)
7
+ <<-SQL
8
+ (
9
+ SELECT
10
+ j.*, null AS "historical_job_id"
11
+ FROM
12
+ "#{::Naf.schema_name}"."historical_jobs" AS j
13
+ WHERE
14
+ (j.finished_at IS NOT NULL OR
15
+ j.request_to_terminate = true)
16
+ #{conditions}
17
+ ORDER BY
18
+ finished_at DESC NULLS LAST
19
+ )
20
+ SQL
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ module Logical
2
+ module Naf
3
+ module JobStatuses
4
+ class FinishedLessMinute
5
+
6
+ def self.all(conditions)
7
+ <<-SQL
8
+ (
9
+ SELECT
10
+ j.*, NULL AS "historical_job_id"
11
+ FROM
12
+ "#{::Naf.schema_name}"."historical_jobs" AS j
13
+ WHERE
14
+ j.finished_at > '#{Time.zone.now - 1.minute}'
15
+ #{conditions}
16
+ ORDER BY
17
+ finished_at DESC
18
+ )
19
+ SQL
20
+ end
21
+
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,32 @@
1
+ module Logical
2
+ module Naf
3
+ module JobStatuses
4
+ class Queued
5
+
6
+ def self.all(conditions)
7
+ <<-SQL
8
+ (
9
+ SELECT DISTINCT
10
+ j.*, jp."historical_job_id"
11
+ FROM
12
+ "#{::Naf.schema_name}"."historical_jobs" AS j
13
+ LEFT JOIN
14
+ "#{::Naf.schema_name}"."historical_job_prerequisites" AS jp
15
+ ON j."id" = jp."historical_job_id"
16
+ WHERE
17
+ j.finished_at IS NULL AND
18
+ j.request_to_terminate = false AND
19
+ jp.historical_job_id IS NULL AND
20
+ j.started_at IS NULL
21
+ #{conditions}
22
+ ORDER BY
23
+ created_at desc
24
+ )
25
+ SQL
26
+ end
27
+
28
+ end
29
+ end
30
+ end
31
+ end
32
+
@@ -0,0 +1,34 @@
1
+ module Logical
2
+ module Naf
3
+ module JobStatuses
4
+ class Running
5
+
6
+ def self.all(status = :running, conditions)
7
+ if status == :queued
8
+ order = "created_at"
9
+ direction = "desc"
10
+ else
11
+ order = "started_at"
12
+ direction = "desc"
13
+ end
14
+ <<-SQL
15
+ (
16
+ SELECT
17
+ j.*, null AS "historical_job_id"
18
+ FROM
19
+ "#{::Naf.schema_name}"."historical_jobs" AS j
20
+ WHERE
21
+ j.started_at IS NOT NULL AND
22
+ j.finished_at IS NULL AND
23
+ j.request_to_terminate = false
24
+ #{conditions}
25
+ ORDER BY
26
+ #{order} #{direction}
27
+ )
28
+ SQL
29
+ end
30
+
31
+ end
32
+ end
33
+ end
34
+ end