panoptic 0.1.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 92d310e17406ea0681469b5f4f4ff1d456b9d24ad4c89d4498adc87643f9ed8c
4
- data.tar.gz: 9e2faccbac6daf2820c63202adc28292918934e596462443b046be5d4b874c72
3
+ metadata.gz: 0c9c24666cf21962529d267d1432b25fb3b2ba813ec8997c5a50373da1b76f2b
4
+ data.tar.gz: 72eae4c018c7585f2abf3ec7968c94e9ccf223783d3f730e75d5796ff06b2f7b
5
5
  SHA512:
6
- metadata.gz: b596a1d4224631ffb6f1e619958bbed94c20c4bfcb6c64fd967045efd40d785be72d2393b1317dc239866be6ba35952eebbf3eeac22e02cc270626475f325328
7
- data.tar.gz: b07d2227e30e712aedaeb5d1213991fba6cb5e467f67466795c3b1fd8d10a92e9fa5c9a98e86f6afc2a71bd2ac4de963c3a5de2a49a3f74494973c666227d4ba
6
+ metadata.gz: 248f586bdf987718900bd83c4e9989b2f6b617853637e2a9ac690b94723e01cd5659126a01c812ee4ba7584ebfaa87778a1e3208cb6be442f415e348dfe6a1bc
7
+ data.tar.gz: 5e58e532a16725fc88dfc90f1a7321a20fc4730957a31db28e5e14952381ac5192c1afda78547395b1de833b5cbef45750cacd0effe1e5b822402b1afddfc866
data/README.md CHANGED
@@ -1,8 +1,12 @@
1
1
  # Panoptic
2
- Short description and motivation.
3
2
 
