ground_control-api 0.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.
- checksums.yaml +7 -0
- data/.github/dependabot.yml +24 -0
- data/.github/workflows/ci.yml +59 -0
- data/.github/workflows/claude-code-review.yml +24 -0
- data/.github/workflows/claude.yml +38 -0
- data/.github/workflows/codeql-actions.yml +28 -0
- data/.github/workflows/release.yml +89 -0
- data/.lefthook/bundle-sync.sh +58 -0
- data/.lefthook/lib/git-upstream.sh +13 -0
- data/.lefthook/verify-signatures.sh +46 -0
- data/.lefthook/whitespace-check.sh +8 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +16 -0
- data/CLAUDE.md +78 -0
- data/MIT-LICENSE +20 -0
- data/README.md +130 -0
- data/Rakefile +8 -0
- data/app/controllers/concerns/ground_control/api/adapter_features.rb +36 -0
- data/app/controllers/concerns/ground_control/api/error_handling.rb +25 -0
- data/app/controllers/concerns/ground_control/api/job_filters.rb +42 -0
- data/app/controllers/ground_control/api/application_controller.rb +24 -0
- data/app/controllers/ground_control/api/applications_controller.rb +13 -0
- data/app/controllers/ground_control/api/bulk_discards_controller.rb +21 -0
- data/app/controllers/ground_control/api/bulk_retries_controller.rb +15 -0
- data/app/controllers/ground_control/api/discards_controller.rb +14 -0
- data/app/controllers/ground_control/api/dispatches_controller.rb +14 -0
- data/app/controllers/ground_control/api/features_controller.rb +11 -0
- data/app/controllers/ground_control/api/jobs_controller.rb +37 -0
- data/app/controllers/ground_control/api/queues/pauses_controller.rb +29 -0
- data/app/controllers/ground_control/api/queues_controller.rb +26 -0
- data/app/controllers/ground_control/api/recurring_tasks_controller.rb +40 -0
- data/app/controllers/ground_control/api/retries_controller.rb +14 -0
- data/app/controllers/ground_control/api/workers_controller.rb +33 -0
- data/app/resources/ground_control/api/application_resource.rb +12 -0
- data/app/resources/ground_control/api/base_resource.rb +13 -0
- data/app/resources/ground_control/api/job_resource.rb +46 -0
- data/app/resources/ground_control/api/page_resource.rb +47 -0
- data/app/resources/ground_control/api/queue_resource.rb +22 -0
- data/app/resources/ground_control/api/recurring_task_resource.rb +17 -0
- data/app/resources/ground_control/api/server_resource.rb +10 -0
- data/app/resources/ground_control/api/worker_resource.rb +14 -0
- data/config/routes.rb +27 -0
- data/lefthook.yml +17 -0
- data/lib/ground_control/api/engine.rb +18 -0
- data/lib/ground_control/api/version.rb +7 -0
- data/lib/ground_control/api.rb +15 -0
- data/sig/ground_control/api.rbs +6 -0
- data/spec/spec_helper.rb +15 -0
- metadata +136 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GroundControl
|
|
4
|
+
module Api
|
|
5
|
+
module AdapterFeatures
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def supported_job_statuses
|
|
11
|
+
MissionControl::Jobs::Current.server.queue_adapter.supported_job_statuses
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def queue_pausing_supported?
|
|
15
|
+
MissionControl::Jobs::Current.server.queue_adapter.supports_queue_pausing?
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def workers_exposed?
|
|
19
|
+
MissionControl::Jobs::Current.server.queue_adapter.exposes_workers?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def recurring_tasks_supported?
|
|
23
|
+
MissionControl::Jobs::Current.server.queue_adapter.supports_recurring_tasks?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def adapter_features
|
|
27
|
+
{
|
|
28
|
+
statuses: supported_job_statuses,
|
|
29
|
+
queue_pausing: queue_pausing_supported?,
|
|
30
|
+
workers: workers_exposed?,
|
|
31
|
+
recurring_tasks: recurring_tasks_supported?
|
|
32
|
+
}
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GroundControl
|
|
4
|
+
module Api
|
|
5
|
+
module ErrorHandling
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
included do
|
|
9
|
+
rescue_from ActiveJob::Errors::JobNotFoundError do |_exception|
|
|
10
|
+
render json: { error: "Job not found" }, status: :not_found
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
rescue_from MissionControl::Jobs::Errors::ResourceNotFound do |exception|
|
|
14
|
+
render json: { error: exception.message }, status: :not_found
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
rescue_from StandardError do |exception|
|
|
18
|
+
raise exception unless Rails.env.production?
|
|
19
|
+
|
|
20
|
+
render json: { error: "Internal server error" }, status: :internal_server_error
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GroundControl
|
|
4
|
+
module Api
|
|
5
|
+
module JobFilters
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
included do
|
|
9
|
+
before_action :set_filters
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def set_filters
|
|
15
|
+
filter = params[:filter] || {}
|
|
16
|
+
|
|
17
|
+
job_class_name = filter[:job_class_name]&.strip.presence
|
|
18
|
+
queue_name = filter[:queue_name]&.strip.presence
|
|
19
|
+
finished_at = build_finished_at_range(filter)
|
|
20
|
+
|
|
21
|
+
@job_filters = {
|
|
22
|
+
job_class_name: job_class_name,
|
|
23
|
+
queue_name: queue_name,
|
|
24
|
+
finished_at: finished_at
|
|
25
|
+
}.compact
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def build_finished_at_range(filter)
|
|
29
|
+
start_time = filter[:finished_at_start].present? ? Time.zone.parse(filter[:finished_at_start]) : nil
|
|
30
|
+
end_time = filter[:finished_at_end].present? ? Time.zone.parse(filter[:finished_at_end]) : nil
|
|
31
|
+
|
|
32
|
+
return nil unless start_time || end_time
|
|
33
|
+
|
|
34
|
+
(start_time..end_time)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def active_filters?
|
|
38
|
+
@job_filters.present?
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GroundControl
|
|
4
|
+
module Api
|
|
5
|
+
class ApplicationController < ActionController::API
|
|
6
|
+
include MissionControl::Jobs::ApplicationScoped
|
|
7
|
+
include JobFilters
|
|
8
|
+
include AdapterFeatures
|
|
9
|
+
include ErrorHandling
|
|
10
|
+
|
|
11
|
+
before_action :authenticate!
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def authenticate!
|
|
16
|
+
GroundControl::Api.authenticate_with&.call(self)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def serialize(resource)
|
|
20
|
+
resource.serializable_hash
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GroundControl
|
|
4
|
+
module Api
|
|
5
|
+
class ApplicationsController < ApplicationController
|
|
6
|
+
def index
|
|
7
|
+
applications = MissionControl::Jobs.applications
|
|
8
|
+
|
|
9
|
+
render json: { data: ApplicationResource.new(applications).serializable_hash }
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GroundControl
|
|
4
|
+
module Api
|
|
5
|
+
class BulkDiscardsController < ApplicationController
|
|
6
|
+
def create
|
|
7
|
+
jobs = ActiveJob.jobs.where(**@job_filters).failed
|
|
8
|
+
|
|
9
|
+
if active_filters?
|
|
10
|
+
count = [jobs.count, 3000].min
|
|
11
|
+
jobs.limit(3000).discard_all
|
|
12
|
+
else
|
|
13
|
+
count = jobs.count
|
|
14
|
+
jobs.discard_all
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
render json: { message: "Discarded #{count} jobs" }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GroundControl
|
|
4
|
+
module Api
|
|
5
|
+
class BulkRetriesController < ApplicationController
|
|
6
|
+
def create
|
|
7
|
+
jobs = ActiveJob.jobs.where(**@job_filters).failed
|
|
8
|
+
count = [jobs.count, 3000].min
|
|
9
|
+
jobs.limit(3000).retry_all
|
|
10
|
+
|
|
11
|
+
render json: { message: "Retried #{count} jobs" }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GroundControl
|
|
4
|
+
module Api
|
|
5
|
+
class DiscardsController < ApplicationController
|
|
6
|
+
def create
|
|
7
|
+
job = ActiveJob.jobs.find_by_id(params[:job_id])
|
|
8
|
+
job.discard
|
|
9
|
+
|
|
10
|
+
render json: { message: "Discarded job #{job.job_id}" }
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GroundControl
|
|
4
|
+
module Api
|
|
5
|
+
class DispatchesController < ApplicationController
|
|
6
|
+
def create
|
|
7
|
+
job = ActiveJob.jobs.find_by_id(params[:job_id])
|
|
8
|
+
job.dispatch
|
|
9
|
+
|
|
10
|
+
render json: { message: "Dispatched job #{job.job_id}" }
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GroundControl
|
|
4
|
+
module Api
|
|
5
|
+
class JobsController < ApplicationController
|
|
6
|
+
def index
|
|
7
|
+
status = params[:status]
|
|
8
|
+
jobs = ActiveJob.jobs.where(**@job_filters).with_status(status)
|
|
9
|
+
page = MissionControl::Jobs::Page.new(jobs, page: params[:page].to_i, page_size: GroundControl::Api.page_size)
|
|
10
|
+
|
|
11
|
+
job_class_names = begin
|
|
12
|
+
ActiveJob.jobs.with_status(status).job_class_names
|
|
13
|
+
rescue
|
|
14
|
+
[]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
queue_names = ActiveJob.queues.map(&:name)
|
|
18
|
+
|
|
19
|
+
render json: {
|
|
20
|
+
data: PageResource.new(page, inner_resource_class: JobResource).serializable_hash,
|
|
21
|
+
meta: {
|
|
22
|
+
status: status,
|
|
23
|
+
filters: @job_filters,
|
|
24
|
+
job_class_names: job_class_names,
|
|
25
|
+
queue_names: queue_names
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def show
|
|
31
|
+
job = ActiveJob.jobs.find_by_id(params[:id])
|
|
32
|
+
|
|
33
|
+
render json: { data: JobResource.new(job).serializable_hash }
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GroundControl
|
|
4
|
+
module Api
|
|
5
|
+
module Queues
|
|
6
|
+
class PausesController < ApplicationController
|
|
7
|
+
before_action :set_queue
|
|
8
|
+
|
|
9
|
+
def create
|
|
10
|
+
@queue.pause
|
|
11
|
+
|
|
12
|
+
render json: { message: "Queue paused" }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def destroy
|
|
16
|
+
@queue.resume
|
|
17
|
+
|
|
18
|
+
render json: { message: "Queue resumed" }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def set_queue
|
|
24
|
+
@queue = ActiveJob.queues[params[:queue_id]]
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GroundControl
|
|
4
|
+
module Api
|
|
5
|
+
class QueuesController < ApplicationController
|
|
6
|
+
def index
|
|
7
|
+
queues = ActiveJob.queues.sort_by(&:name)
|
|
8
|
+
|
|
9
|
+
render json: {
|
|
10
|
+
data: QueueResource.new(queues).serializable_hash,
|
|
11
|
+
meta: { features: adapter_features }
|
|
12
|
+
}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def show
|
|
16
|
+
queue = ActiveJob.queues[params[:id]]
|
|
17
|
+
page = MissionControl::Jobs::Page.new(queue.jobs, page: params[:page].to_i, page_size: GroundControl::Api.page_size)
|
|
18
|
+
|
|
19
|
+
render json: {
|
|
20
|
+
data: QueueResource.new(queue).serializable_hash,
|
|
21
|
+
jobs: PageResource.new(page, inner_resource_class: JobResource).serializable_hash
|
|
22
|
+
}
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GroundControl
|
|
4
|
+
module Api
|
|
5
|
+
class RecurringTasksController < ApplicationController
|
|
6
|
+
before_action :ensure_recurring_tasks_supported
|
|
7
|
+
|
|
8
|
+
def index
|
|
9
|
+
tasks = MissionControl::Jobs::Current.server.recurring_tasks
|
|
10
|
+
|
|
11
|
+
render json: { data: RecurringTaskResource.new(tasks).serializable_hash }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def show
|
|
15
|
+
task = MissionControl::Jobs::Current.server.find_recurring_task(params[:id])
|
|
16
|
+
page = MissionControl::Jobs::Page.new(task.jobs, page: params[:page].to_i, page_size: GroundControl::Api.page_size)
|
|
17
|
+
|
|
18
|
+
render json: {
|
|
19
|
+
data: RecurringTaskResource.new(task).serializable_hash,
|
|
20
|
+
jobs: PageResource.new(page, inner_resource_class: JobResource).serializable_hash
|
|
21
|
+
}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def update
|
|
25
|
+
task = MissionControl::Jobs::Current.server.find_recurring_task(params[:id])
|
|
26
|
+
task.enqueue
|
|
27
|
+
|
|
28
|
+
render json: { message: "Enqueued recurring task #{task.id}" }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def ensure_recurring_tasks_supported
|
|
34
|
+
unless recurring_tasks_supported?
|
|
35
|
+
render json: { error: "Recurring tasks not supported by this adapter" }, status: :not_found
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GroundControl
|
|
4
|
+
module Api
|
|
5
|
+
class RetriesController < ApplicationController
|
|
6
|
+
def create
|
|
7
|
+
job = ActiveJob.jobs.failed.find_by_id(params[:job_id])
|
|
8
|
+
job.retry
|
|
9
|
+
|
|
10
|
+
render json: { message: "Retried job #{job.job_id}" }
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GroundControl
|
|
4
|
+
module Api
|
|
5
|
+
class WorkersController < ApplicationController
|
|
6
|
+
before_action :ensure_workers_exposed
|
|
7
|
+
|
|
8
|
+
def index
|
|
9
|
+
page = MissionControl::Jobs::Page.new(
|
|
10
|
+
MissionControl::Jobs::Current.server.workers_relation,
|
|
11
|
+
page: params[:page].to_i,
|
|
12
|
+
page_size: GroundControl::Api.page_size
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
render json: { data: PageResource.new(page, inner_resource_class: WorkerResource).serializable_hash }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def show
|
|
19
|
+
worker = MissionControl::Jobs::Current.server.find_worker(params[:id])
|
|
20
|
+
|
|
21
|
+
render json: { data: WorkerResource.new(worker).serializable_hash }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def ensure_workers_exposed
|
|
27
|
+
unless workers_exposed?
|
|
28
|
+
render json: { error: "Workers not supported by this adapter" }, status: :not_found
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GroundControl
|
|
4
|
+
module Api
|
|
5
|
+
class JobResource < BaseResource
|
|
6
|
+
attribute :job_id, &:job_id
|
|
7
|
+
attribute :job_class_name, &:job_class_name
|
|
8
|
+
attribute :queue_name, &:queue_name
|
|
9
|
+
|
|
10
|
+
attribute :status do |job|
|
|
11
|
+
job.status.to_s
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
attribute :arguments do |job|
|
|
15
|
+
if job.respond_to?(:filtered_raw_data) && job.filtered_raw_data
|
|
16
|
+
job.filtered_raw_data
|
|
17
|
+
else
|
|
18
|
+
job.arguments
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
attribute :priority, &:priority
|
|
23
|
+
attribute :executions, &:executions
|
|
24
|
+
attribute :scheduled_at, &:scheduled_at
|
|
25
|
+
attribute :finished_at, &:finished_at
|
|
26
|
+
attribute :started_at, &:started_at
|
|
27
|
+
attribute :failed_at, &:failed_at
|
|
28
|
+
|
|
29
|
+
attribute :last_execution_error do |job|
|
|
30
|
+
error = job.last_execution_error
|
|
31
|
+
next nil if error.nil?
|
|
32
|
+
|
|
33
|
+
{
|
|
34
|
+
error_class: error.error_class,
|
|
35
|
+
message: error.message,
|
|
36
|
+
backtrace: error.backtrace
|
|
37
|
+
}
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
attribute :blocked_by, &:blocked_by
|
|
41
|
+
attribute :blocked_until, &:blocked_until
|
|
42
|
+
attribute :worker_id, &:worker_id
|
|
43
|
+
attribute :raw_data, &:raw_data
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GroundControl
|
|
4
|
+
module Api
|
|
5
|
+
class PageResource
|
|
6
|
+
include Alba::Resource
|
|
7
|
+
|
|
8
|
+
transform_keys :lower_camel
|
|
9
|
+
|
|
10
|
+
attribute :page do |page|
|
|
11
|
+
page.index
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
attribute :page_size, &:page_size
|
|
15
|
+
|
|
16
|
+
attribute :total_count do |page|
|
|
17
|
+
count = page.total_count
|
|
18
|
+
count.infinite? ? nil : count
|
|
19
|
+
rescue NoMethodError
|
|
20
|
+
count
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
attribute :pages_count, &:pages_count
|
|
24
|
+
|
|
25
|
+
attribute :first do |page|
|
|
26
|
+
page.first?
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
attribute :last do |page|
|
|
30
|
+
page.last?
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
attribute :records do |page|
|
|
34
|
+
if @inner_resource_class
|
|
35
|
+
@inner_resource_class.new(page.records).serializable_hash
|
|
36
|
+
else
|
|
37
|
+
page.records.map(&:to_h)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def initialize(object, inner_resource_class: nil)
|
|
42
|
+
@inner_resource_class = inner_resource_class
|
|
43
|
+
super(object)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GroundControl
|
|
4
|
+
module Api
|
|
5
|
+
class QueueResource < BaseResource
|
|
6
|
+
attribute :id do |queue|
|
|
7
|
+
queue.name.parameterize
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
attribute :name, &:name
|
|
11
|
+
attribute :size, &:size
|
|
12
|
+
|
|
13
|
+
attribute :active do |queue|
|
|
14
|
+
queue.active?
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
attribute :paused do |queue|
|
|
18
|
+
queue.paused?
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GroundControl
|
|
4
|
+
module Api
|
|
5
|
+
class RecurringTaskResource < BaseResource
|
|
6
|
+
attribute :id, &:id
|
|
7
|
+
attribute :job_class_name, &:job_class_name
|
|
8
|
+
attribute :command, &:command
|
|
9
|
+
attribute :arguments, &:arguments
|
|
10
|
+
attribute :schedule, &:schedule
|
|
11
|
+
attribute :last_enqueued_at, &:last_enqueued_at
|
|
12
|
+
attribute :next_time, &:next_time
|
|
13
|
+
attribute :queue_name, &:queue_name
|
|
14
|
+
attribute :priority, &:priority
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GroundControl
|
|
4
|
+
module Api
|
|
5
|
+
class WorkerResource < BaseResource
|
|
6
|
+
attribute :id, &:id
|
|
7
|
+
attribute :name, &:name
|
|
8
|
+
attribute :hostname, &:hostname
|
|
9
|
+
attribute :last_heartbeat_at, &:last_heartbeat_at
|
|
10
|
+
attribute :configuration, &:configuration
|
|
11
|
+
attribute :raw_data, &:raw_data
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
GroundControl::Api::Engine.routes.draw do
|
|
4
|
+
resources :applications, only: [:index] do
|
|
5
|
+
resources :queues, only: [:index, :show] do
|
|
6
|
+
scope module: :queues do
|
|
7
|
+
resource :pause, only: [:create, :destroy]
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
resources :jobs, only: [:show] do
|
|
12
|
+
resource :retry, only: :create
|
|
13
|
+
resource :discard, only: :create
|
|
14
|
+
resource :dispatch, only: :create
|
|
15
|
+
|
|
16
|
+
collection do
|
|
17
|
+
resource :bulk_retries, only: :create
|
|
18
|
+
resource :bulk_discards, only: :create
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
resources :jobs, only: :index, path: ":status/jobs"
|
|
23
|
+
resources :workers, only: [:index, :show]
|
|
24
|
+
resources :recurring_tasks, only: [:index, :show, :update]
|
|
25
|
+
resource :features, only: [:show]
|
|
26
|
+
end
|
|
27
|
+
end
|
data/lefthook.yml
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Lefthook manages git hooks for pre-push checks.
|
|
2
|
+
#
|
|
3
|
+
# Install: brew install lefthook && lefthook install
|
|
4
|
+
# Skip: LEFTHOOK=0 git push
|
|
5
|
+
|
|
6
|
+
pre-push:
|
|
7
|
+
parallel: true
|
|
8
|
+
commands:
|
|
9
|
+
whitespace:
|
|
10
|
+
run: .lefthook/whitespace-check.sh
|
|
11
|
+
signed-commits:
|
|
12
|
+
run: .lefthook/verify-signatures.sh
|
|
13
|
+
rubocop:
|
|
14
|
+
run: bundle exec rubocop
|
|
15
|
+
glob: "**/*.rb"
|
|
16
|
+
rspec:
|
|
17
|
+
run: bundle exec rspec --fail-fast
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GroundControl
|
|
4
|
+
module Api
|
|
5
|
+
class Engine < ::Rails::Engine
|
|
6
|
+
isolate_namespace GroundControl::Api
|
|
7
|
+
|
|
8
|
+
initializer "ground_control.api.middleware" do |app|
|
|
9
|
+
app.middleware.use ActionDispatch::Flash
|
|
10
|
+
app.middleware.use Rack::MethodOverride
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
config.after_initialize do
|
|
14
|
+
require "mission_control/jobs/engine"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|