barbeque 0.0.1 → 0.0.10

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 (85) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -3
  3. data/Rakefile +2 -6
  4. data/app/assets/javascripts/barbeque/application.js +5 -0
  5. data/app/assets/javascripts/barbeque/job_definitions.coffee +10 -0
  6. data/app/assets/stylesheets/barbeque/application.scss +7 -0
  7. data/app/assets/stylesheets/barbeque/common.scss +22 -0
  8. data/app/assets/stylesheets/barbeque/job_definitions.scss +21 -0
  9. data/app/controllers/barbeque/api/application_controller.rb +22 -0
  10. data/app/controllers/barbeque/api/job_executions_controller.rb +35 -0
  11. data/app/controllers/barbeque/api/job_retries_controller.rb +28 -0
  12. data/app/controllers/barbeque/api/revision_locks_controller.rb +34 -0
  13. data/app/controllers/barbeque/apps_controller.rb +43 -0
  14. data/app/controllers/barbeque/job_definitions_controller.rb +86 -0
  15. data/app/controllers/barbeque/job_executions_controller.rb +19 -0
  16. data/app/controllers/barbeque/job_queues_controller.rb +59 -0
  17. data/app/controllers/barbeque/job_retries_controller.rb +10 -0
  18. data/app/helpers/barbeque/job_definitions_helper.rb +14 -0
  19. data/app/helpers/barbeque/job_executions_helper.rb +18 -0
  20. data/app/models/{api → barbeque/api}/application_resource.rb +3 -1
  21. data/app/models/{api → barbeque/api}/job_execution_resource.rb +1 -1
  22. data/app/models/{api → barbeque/api}/job_retry_resource.rb +1 -1
  23. data/app/models/barbeque/api/revision_lock_resource.rb +7 -0
  24. data/app/models/{app.rb → barbeque/app.rb} +1 -1
  25. data/app/models/barbeque/job_definition.rb +26 -0
  26. data/app/models/{job_execution.rb → barbeque/job_execution.rb} +7 -4
  27. data/app/models/{job_queue.rb → barbeque/job_queue.rb} +1 -1
  28. data/app/models/{job_retry.rb → barbeque/job_retry.rb} +7 -2
  29. data/app/models/{slack_notification.rb → barbeque/slack_notification.rb} +1 -1
  30. data/app/services/barbeque/message_enqueuing_service.rb +41 -0
  31. data/app/services/barbeque/message_retrying_service.rb +32 -0
  32. data/app/views/barbeque/apps/_form.html.haml +34 -0
  33. data/app/views/barbeque/apps/edit.html.haml +3 -0
  34. data/app/views/barbeque/apps/index.html.haml +24 -0
  35. data/app/views/barbeque/apps/new.html.haml +3 -0
  36. data/app/views/barbeque/apps/show.html.haml +47 -0
  37. data/app/views/barbeque/job_definitions/_form.html.haml +45 -0
  38. data/app/views/barbeque/job_definitions/_slack_notification_field.html.haml +35 -0
  39. data/app/views/barbeque/job_definitions/edit.html.haml +3 -0
  40. data/app/views/barbeque/job_definitions/index.html.haml +24 -0
  41. data/app/views/barbeque/job_definitions/new.html.haml +3 -0
  42. data/app/views/barbeque/job_definitions/show.html.haml +90 -0
  43. data/app/views/barbeque/job_definitions/stats.html.haml +52 -0
  44. data/app/views/barbeque/job_executions/show.html.haml +92 -0
  45. data/app/views/barbeque/job_queues/_form.html.haml +29 -0
  46. data/app/views/barbeque/job_queues/edit.html.haml +3 -0
  47. data/app/views/barbeque/job_queues/index.html.haml +22 -0
  48. data/app/views/barbeque/job_queues/new.html.haml +3 -0
  49. data/app/views/barbeque/job_queues/show.html.haml +22 -0
  50. data/app/views/barbeque/job_retries/show.html.haml +59 -0
  51. data/app/views/layouts/barbeque/_header.html.haml +10 -0
  52. data/app/views/layouts/barbeque/_sidebar.html.haml +16 -0
  53. data/app/views/layouts/barbeque/application.html.haml +24 -0
  54. data/app/views/layouts/barbeque/apps.html.haml +6 -0
  55. data/app/views/layouts/barbeque/job_definitions.html.haml +6 -0
  56. data/app/views/layouts/barbeque/job_executions.html.haml +5 -0
  57. data/app/views/layouts/barbeque/job_queues.html.haml +6 -0
  58. data/config/initializers/garage.rb +4 -0
  59. data/config/routes.rb +32 -0
  60. data/db/migrate/20160829023237_prefix_barbeque_to_tables.rb +10 -0
  61. data/lib/barbeque.rb +3 -5
  62. data/lib/barbeque/configuration.rb +19 -0
  63. data/lib/barbeque/docker_image.rb +20 -0
  64. data/lib/barbeque/engine.rb +11 -0
  65. data/lib/barbeque/execution_log.rb +51 -0
  66. data/lib/barbeque/message.rb +28 -0
  67. data/lib/barbeque/message/base.rb +29 -0
  68. data/lib/barbeque/message/invalid_message.rb +11 -0
  69. data/lib/barbeque/message/job_execution.rb +20 -0
  70. data/lib/barbeque/message/job_retry.rb +16 -0
  71. data/lib/barbeque/message_handler.rb +8 -0
  72. data/lib/barbeque/message_handler/job_execution.rb +86 -0
  73. data/lib/barbeque/message_handler/job_retry.rb +83 -0
  74. data/lib/barbeque/message_queue.rb +66 -0
  75. data/lib/barbeque/runner.rb +12 -0
  76. data/lib/barbeque/runner/docker.rb +34 -0
  77. data/lib/barbeque/slack_client.rb +48 -0
  78. data/lib/barbeque/version.rb +1 -1
  79. data/lib/barbeque/worker.rb +58 -0
  80. data/lib/tasks/barbeque_tasks.rake +9 -4
  81. metadata +272 -18
  82. data/app/assets/stylesheets/barbeque/application.css +0 -15
  83. data/app/models/application_record.rb +0 -3
  84. data/app/models/job_definition.rb +0 -14
  85. data/app/views/layouts/barbeque/application.html.erb +0 -14
