rush_job_mongoid 1.0.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/MIT-LICENSE +20 -0
- data/README.md +60 -0
- data/Rakefile +5 -0
- data/app/assets/config/rush_job_mongoid_manifest.js +4 -0
- data/app/assets/images/rush_job_mongoid/funnel-fill.svg +3 -0
- data/app/assets/images/rush_job_mongoid/funnel.svg +3 -0
- data/app/assets/images/rush_job_mongoid/pencil-square-dark.svg +4 -0
- data/app/assets/images/rush_job_mongoid/pencil-square-light.svg +4 -0
- data/app/assets/javascript/rush_job_mongoid/application.js +13 -0
- data/app/assets/javascript/rush_job_mongoid/controllers/rush_job_mongoid_filters_controller.js +9 -0
- data/app/assets/javascript/rush_job_mongoid/controllers/rush_job_mongoid_polling_controller.js +50 -0
- data/app/assets/javascript/rush_job_mongoid/controllers/rush_job_mongoid_reload_jobs_table_controller.js +7 -0
- data/app/assets/javascript/rush_job_mongoid/controllers/rush_job_mongoid_table_update_controller.js +19 -0
- data/app/assets/stylesheets/rush_job_mongoid/application.scss +16 -0
- data/app/assets/stylesheets/rush_job_mongoid/components/_polling.scss +3 -0
- data/app/assets/stylesheets/rush_job_mongoid/layout/_container.scss +4 -0
- data/app/controllers/rush_job_mongoid/application_controller.rb +5 -0
- data/app/controllers/rush_job_mongoid/dashboard_controller.rb +28 -0
- data/app/controllers/rush_job_mongoid/rush_jobs_controller.rb +57 -0
- data/app/controllers/rush_job_mongoid/settings_controller.rb +18 -0
- data/app/helpers/rush_job_mongoid/application_helper.rb +6 -0
- data/app/helpers/rush_job_mongoid/filter_helper.rb +20 -0
- data/app/helpers/rush_job_mongoid/settings_helper.rb +19 -0
- data/app/models/rush_job_mongoid/rush_job.rb +83 -0
- data/app/presenters/rush_job_mongoid/pagination_presenter.rb +17 -0
- data/app/presenters/rush_job_mongoid/queue_groups_presenter.rb +25 -0
- data/app/services/rush_job_mongoid/locked_jobs.rb +15 -0
- data/app/services/rush_job_mongoid/settings.rb +19 -0
- data/app/views/layouts/rush_job_mongoid/_filter_modal.html.erb +58 -0
- data/app/views/layouts/rush_job_mongoid/_flash_messages.html.erb +5 -0
- data/app/views/layouts/rush_job_mongoid/_navbar.html.erb +72 -0
- data/app/views/layouts/rush_job_mongoid/application.html.erb +24 -0
- data/app/views/rush_job_mongoid/dashboard/_dashboard_tables.html.erb +34 -0
- data/app/views/rush_job_mongoid/dashboard/_queues_table.html.erb +39 -0
- data/app/views/rush_job_mongoid/dashboard/index.html.erb +7 -0
- data/app/views/rush_job_mongoid/dashboard/index.js.erb +3 -0
- data/app/views/rush_job_mongoid/rush_jobs/_jobs_table.html.erb +43 -0
- data/app/views/rush_job_mongoid/rush_jobs/edit.html.erb +51 -0
- data/app/views/rush_job_mongoid/rush_jobs/index.html.erb +7 -0
- data/app/views/rush_job_mongoid/rush_jobs/index.js.erb +3 -0
- data/app/views/rush_job_mongoid/shared/_pagination.html.erb +89 -0
- data/app/views/rush_job_mongoid/shared/_pagination_link.html.erb +3 -0
- data/app/views/rush_job_mongoid/shared/_polling.html.erb +32 -0
- data/config/importmap.rb +5 -0
- data/config/locales/en.yml +46 -0
- data/config/routes.rb +7 -0
- data/lib/rush_job_mongoid/engine.rb +23 -0
- data/lib/rush_job_mongoid/version.rb +3 -0
- data/lib/rush_job_mongoid.rb +6 -0
- data/lib/tasks/rush_job_mongoid_tasks.rake +4 -0
- data/vendor/stylesheets/rush_job_mongoid/bootstrap.css +12273 -0
- metadata +364 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 965c03dc946e6df0a48d7d174e4cc88554c754ab9348f20568177790d866125b
|
4
|
+
data.tar.gz: db8783bcb66c206c1ad374799595ab58b6f13e97f0b442f2ac1ed4990efc0e01
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 24a160ff6b9a070d8d1267ce6374b5f82ce0114da5fd4f55f59d9ed48889b2f47caf2fe8e38c1383adf86cc90e7a516ee0667dfd18cd917d6cffe9e229a0ef76
|
7
|
+
data.tar.gz: 6191e7b39f8077e2ea636fc047cf7c5db2d89cd285b5f9c86e13b4dfdf27d54f26d0c926c11b75c1de66a9685e9542c23598a2cb25f460f7e1a17943deb866bb
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright JavaKoala
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# RushJobMongoid
|
2
|
+
User interface for Delayed Job Mongoid (https://github.com/collectiveidea/delayed_job_mongoid) in Ruby on Rails
|
3
|
+
|
4
|
+
<img width="656" alt="Dashboard" src="docs/assets/dashboard.png">
|
5
|
+
<img width="656" alt="Jobs" src="docs/assets/jobs.png">
|
6
|
+
|
7
|
+
### Note
|
8
|
+
- This app uses cookies to store the selected options.
|
9
|
+
|
10
|
+
## Usage
|
11
|
+
You will need Delayed Job, `delayed_job`, and Delayed Job Mongoid, `delayed_job_mongoid`, installed in a Ruby on Rails application for this gem to work properly.
|
12
|
+
|
13
|
+
Navigate to the `/rush_job_mongoid` route in your application to see the Delayed Jobs. Locally this would be `http://localhost:3000/rush_job_mongoid`
|
14
|
+
|
15
|
+
### Options
|
16
|
+
|
17
|
+
#### Dark Mode
|
18
|
+
|
19
|
+
Enables or disables dark mode
|
20
|
+
|
21
|
+
#### Editing
|
22
|
+
|
23
|
+
Make sure workers are stopped before editing
|
24
|
+
|
25
|
+
#### Queues
|
26
|
+
|
27
|
+
Queues on the dashboard are eager loaded. If there are lots of queues this can affect performance. Disable queues if this becomes an issue.
|
28
|
+
|
29
|
+
## Installation
|
30
|
+
Add this line to your Ruby on Rails application's Gemfile:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
gem 'rush_job', '~> 1.0.0'
|
34
|
+
```
|
35
|
+
|
36
|
+
And then execute:
|
37
|
+
```bash
|
38
|
+
$ bundle install
|
39
|
+
```
|
40
|
+
|
41
|
+
Add the following to your `config/routes.rb` file:
|
42
|
+
```ruby
|
43
|
+
mount RushJob::Engine => '/rush_job_mongoid'
|
44
|
+
```
|
45
|
+
|
46
|
+
## Contributing
|
47
|
+
Open an issue or
|
48
|
+
1. Fork
|
49
|
+
2. Update
|
50
|
+
3. Test
|
51
|
+
1. `bundle exec rails app:test:all` and check coverage in `test/coverage/index.html`
|
52
|
+
2. `bundle exec rubocop`
|
53
|
+
3. `bundle exec brakeman`
|
54
|
+
4. Open pull request
|
55
|
+
|
56
|
+
## Upcoming
|
57
|
+
1. Remove dependency on Rails UJS and move to Hotwire and Turbo
|
58
|
+
|
59
|
+
## License
|
60
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,3 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="rgb(255, 255, 255)" class="bi bi-funnel-fill" viewBox="0 0 16 16">
|
2
|
+
<path d="M1.5 1.5A.5.5 0 0 1 2 1h12a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.128.334L10 8.692V13.5a.5.5 0 0 1-.342.474l-3 1A.5.5 0 0 1 6 14.5V8.692L1.628 3.834A.5.5 0 0 1 1.5 3.5z"/>
|
3
|
+
</svg>
|
@@ -0,0 +1,3 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="rgb(255, 255, 255)" class="bi bi-funnel" viewBox="0 0 16 16">
|
2
|
+
<path d="M1.5 1.5A.5.5 0 0 1 2 1h12a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.128.334L10 8.692V13.5a.5.5 0 0 1-.342.474l-3 1A.5.5 0 0 1 6 14.5V8.692L1.628 3.834A.5.5 0 0 1 1.5 3.5zm1 .5v1.308l4.372 4.858A.5.5 0 0 1 7 8.5v5.306l2-.666V8.5a.5.5 0 0 1 .128-.334L13.5 3.308V2z"/>
|
3
|
+
</svg>
|
@@ -0,0 +1,4 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="rgb(0, 0, 0)" class="bi bi-pencil-square" viewBox="0 0 16 16">
|
2
|
+
<path d="M15.502 1.94a.5.5 0 0 1 0 .706L14.459 3.69l-2-2L13.502.646a.5.5 0 0 1 .707 0l1.293 1.293zm-1.75 2.456-2-2L4.939 9.21a.5.5 0 0 0-.121.196l-.805 2.414a.25.25 0 0 0 .316.316l2.414-.805a.5.5 0 0 0 .196-.12l6.813-6.814z"/>
|
3
|
+
<path fill-rule="evenodd" d="M1 13.5A1.5 1.5 0 0 0 2.5 15h11a1.5 1.5 0 0 0 1.5-1.5v-6a.5.5 0 0 0-1 0v6a.5.5 0 0 1-.5.5h-11a.5.5 0 0 1-.5-.5v-11a.5.5 0 0 1 .5-.5H9a.5.5 0 0 0 0-1H2.5A1.5 1.5 0 0 0 1 2.5z"/>
|
4
|
+
</svg>
|
@@ -0,0 +1,4 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="rgb(255, 255, 255)" class="bi bi-pencil-square" viewBox="0 0 16 16">
|
2
|
+
<path d="M15.502 1.94a.5.5 0 0 1 0 .706L14.459 3.69l-2-2L13.502.646a.5.5 0 0 1 .707 0l1.293 1.293zm-1.75 2.456-2-2L4.939 9.21a.5.5 0 0 0-.121.196l-.805 2.414a.25.25 0 0 0 .316.316l2.414-.805a.5.5 0 0 0 .196-.12l6.813-6.814z"/>
|
3
|
+
<path fill-rule="evenodd" d="M1 13.5A1.5 1.5 0 0 0 2.5 15h11a1.5 1.5 0 0 0 1.5-1.5v-6a.5.5 0 0 0-1 0v6a.5.5 0 0 1-.5.5h-11a.5.5 0 0 1-.5-.5v-11a.5.5 0 0 1 .5-.5H9a.5.5 0 0 0 0-1H2.5A1.5 1.5 0 0 0 1 2.5z"/>
|
4
|
+
</svg>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import { Application } from '@hotwired/stimulus';
|
2
|
+
import Rails from '@rails/ujs';
|
3
|
+
import RushJobMongoidFiltersController from './controllers/rush_job_mongoid_filters_controller';
|
4
|
+
import RushJobMongoidPollingController from './controllers/rush_job_mongoid_polling_controller';
|
5
|
+
import RushJobMongoidReloadJobsTableController from './controllers/rush_job_mongoid_reload_jobs_table_controller';
|
6
|
+
import 'bootstrap';
|
7
|
+
|
8
|
+
Rails.start();
|
9
|
+
|
10
|
+
window.Stimulus = Application.start();
|
11
|
+
Stimulus.register('rush-job-mongoid-filter', RushJobMongoidFiltersController);
|
12
|
+
Stimulus.register('rush-job-mongoid-polling', RushJobMongoidPollingController);
|
13
|
+
Stimulus.register('rush-job-mongoid-reload-jobs-table', RushJobMongoidReloadJobsTableController);
|
data/app/assets/javascript/rush_job_mongoid/controllers/rush_job_mongoid_polling_controller.js
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
import { RushJobMongoidTableUpdateController } from './rush_job_mongoid_table_update_controller';
|
2
|
+
|
3
|
+
let intervalID;
|
4
|
+
|
5
|
+
export default class RushJobMongoidPollingController extends RushJobMongoidTableUpdateController {
|
6
|
+
static targets = ['pollingTime', 'pollingTimeLabel', 'pollingSlide'];
|
7
|
+
|
8
|
+
connect() {
|
9
|
+
this.pollingChange();
|
10
|
+
this.stopPolling();
|
11
|
+
}
|
12
|
+
|
13
|
+
pollingChange() {
|
14
|
+
const pollingLabelRegex = /\d+/;
|
15
|
+
const pollingTimeTargetHtml = this.pollingTimeLabelTarget.innerHTML;
|
16
|
+
const pollingLabelUpdate = pollingTimeTargetHtml.replace(pollingLabelRegex, this.pollingTime());
|
17
|
+
this.pollingTimeLabelTarget.innerHTML = pollingLabelUpdate;
|
18
|
+
}
|
19
|
+
|
20
|
+
pollingToggle() {
|
21
|
+
const pollingSlide = this.pollingSlideTarget;
|
22
|
+
|
23
|
+
if (pollingSlide.checked === true) {
|
24
|
+
this.startPolling();
|
25
|
+
} else {
|
26
|
+
this.stopPolling();
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
startPolling() {
|
31
|
+
this.updateJobs();
|
32
|
+
|
33
|
+
intervalID = setTimeout(() => {
|
34
|
+
this.startPolling();
|
35
|
+
}, this.pollingTime() * 1000);
|
36
|
+
}
|
37
|
+
|
38
|
+
stopPolling() {
|
39
|
+
if (intervalID) {
|
40
|
+
clearInterval(intervalID);
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
pollingTime() {
|
45
|
+
const pollingTimes = [3, 5, 8, 13, 21, 34, 55];
|
46
|
+
const pollingTime = this.pollingTimeTarget.value || 3;
|
47
|
+
|
48
|
+
return pollingTimes[pollingTime];
|
49
|
+
}
|
50
|
+
}
|
data/app/assets/javascript/rush_job_mongoid/controllers/rush_job_mongoid_table_update_controller.js
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus';
|
2
|
+
import Rails from '@rails/ujs';
|
3
|
+
|
4
|
+
export class RushJobMongoidTableUpdateController extends Controller {
|
5
|
+
updateJobs() {
|
6
|
+
this.blurTable();
|
7
|
+
|
8
|
+
Rails.ajax({
|
9
|
+
url: document.location.href,
|
10
|
+
type: 'GET',
|
11
|
+
dataType: 'script',
|
12
|
+
});
|
13
|
+
}
|
14
|
+
|
15
|
+
blurTable() {
|
16
|
+
const jobsContainer = document.getElementById('rush-job-mongoid-jobs');
|
17
|
+
jobsContainer.classList.add('table-refresh');
|
18
|
+
}
|
19
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*/
|
14
|
+
@import "../../../vendor/stylesheets/rush_job_mongoid/bootstrap";
|
15
|
+
@import "layout/container";
|
16
|
+
@import "components/polling";
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module RushJobMongoid
|
2
|
+
class DashboardController < ApplicationController
|
3
|
+
include RushJobMongoid::SettingsHelper
|
4
|
+
|
5
|
+
def index
|
6
|
+
@locked_jobs_presenter = PaginationPresenter.new(params[:locked_jobs_page])
|
7
|
+
@locked_jobs = LockedJobs.new(filter_params)
|
8
|
+
@queues_presenter = QueueGroupsPresenter.new(params[:queue_groups_page]) if queue_groups_enabled?
|
9
|
+
end
|
10
|
+
|
11
|
+
def destroy
|
12
|
+
RushJob.clear_queue(queue_params[:queue], queue_params[:priority])
|
13
|
+
|
14
|
+
flash[:success] = t(:cleared_queue, queue: params[:queue])
|
15
|
+
redirect_to root_path, status: :see_other
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def queue_params
|
21
|
+
params.permit(:queue, :priority)
|
22
|
+
end
|
23
|
+
|
24
|
+
def filter_params
|
25
|
+
params.permit(:doc_id, :priority, :attempts, :job_class, :arguments, :locked_by, :last_error, :queue)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module RushJobMongoid
|
2
|
+
class RushJobsController < ApplicationController
|
3
|
+
before_action :find_job, only: %i[edit update destroy]
|
4
|
+
|
5
|
+
def index
|
6
|
+
@pagination_presenter = PaginationPresenter.new(params[:page])
|
7
|
+
@rush_jobs = RushJob.filter(filter_params).locked_by_desc.paginate(@pagination_presenter.page, 20)
|
8
|
+
end
|
9
|
+
|
10
|
+
def edit
|
11
|
+
flash.now[:warning] = t(:edit_warning)
|
12
|
+
end
|
13
|
+
|
14
|
+
def update
|
15
|
+
if @job.update(update_params)
|
16
|
+
flash[:success] = t(:updated_job, job_id: @job.id)
|
17
|
+
redirect_to rush_jobs_path(doc_id: @job.id)
|
18
|
+
else
|
19
|
+
flash[:danger] = t(:unable_to_update, errors: @job.errors.full_messages.to_sentence)
|
20
|
+
render :edit, status: :unprocessable_entity
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def destroy
|
25
|
+
@job.destroy
|
26
|
+
|
27
|
+
flash[:success] = t(:deleted_job, job_id: @job.id)
|
28
|
+
redirect_to rush_jobs_path
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def find_job
|
34
|
+
@job = RushJob.find(params[:id])
|
35
|
+
rescue Mongoid::Errors::DocumentNotFound => e
|
36
|
+
Rails.logger.info e.message
|
37
|
+
flash[:danger] = t(:missing_document)
|
38
|
+
redirect_to rush_jobs_path
|
39
|
+
end
|
40
|
+
|
41
|
+
def filter_params
|
42
|
+
params.permit(:doc_id, :priority, :attempts, :job_class, :arguments, :locked_by, :last_error, :queue)
|
43
|
+
end
|
44
|
+
|
45
|
+
def update_params
|
46
|
+
params.require(:rush_job).permit(:priority,
|
47
|
+
:attempts,
|
48
|
+
:handler,
|
49
|
+
:run_at,
|
50
|
+
:locked_at,
|
51
|
+
:locked_by,
|
52
|
+
:failed_at,
|
53
|
+
:last_error,
|
54
|
+
:queue)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module RushJobMongoid
|
2
|
+
class SettingsController < ApplicationController
|
3
|
+
def update
|
4
|
+
change_setting if Settings::RUSH_JOB_SETTINGS[params[:setting]&.to_sym]
|
5
|
+
|
6
|
+
redirect_to root_path
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def change_setting
|
12
|
+
setting_param = params[:setting]
|
13
|
+
setting_cookie = "rush_job_#{setting_param}"
|
14
|
+
|
15
|
+
cookies.permanent[setting_cookie.to_sym] = Settings.change_setting(setting_param, cookies[setting_cookie.to_sym])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module RushJobMongoid
|
2
|
+
module FilterHelper
|
3
|
+
def filter_param_query
|
4
|
+
{
|
5
|
+
doc_id: params[:doc_id],
|
6
|
+
priority: params[:priority],
|
7
|
+
attempts: params[:attempts],
|
8
|
+
job_class: params[:job_class],
|
9
|
+
arguments: params[:arguments],
|
10
|
+
locked_by: params[:locked_by],
|
11
|
+
last_error: params[:last_error],
|
12
|
+
queue: params[:queue]
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
def filter_param_query_empty?
|
17
|
+
filter_param_query.values.join.empty?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module RushJobMongoid
|
2
|
+
module SettingsHelper
|
3
|
+
def current_theme
|
4
|
+
cookies[:rush_job_theme] == 'dark' ? 'dark' : 'light'
|
5
|
+
end
|
6
|
+
|
7
|
+
def invert_theme
|
8
|
+
cookies[:rush_job_theme] == 'dark' ? 'light' : 'dark'
|
9
|
+
end
|
10
|
+
|
11
|
+
def editing_enabled?
|
12
|
+
cookies[:rush_job_editing] == 'enabled'
|
13
|
+
end
|
14
|
+
|
15
|
+
def queue_groups_enabled?
|
16
|
+
cookies[:rush_job_queue_groups_presenter] != 'disabled'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module RushJobMongoid
|
2
|
+
class RushJob
|
3
|
+
include Mongoid::Document
|
4
|
+
|
5
|
+
store_in collection: 'delayed_backend_mongoid_jobs'
|
6
|
+
|
7
|
+
field :priority, type: Integer, default: 0
|
8
|
+
field :attempts, type: Integer, default: 0
|
9
|
+
field :handler, type: String
|
10
|
+
field :run_at, type: Time
|
11
|
+
field :locked_at, type: Time
|
12
|
+
field :locked_by, type: String
|
13
|
+
field :failed_at, type: Time
|
14
|
+
field :last_error, type: String
|
15
|
+
field :queue, type: String
|
16
|
+
|
17
|
+
validates :priority, presence: true
|
18
|
+
|
19
|
+
scope :locked_jobs, -> { where(:locked_at.exists => true) }
|
20
|
+
scope :locked_by_desc, -> { order_by(locked_by: -1, priority: 1, run_at: 1) }
|
21
|
+
scope :paginate, ->(page, jobs_per_page) { limit(jobs_per_page).skip(jobs_per_page * (page - 1)) }
|
22
|
+
scope :by_job_class, ->(job_class) { where(handler: /#{job_class}/i) if job_class.present? }
|
23
|
+
scope :by_arguments, ->(job_arguments) { where(handler: /#{job_arguments}/i) if job_arguments.present? }
|
24
|
+
scope :by_last_error, ->(last_error) { where(last_error: /#{last_error}/i) if last_error.present? }
|
25
|
+
|
26
|
+
%i[by_doc_id by_priority by_attempts by_locked_by by_queue].each do |where_query|
|
27
|
+
define_singleton_method where_query do |arg|
|
28
|
+
param = where_query.to_s.sub('by_', '').sub('doc', '')
|
29
|
+
arg.present? ? where(param => arg) : where({})
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def job_class
|
34
|
+
job_data&.fetch(:job_class)
|
35
|
+
end
|
36
|
+
|
37
|
+
def job_arguments
|
38
|
+
job_data&.fetch(:arguments).presence || ''
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.queue_groups
|
42
|
+
groups = collection.aggregate([
|
43
|
+
{ '$group' => {
|
44
|
+
_id: { 'queue' => '$queue', 'priority' => '$priority' }, count: { '$sum' => 1 }
|
45
|
+
} }
|
46
|
+
]).to_a
|
47
|
+
|
48
|
+
group_result = []
|
49
|
+
|
50
|
+
groups.each do |group|
|
51
|
+
group_result << { queue: group['_id']['queue'], priority: group['_id']['priority'], count: group['count'] }
|
52
|
+
end
|
53
|
+
|
54
|
+
group_result.sort_by! { |group| [group[:priority], group[:queue]] }
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.clear_queue(queue_name, queue_priority)
|
58
|
+
where(queue: queue_name, priority: queue_priority).delete_all
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.filter(filter_params)
|
62
|
+
by_doc_id(filter_params[:doc_id])
|
63
|
+
.by_priority(filter_params[:priority])
|
64
|
+
.by_attempts(filter_params[:attempts])
|
65
|
+
.by_job_class(filter_params[:job_class])
|
66
|
+
.by_arguments(filter_params[:arguments])
|
67
|
+
.by_locked_by(filter_params[:locked_by])
|
68
|
+
.by_last_error(filter_params[:last_error])
|
69
|
+
.by_queue(filter_params[:queue])
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def handler_hash
|
75
|
+
safe_yaml = handler.sub('!ruby/object:ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper', '')
|
76
|
+
Psych.safe_load(safe_yaml, symbolize_names: true)
|
77
|
+
end
|
78
|
+
|
79
|
+
def job_data
|
80
|
+
handler_hash&.fetch(:job_data)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module RushJobMongoid
|
2
|
+
class PaginationPresenter
|
3
|
+
def initialize(page_param)
|
4
|
+
@page_param = page_param
|
5
|
+
end
|
6
|
+
|
7
|
+
def page
|
8
|
+
page = @page_param&.to_i || 1
|
9
|
+
|
10
|
+
[page, 1].max
|
11
|
+
end
|
12
|
+
|
13
|
+
def pages(item_count, items_per_page)
|
14
|
+
(item_count / items_per_page.to_f).ceil
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module RushJobMongoid
|
2
|
+
class QueueGroupsPresenter
|
3
|
+
attr_reader :queue_groups_presenter, :rush_job_queue_groups, :queue_groups
|
4
|
+
|
5
|
+
def initialize(queue_groups_page)
|
6
|
+
@queue_groups_presenter = PaginationPresenter.new(queue_groups_page)
|
7
|
+
@rush_job_queue_groups = RushJob.queue_groups
|
8
|
+
@queue_groups = queue_groups_from_presener
|
9
|
+
end
|
10
|
+
|
11
|
+
def pages_count
|
12
|
+
@queue_groups_presenter.pages(@rush_job_queue_groups.count, 10)
|
13
|
+
end
|
14
|
+
|
15
|
+
def page
|
16
|
+
@queue_groups_presenter.page
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def queue_groups_from_presener
|
22
|
+
@rush_job_queue_groups[(@queue_groups_presenter.page - 1) * 10, 10]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module RushJobMongoid
|
2
|
+
class LockedJobs
|
3
|
+
def initialize(filters = {})
|
4
|
+
@filters = filters
|
5
|
+
end
|
6
|
+
|
7
|
+
def jobs
|
8
|
+
RushJob.filter(@filters).locked_jobs
|
9
|
+
end
|
10
|
+
|
11
|
+
def paginate(page, count_per_page = 10)
|
12
|
+
jobs.locked_by_desc.paginate(page, count_per_page)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module RushJobMongoid
|
2
|
+
class Settings
|
3
|
+
RUSH_JOB_SETTINGS = {
|
4
|
+
theme: %w[light dark],
|
5
|
+
editing: %w[disabled enabled],
|
6
|
+
queue_groups_presenter: %w[enabled disabled]
|
7
|
+
}.freeze
|
8
|
+
|
9
|
+
def self.change_setting(setting, value)
|
10
|
+
return unless RUSH_JOB_SETTINGS[setting.to_sym]
|
11
|
+
|
12
|
+
if RUSH_JOB_SETTINGS[setting.to_sym].include?(value)
|
13
|
+
(RUSH_JOB_SETTINGS[setting.to_sym] - [value]).first
|
14
|
+
else
|
15
|
+
RUSH_JOB_SETTINGS[setting.to_sym].last
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
<div class="modal fade" id="rush-job-mongoid-filter-modal" tabindex="-1" aria-labelledby="rushJobMongoidModalLabel" aria-hidden="true">
|
2
|
+
<div class="modal-dialog">
|
3
|
+
<div class="modal-content">
|
4
|
+
<div class="modal-header">
|
5
|
+
<h1 class="modal-title fs-5" id="rushJobMongoidModalLabel"><%= t(:filter_jobs) %></h1>
|
6
|
+
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
7
|
+
</div>
|
8
|
+
<%= form_with url: request.path, method: :get, data: { controller: 'rush-job-mongoid-filter' } do |form| %>
|
9
|
+
<div class="modal-body">
|
10
|
+
<div class="mb-3">
|
11
|
+
<%= form.label :doc_id, t(:id), class: 'form-label' %>
|
12
|
+
<%= form.text_field :doc_id, value: params[:doc_id], class: 'form-control', data: { 'rush-job-mongoid-filter-target' => 'input' } %>
|
13
|
+
</div>
|
14
|
+
|
15
|
+
<div class="mb-3">
|
16
|
+
<%= form.label :priority, t(:priority), class: 'form-label' %>
|
17
|
+
<%= form.number_field :priority, value: params[:priority], class: 'form-control', data: { 'rush-job-mongoid-filter-target' => 'input' } %>
|
18
|
+
</div>
|
19
|
+
|
20
|
+
<div class="mb-3">
|
21
|
+
<%= form.label :attempts, t(:attempts), class: 'form-label' %>
|
22
|
+
<%= form.number_field :attempts, value: params[:attempts], class: 'form-control', data: { 'rush-job-mongoid-filter-target' => 'input' } %>
|
23
|
+
</div>
|
24
|
+
|
25
|
+
<div class="mb-3">
|
26
|
+
<%= form.label :job_class, t(:job_class), class: 'form-label' %>
|
27
|
+
<%= form.text_field :job_class, value: params[:job_class], class: 'form-control', data: { 'rush-job-mongoid-filter-target' => 'input' } %>
|
28
|
+
</div>
|
29
|
+
|
30
|
+
<div class="mb-3">
|
31
|
+
<%= form.label :arguments, t(:arguments), class: 'form-label' %>
|
32
|
+
<%= form.text_field :arguments, value: params[:arguments], class: 'form-control', data: { 'rush-job-mongoid-filter-target' => 'input' } %>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<div class="mb-3">
|
36
|
+
<%= form.label :locked_by, t(:locked_by), class: 'form-label' %>
|
37
|
+
<%= form.text_field :locked_by, value: params[:locked_by], class: 'form-control', data: { 'rush-job-mongoid-filter-target' => 'input' } %>
|
38
|
+
</div>
|
39
|
+
|
40
|
+
<div class="mb-3">
|
41
|
+
<%= form.label :last_error, t(:last_error), class: 'form-label' %>
|
42
|
+
<%= form.text_field :last_error, value: params[:last_error], class: 'form-control', data: { 'rush-job-mongoid-filter-target' => 'input' } %>
|
43
|
+
</div>
|
44
|
+
|
45
|
+
<div class="mb-3">
|
46
|
+
<%= form.label :queue, t(:queue), class: 'form-label' %>
|
47
|
+
<%= form.text_field :queue, value: params[:queue], class: 'form-control', data: { 'rush-job-mongoid-filter-target' => 'input' } %>
|
48
|
+
</div>
|
49
|
+
</div>
|
50
|
+
<div class="modal-footer">
|
51
|
+
<button type="button" class="btn btn-outline-secondary" data-action="click->rush-job-mongoid-filter#clearForm"><%= t(:clear) %></button>
|
52
|
+
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><%= t(:close) %></button>
|
53
|
+
<%= form.submit t(:filter), class: 'btn btn-primary' %>
|
54
|
+
</div>
|
55
|
+
<% end %>
|
56
|
+
</div>
|
57
|
+
</div>
|
58
|
+
</div>
|