4
- ## Usage
5
- How to use my plugin.
3
+ [![Gem Version](https://badge.fury.io/rb/panoptic.svg)](https://badge.fury.io/rb/panoptic)
4
+
5
+ Panoptic is a web interface for the [SolidQueue](https://github.com/basecamp/solid_queue) queuing backend.
6
+
7
+ ![](./images/demo.png)
8
+
9
+ While MissionControl is getting ready for release, this gem offers a visual interface for testing purposes with SolidQueue.
6
10
 
7
11
  ## Installation
8
12
  Add this line to your application's Gemfile:
@@ -11,18 +15,23 @@ Add this line to your application's Gemfile:
11
15
  gem "panoptic"
12
16
  ```
13
17
 
14
- And then execute:
15
- ```bash
16
- $ bundle
17
- ```
18
+ Then mount the engine in your `config/routes.rb` file
18
19
 
19
- Or install it yourself as:
20
- ```bash
21
- $ gem install panoptic
20
+ ```ruby
21
+ mount Panoptic::Engine => "/panoptic"
22
22
  ```
23
23
 
24
- ## Contributing
25
- Contribution directions go here.
24
+ ## Usage
25
+
26
+ Once the gem is installed and the Engine mounted, visit your engine route to access Panoptic. For now, it offers three views:
27
+ - Processes
28
+ - Queues
29
+ - A first version of the jobs view
30
+
31
+ In the near future, the following features could be implemented:
32
+ - Pause and clear queues
33
+ - Advanced jobs view, with filters for executed, failed and scheduled jobs
34
+ - Search and retries
26
35
 
27
36
  ## License
28
37
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -1,4 +1,5 @@
1
1
  module Panoptic
2
2
  class ApplicationController < ActionController::Base
3
+ include Pagy::Backend
3
4
  end
4
5
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Panoptic
4
+ class Jobs::FailedController < ApplicationController
5
+ layout "panoptic/jobs", only: :index
6
+
7
+ def index
8
+ @pagy, @jobs = pagy(
9
+ Panoptic::FailedJob.order(created_at: :asc)
10
+ )
11
+ end
12
+
13
+ def show
14
+ @job = Panoptic::FailedJob.find(params[:id])
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Panoptic
4
+ class Jobs::ScheduledController < ApplicationController
5
+ layout "panoptic/jobs"
6
+
7
+ def index
8
+ # TODO: use the `scheduled` scope available in SolidQueue next release
9
+ @pagy, @jobs = pagy(
10
+ SolidQueue::Job.joins(:scheduled_execution).order(created_at: :asc)
11
+ )
12
+
13
+ render "panoptic/jobs/index"
14
+ end
15
+ end
16
+ end
@@ -2,8 +2,6 @@
2
2
 
3
3
  module Panoptic
4
4
  class JobsController < ApplicationController
5
- include Pagy::Backend
6
-
7
5
  def index
8
6
  @pagy, @jobs = pagy(SolidQueue::Job.order(created_at: :asc))
9
7
  end
@@ -1,5 +1,7 @@
1
1
  module Panoptic
2
2
  module ApplicationHelper
3
3
  include Pagy::Frontend
4
+ include BreadcrumbsHelper
5
+ include DateTimeHelper
4
6
  end
5
7
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Panoptic
4
+ module BreadcrumbsHelper
5
+ def breadcrumb_items
6
+ @breadcrumb_items ||= []
7
+ end
8
+
9
+ def breadcrumbs
10
+ tag.nav(aria: { label: "breadcrumb" }) do
11
+ tag.ol(class: "breadcrumb") do
12
+ breadcrumb_items.map do |item|
13
+ concat tag.li(item, class: "breadcrumb-item")
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Panoptic
4
+ module DateTimeHelper
5
+ def safe_time_tag(date_or_time, *args, &block)
6
+ return "-" unless date_or_time
7
+
8
+ time_tag(date_or_time, *args, &block)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Panoptic
4
+ class FailedJob < SolidQueue::Job
5
+ # TODO: use the `failed` scope available in SolidQueue next release
6
+ default_scope { joins(:failed_execution) }
7
+
8
+ def enqueued_at
9
+ Time.parse(arguments["enqueued_at"])
10
+ end
11
+
12
+ def exception_class
13
+ failed_execution.error["exception_class"]
14
+ end
15
+
16
+ def exception_message
17
+ failed_execution.error["message"]
18
+ end
19
+
20
+ def stacktrace
21
+ failed_execution.error["backtrace"]
22
+ end
23
+ end
24
+ end
@@ -7,11 +7,11 @@
7
7
 
8
8
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
9
9
  </head>
10
- <body>
10
+ <body class="pb-4">
11
11
  <%= render "shared/navbar" %>
12
12
 
13
13
  <main class="container mt-2">
14
- <%= yield %>
14
+ <%= content_for?(:content) ? yield(:content) : yield %>
15
15
  </main>
16
16
 
17
17
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
@@ -0,0 +1,27 @@
1
+ <% content_for(:content) do %>
2
+ <h1>Jobs</h1>
3
+
4
+ <ul class="nav nav-underline">
5
+ <li class="nav-item">
6
+ <%= link_to "All", jobs_path, class: class_names("nav-link", "active": current_page?(jobs_path)) %>
7
+ </li>
8
+ <li class="nav-item">
9
+ <%= link_to "Scheduled", scheduled_jobs_path, class: class_names("nav-link", "active": current_page?(scheduled_jobs_path)) %>
10
+ </li>
11
+ <li class="nav-item">
12
+ <%= link_to "Failed", failed_jobs_path, class: class_names("nav-link", "active": current_page?(failed_jobs_path)) %>
13
+ </li>
14
+ </ul>
15
+
16
+ <div class="d-flex justify-content-end">
17
+ <%== pagy_info(@pagy) %>
18
+ </div>
19
+
20
+ <%= yield %>
21
+
22
+ <div class="d-flex justify-content-center">
23
+ <%== pagy_bootstrap_nav(@pagy) if @pagy.pages > 1 %>
24
+ </div>
25
+ <% end %>
26
+
27
+ <%= render template: "layouts/panoptic/application" %>
@@ -2,7 +2,6 @@
2
2
  <th scope="row"><%= job.id %></th>
3
3
  <td scope="col"><%= job.class_name %></td>
4
4
  <td scope="col"><%= job.queue_name %></td>
5
- <td scope="col"><%= job.arguments %></td>
6
- <td scope="col"><% job.scheduled_at %></td>
7
- <td scope="col"><% job.finished_at %></td>
5
+ <td scope="col"><%= safe_time_tag job.scheduled_at %></td>
6
+ <td scope="col"><%= safe_time_tag job.finished_at %></td>
8
7
  </tr>
@@ -0,0 +1,10 @@
1
+ <tr>
2
+ <th scope="row"><%= job.id %></th>
3
+ <td scope="col"><%= job.class_name %></td>
4
+ <td scope="col"><%= job.queue_name %></td>
5
+ <td scope="col" class="font-monospace"><%= job.exception_class %></td>
6
+ <td scope="col"><%= safe_time_tag job.enqueued_at %></td>
7
+ <td scope="col">
8
+ <%= link_to "Details", failed_job_path(job) %>
9
+ </td>
10
+ </tr>
@@ -0,0 +1,16 @@
1
+ <table class="table">
2
+ <thead>
3
+ <tr>
4
+ <th scope="col">#</th>
5
+ <th scope="col">Class</th>
6
+ <th scope="col">Queue</th>
7
+ <th scope="col">Exception</th>
8
+ <th scope="col">Enqueued</th>
9
+ <th scope="col"></th>
10
+ </tr>
11
+ </thead>
12
+
13
+ <tbody>
14
+ <%= render partial: "job", collection: @jobs %>
15
+ </tbody>
16
+ </table>
@@ -0,0 +1,24 @@
1
+ <% breadcrumb_items.push link_to("Jobs", jobs_path) %>
2
+ <% breadcrumb_items.push link_to("Failed", failed_jobs_path) %>
3
+ <% breadcrumb_items.push @job.id %>
4
+ <%= breadcrumbs %>
5
+
6
+ <h1><%= @job.class_name %></h1>
7
+
8
+ <div class="alert alert-danger" role="alert">
9
+ <h4 class="alert-heading"><%= @job.exception_class %></h4>
10
+ <p class="font-monospace mb-0">
11
+ <%= @job.exception_message %>
12
+ </p>
13
+ </div>
14
+
15
+ <div class="card" >
16
+ <div class="card-header">
17
+ Stacktrace
18
+ </div>
19
+ <ul class="list-group list-group-flush font-monospace text-xs">
20
+ <% @job.stacktrace.each do |trace| %>
21
+ <li class="list-group-item"><%= trace %></li>
22
+ <% end %>
23
+ </ul>
24
+ </div>
@@ -1,26 +1,15 @@
1
- <h1>Jobs</h1>
2
-
3
- <div class="d-flex justify-content-end">
4
- <%== pagy_info(@pagy) %>
5
- </div>
6
-
7
1
  <table class="table">
8
2
  <thead>
9
3
  <tr>
10
4
  <th scope="col">#</th>
11
5
  <th scope="col">Class</th>
12
6
  <th scope="col">Queue</th>
13
- <th scope="col">Arguments</th>
14
- <th scope="col">Scheduled at</th>
15
- <th scope="col">Finished at</th>
7
+ <th scope="col">Scheduled</th>
8
+ <th scope="col">Finished</th>
16
9
  </tr>
17
10
  </thead>
18
11
 
19
12
  <tbody>
20
- <%= render partial: "job", collection: @jobs %>
13
+ <%= render partial: "panoptic/jobs/job", collection: @jobs %>
21
14
  </tbody>
22
15
  </table>
23
-
24
- <div class="d-flex justify-content-center">
25
- <%== pagy_bootstrap_nav(@pagy) if @pagy.pages > 1 %>
26
- </div>
data/config/routes.rb CHANGED
@@ -2,5 +2,13 @@ Panoptic::Engine.routes.draw do
2
2
  root to: "processes#index"
3
3
 
4
4
  resources :queues, only: [:index]
5
- resources :jobs, only: [:index]
5
+
6
+ scope "jobs" do
7
+ get "all", to: "jobs#index", as: "jobs"
8
+
9
+ scope module: "jobs" do
10
+ resources :scheduled, only: :index, as: :scheduled_jobs
11
+ resources :failed, only: [:index, :show], as: :failed_jobs
12
+ end
13
+ end
6
14
  end
@@ -1,3 +1,3 @@
1
1
  module Panoptic
2
- VERSION = "0.1.3"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: panoptic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vincent Rolea
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-28 00:00:00.000000000 Z
11
+ date: 2023-12-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -59,20 +59,28 @@ executables: []
59
59
  extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
- - MIT-LICENSE
63
62
  - README.md
64
63
  - Rakefile
65
64
  - app/controllers/panoptic/application_controller.rb
65
+ - app/controllers/panoptic/jobs/failed_controller.rb
66
+ - app/controllers/panoptic/jobs/scheduled_controller.rb
66
67
  - app/controllers/panoptic/jobs_controller.rb
67
68
  - app/controllers/panoptic/processes_controller.rb
68
69
  - app/controllers/panoptic/queues_controller.rb
69
70
  - app/helpers/panoptic/application_helper.rb
71
+ - app/helpers/panoptic/breadcrumbs_helper.rb
72
+ - app/helpers/panoptic/date_time_helper.rb
70
73
  - app/jobs/panoptic/application_job.rb
71
74
  - app/mailers/panoptic/application_mailer.rb
72
75
  - app/models/panoptic/application_record.rb
76
+ - app/models/panoptic/failed_job.rb
73
77
  - app/models/panoptic/process.rb
74
78
  - app/views/layouts/panoptic/application.html.erb
79
+ - app/views/layouts/panoptic/jobs.html.erb
75
80
  - app/views/panoptic/jobs/_job.html.erb
81
+ - app/views/panoptic/jobs/failed/_job.html.erb
82
+ - app/views/panoptic/jobs/failed/index.html.erb
83
+ - app/views/panoptic/jobs/failed/show.html.erb
76
84
  - app/views/panoptic/jobs/index.html.erb
77
85
  - app/views/panoptic/processes/_process.html.erb
78
86
  - app/views/panoptic/processes/index.html.erb
data/MIT-LICENSE DELETED
@@ -1,20 +0,0 @@
1
- Copyright Vincent Rolea
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.