@@ -0,0 +1,24 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %meta{ content: 'text/html; charset=UTF-8', 'http-equiv': 'Content-Type' }
5
+ %meta{ charset: 'UTF-8' }
6
+ %title Barbeque
7
+ %meta{ content: 'width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no', name: 'viewport' }
8
+ -# FIXME: Don't rely on others' CDN
9
+ %link{ href: 'https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css', rel: 'stylesheet', type: 'text/css' }
10
+ %link{ href: 'https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css', rel: 'stylesheet', type: 'text/css' }
11
+ = stylesheet_link_tag 'barbeque/application', media: 'all'
12
+ = javascript_include_tag 'barbeque/application'
13
+ = csrf_meta_tags
14
+
15
+ %body.skin-blue.sidebar-mini{ class: "#{controller_path.parameterize(separator: '_')}_controller #{action_name}_action" }
16
+ .wrapper
17
+ = render partial: 'layouts/barbeque/header'
18
+ = render partial: 'layouts/barbeque/sidebar'
19
+ .content-wrapper
20
+ - if content_for?(:header)
21
+ %section.content-header
22
+ = content_for(:header)
23
+ %section.content
24
+ = yield
@@ -0,0 +1,6 @@
1
+ - content_for(:header) do
2
+ %h1
3
+ .fa.fa-users
4
+ Applications
5
+
6
+ = render template: 'layouts/barbeque/application'
@@ -0,0 +1,6 @@
1
+ - content_for(:header) do
2
+ %h1
3
+ .fa.fa-tasks
4
+ Job Definitions
5
+
6
+ = render template: 'layouts/barbeque/application'
@@ -0,0 +1,5 @@
1
+ - content_for(:header) do
2
+ %h1
3
+ Job Executions
4
+
5
+ = render template: 'layouts/barbeque/application'
@@ -0,0 +1,6 @@
1
+ - content_for(:header) do
2
+ %h1
3
+ .fa.fa-cubes
4
+ Queues
5
+
6
+ = render template: 'layouts/barbeque/application'
@@ -0,0 +1,4 @@
1
+ require 'garage'
2
+
3
+ Garage.configure {}
4
+ Garage.configuration.strategy = Garage::Strategy::NoAuthentication
@@ -1,2 +1,34 @@
1
1
  Barbeque::Engine.routes.draw do
2
+ root to: 'apps#index'
3
+
4
+ resources :apps, except: :index
5
+
6
+ resources :job_definitions do
7
+ get :stats
8
+ get :execution_stats
9
+ end
10
+
11
+ resources :job_executions, only: :show do
12
+ post :retry
13
+
14
+ resources :job_retries, only: :show
15
+ end
16
+
17
+ resources :job_queues
18
+
19
+ scope :v1, module: 'api', as: :v1 do
20
+ resources :apps, only: [], param: :name, constraints: { name: /[\w-]+/ } do
21
+ resource :revision_lock, only: [:create, :destroy]
22
+ end
23
+
24
+ resources :job_executions, only: :show, param: :message_id,
25
+ constraints: { message_id: /[a-f\d]{8}-([a-f\d]{4}-){3}[a-f\d]{12}/ } do
26
+ resources :job_retries, only: [:create], path: 'retries'
27
+ end
28
+ end
29
+
30
+ scope :v2, module: 'api', as: :v2 do
31
+ resources :job_executions, only: :create, param: :message_id,
32
+ constraints: { message_id: /[a-f\d]{8}-([a-f\d]{4}-){3}[a-f\d]{12}/ }
33
+ end
2
34
  end
@@ -0,0 +1,10 @@
1
+ class PrefixBarbequeToTables < ActiveRecord::Migration[5.0]
2
+ def change
3
+ rename_table :apps, :barbeque_apps
4
+ rename_table :job_definitions, :barbeque_job_definitions
5
+ rename_table :job_executions, :barbeque_job_executions
6
+ rename_table :job_queues, :barbeque_job_queues
7
+ rename_table :job_retries, :barbeque_job_retries
8
+ rename_table :slack_notifications, :barbeque_slack_notifications
9
+ end
10
+ end
@@ -1,5 +1,3 @@
1
- require "barbeque/engine"
2
-
3
- module Barbeque
4
- # Your code goes here...
5
- end
1
+ require 'barbeque/docker_image'
2
+ require 'barbeque/engine'
3
+ require 'barbeque/execution_log'
@@ -0,0 +1,19 @@
1
+ require 'erb'
2
+ require 'yaml'
3
+ require 'hashie'
4
+
5
+ module Barbeque
6
+ module Configuration
7
+ def config
8
+ @config ||= build_config
9
+ end
10
+
11
+ def build_config
12
+ filename = Rails.root.join('config', 'barbeque.yml').to_s
13
+ hash = YAML.load(ERB.new(File.read(filename)).result)
14
+ Hashie::Mash.new(hash[Rails.env])
15
+ end
16
+ end
17
+
18
+ extend Configuration
19
+ end
@@ -0,0 +1,20 @@
1
+ module Barbeque
2
+ class DockerImage
3
+ DEFAULT_TAG = 'latest'
4
+
5
+ def initialize(str)
6
+ # See: https://github.com/docker/docker/blob/v1.10.2/image/spec/v1.md
7
+ result = str.match(%r{((?<registry>[^/]+)?/)?(?<repository>[\w./-]+)(:(?<tag>[\w.-]+))?\z})
8
+ @repository = result[:repository]
9
+ @tag = result[:tag] || DEFAULT_TAG
10
+ @registry = result[:registry] || ENV['BARBEQUE_DOCKER_REGISTRY']
11
+ end
12
+
13
+ attr_reader :registry, :repository
14
+ attr_accessor :tag
15
+
16
+ def to_s
17
+ [registry, "#{repository}:#{tag}"].compact.join('/')
18
+ end
19
+ end
20
+ end
@@ -1,5 +1,16 @@
1
1
  module Barbeque
2
2
  class Engine < ::Rails::Engine
3
3
  isolate_namespace Barbeque
4
+
5
+ config.before_configuration do
6
+ # Listing gems which are mountable engine or have railtie.
7
+ require 'adminlte2-rails'
8
+ require 'coffee-rails'
9
+ require 'hamlit'
10
+ require 'jquery-rails'
11
+ require 'kaminari'
12
+ require 'sass-rails'
13
+ require 'weak_parameters'
14
+ end
4
15
  end
5
16
  end
@@ -0,0 +1,51 @@
1
+ require 'aws-sdk'
2
+ require 'active_support'
3
+ require 'active_support/core_ext'
4
+
5
+ module Barbeque
6
+ class ExecutionLog
7
+ DEFAULT_S3_BUCKET_NAME = 'barbeque'
8
+
9
+ class << self
10
+ delegate :save, :load, to: :new
11
+ end
12
+
13
+ # @param [Barbeque::JobExecution,Barbeque::JobRetry] execution
14
+ # @param [Hash] log
15
+ def save(execution:, log:)
16
+ s3.put_object(
17
+ bucket: s3_bucket_name,
18
+ key: s3_key_for(execution: execution),
19
+ body: log.to_json,
20
+ )
21
+ end
22
+
23
+ # @param [Barbeque::JobExecution,Barbeque::JobRetry] execution
24
+ # @return [Hash] log
25
+ def load(execution:)
26
+ return {} if execution.pending?
27
+
28
+ s3_object = s3.get_object(
29
+ bucket: s3_bucket_name,
30
+ key: s3_key_for(execution: execution),
31
+ )
32
+ JSON.load(s3_object.body.read)
33
+ end
34
+
35
+ private
36
+
37
+ def s3_bucket_name
38
+ @s3_bucket_name ||= ENV['BARBEQUE_S3_BUCKET_NAME'] || DEFAULT_S3_BUCKET_NAME
39
+ end
40
+
41
+ # @param [Barbeque::JobExecution,Barbeque::JobRetry] execution
42
+ # @param [String] message_id
43
+ def s3_key_for(execution:)
44
+ File.join(execution.app.name, execution.job_definition.job, execution.message_id)
45
+ end
46
+
47
+ def s3
48
+ @s3 ||= Aws::S3::Client.new
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,28 @@
1
+ require 'barbeque/message/base'
2
+ require 'barbeque/message/invalid_message'
3
+ require 'barbeque/message/job_execution'
4
+ require 'barbeque/message/job_retry'
5
+
6
+ module Barbeque
7
+ module Message
8
+ class << self
9
+ # @param [Aws::SQS::Types::Message] raw_message
10
+ # @return [Barbeque::Message::Base]
11
+ def parse(raw_message)
12
+ body = JSON.parse(raw_message.body)
13
+ klass = find_class(body['Type'])
14
+ klass.new(raw_message, body)
15
+ rescue JSON::ParserError
16
+ InvalidMessage.new(raw_message, {})
17
+ end
18
+
19
+ private
20
+
21
+ def find_class(type)
22
+ Message.const_get(type, false)
23
+ rescue NameError
24
+ InvalidMessage
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ module Barbeque
2
+ module Message
3
+ # A model wrapping Aws::SQS::Types::Message.
4
+ class Base
5
+ attr_reader :id # [String] Barbeque::JobExecution is associated via `message_id`
6
+ attr_reader :receipt_handle # [String] Used to ack a message
7
+ attr_reader :type # [String] "JobExecution", "JobRetry", etc
8
+
9
+ # @param [Aws::SQS::Types::Message] raw_message
10
+ # @param [Hash] parse result of `raw_message.body`
11
+ def initialize(raw_message, message_body)
12
+ assign_body(message_body)
13
+ @id = raw_message.message_id
14
+ @receipt_handle = raw_message.receipt_handle
15
+ end
16
+
17
+ # To distinguish with `Barbeque::Message::InvalidMessage`
18
+ def valid?
19
+ true
20
+ end
21
+
22
+ private
23
+
24
+ def assign_body(message_body)
25
+ @type = message_body['Type']
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,11 @@
1
+ require 'barbeque/message/base'
2
+
3
+ module Barbeque
4
+ module Message
5
+ class InvalidMessage < Base
6
+ def valid?
7
+ false
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,20 @@
1
+ require 'barbeque/message/base'
2
+
3
+ module Barbeque
4
+ module Message
5
+ class JobExecution < Base
6
+ attr_reader :body # [Object] free-format JSON
7
+ attr_reader :application # [String] To specify `job_definitions.application_id`
8
+ attr_reader :job # [String] To specify `job_definitions.name`
9
+
10
+ private
11
+
12
+ def assign_body(message_body)
13
+ super
14
+ @application = message_body['Application']
15
+ @job = message_body['Job']
16
+ @body = message_body['Message']
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ require 'barbeque/message/base'
2
+
3
+ module Barbeque
4
+ module Message
5
+ class JobRetry < Base
6
+ attr_reader :retry_message_id # [String] JobExection's message_id
7
+
8
+ private
9
+
10
+ def assign_body(message_body)
11
+ super
12
+ @retry_message_id = message_body['RetryMessageId']
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,8 @@
1
+ module Barbeque
2
+ module MessageHandler
3
+ class DuplicatedExecution < StandardError; end
4
+ end
5
+ end
6
+
7
+ require 'barbeque/message_handler/job_execution'
8
+ require 'barbeque/message_handler/job_retry'
@@ -0,0 +1,86 @@
1
+ require 'barbeque/docker_image'
2
+ require 'barbeque/execution_log'
3
+ require 'barbeque/runner'
4
+ require 'barbeque/slack_client'
5
+
6
+ module Barbeque
7
+ module MessageHandler
8
+ class JobExecution
9
+ # @param [Barbeque::Message::JobExecution] message
10
+ # @param [Barbeque::JobQueue] job_queue
11
+ def initialize(message:, job_queue:)
12
+ @message = message
13
+ @job_queue = job_queue
14
+ end
15
+
16
+ def run
17
+ job_execution = Barbeque::JobExecution.find_or_initialize_by(message_id: @message.id)
18
+ raise DuplicatedExecution if job_execution.persisted?
19
+ job_execution.update!(job_definition: job_definition, job_queue_id: @job_queue.id)
20
+
21
+ stdout, stderr, status = run_command
22
+ job_execution.update!(status: status.success? ? :success : :failed, finished_at: Time.now)
23
+ notify_slack(job_execution, status)
24
+
25
+ log_result(job_execution, stdout, stderr)
26
+ end
27
+
28
+ private
29
+
30
+ def log_result(execution, stdout, stderr)
31
+ log = { message: @message.body.to_json, stdout: stdout, stderr: stderr }
32
+ Barbeque::ExecutionLog.save(execution: execution, log: log)
33
+ end
34
+
35
+ def notify_slack(job_execution, status)
36
+ return if job_execution.slack_notification.nil?
37
+
38
+ client = Barbeque::SlackClient.new(job_execution.slack_notification.channel)
39
+ if status.success?
40
+ if job_execution.slack_notification.notify_success
41
+ client.notify_success("*[SUCCESS]* Succeeded to execute #{job_execution_link(job_execution)}")
42
+ end
43
+ else
44
+ client.notify_failure(
45
+ "*[FAILURE]* Failed to execute #{job_execution_link(job_execution)}" \
46
+ " #{job_execution.slack_notification.failure_notification_text}"
47
+ )
48
+ end
49
+ end
50
+
51
+ def job_execution_link(job_execution)
52
+ "<#{job_execution_url(job_execution)}|#{job_execution.job_definition.job} ##{job_execution.id}>"
53
+ end
54
+
55
+ def job_execution_url(job_execution)
56
+ Barbeque::Engine.routes.url_helpers.job_execution_url(job_execution, host: ENV['BARBEQUE_HOST'])
57
+ end
58
+
59
+ # @return [String] stdout
60
+ # @return [String] stderr
61
+ # @return [Process::Status] status
62
+ def run_command
63
+ image = DockerImage.new(job_definition.app.docker_image)
64
+ runner = Runner.create(docker_image: image)
65
+ runner.run(job_definition.command, job_envs)
66
+ end
67
+
68
+ def job_envs
69
+ {
70
+ 'BARBEQUE_JOB' => @message.job,
71
+ 'BARBEQUE_MESSAGE' => @message.body.to_json,
72
+ 'BARBEQUE_MESSAGE_ID' => @message.id,
73
+ 'BARBEQUE_QUEUE_NAME' => @job_queue.name,
74
+ 'BARBEQUE_RETRY_COUNT' => '0',
75
+ }
76
+ end
77
+
78
+ def job_definition
79
+ @job_definition ||= Barbeque::JobDefinition.joins(:app).find_by!(
80
+ job: @message.job,
81
+ barbeque_apps: { name: @message.application },
82
+ )
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,83 @@
1
+ require 'barbeque/docker_image'
2
+ require 'barbeque/execution_log'
3
+ require 'barbeque/runner'
4
+ require 'barbeque/slack_client'
5
+
6
+ module Barbeque
7
+ module MessageHandler
8
+ class JobRetry
9
+ # @param [Barbeque::Message::JobExecution] message
10
+ # @param [Barbeque::JobQueue] job_queue
11
+ def initialize(message:, job_queue:)
12
+ @message = message
13
+ @job_queue = job_queue
14
+ end
15
+
16
+ def run
17
+ job_retry = Barbeque::JobRetry.find_or_initialize_by(message_id: @message.id)
18
+ job_retry.update!(job_execution: job_execution)
19
+ job_execution.update!(status: 'retried')
20
+
21
+ stdout, stderr, result = run_command
22
+ status = result.success? ? :success : :failed
23
+ job_retry.update!(status: status, finished_at: Time.now)
24
+ job_execution.update!(status: status)
25
+ notify_slack(job_retry, result)
26
+
27
+ log_result(job_retry, stdout, stderr)
28
+ end
29
+
30
+ private
31
+
32
+ def log_result(job_retry, stdout, stderr)
33
+ log = { stdout: stdout, stderr: stderr }
34
+ Barbeque::ExecutionLog.save(execution: job_retry, log: log)
35
+ end
36
+
37
+ # @param [Barbeque::JobRetry] job_retry
38
+ # @param [Process::Status] result
39
+ def notify_slack(job_retry, result)
40
+ return if job_retry.slack_notification.nil?
41
+
42
+ client = Barbeque::SlackClient.new(job_retry.slack_notification.channel)
43
+ if result.success?
44
+ if job_retry.slack_notification.notify_success
45
+ client.notify_success("*[SUCCESS]* Succeeded to retry #{job_retry_link(job_retry)}")
46
+ end
47
+ else
48
+ client.notify_failure(
49
+ "*[FAILURE]* Failed to retry #{job_retry_link(job_retry)}" \
50
+ " #{job_execution.slack_notification.failure_notification_text}"
51
+ )
52
+ end
53
+ end
54
+
55
+ def job_retry_link(job_retry)
56
+ url = Barbeque::Engine.routes.url_helpers.job_execution_job_retry_url(
57
+ job_retry.job_execution, job_retry, host: ENV['BARBEQUE_HOST']
58
+ )
59
+ "<#{url}|#{job_retry.job_definition.job}'s retry ##{job_retry.id}>"
60
+ end
61
+
62
+ def job_execution
63
+ @job_execution ||= Barbeque::JobExecution.find_by!(message_id: @message.retry_message_id)
64
+ end
65
+
66
+ def run_command
67
+ image = DockerImage.new(job_execution.app.docker_image)
68
+ runner = Runner.create(docker_image: image)
69
+ runner.run(job_execution.job_definition.command, job_envs)
70
+ end
71
+
72
+ def job_envs
73
+ {
74
+ 'BARBEQUE_JOB' => job_execution.job_definition.job,
75
+ 'BARBEQUE_MESSAGE' => job_execution.execution_log['message'],
76
+ 'BARBEQUE_MESSAGE_ID' => @message.retry_message_id,
77
+ 'BARBEQUE_QUEUE_NAME' => @job_queue.name,
78
+ 'BARBEQUE_RETRY_COUNT' => job_execution.job_retries.count.to_s,
79
+ }
80
+ end
81
+ end
82
+ end
83
+ end