active_job_reporter 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1c09df3f74f6e36b4c812e7376ec9bf582453caa
4
+ data.tar.gz: 55e742befd0eac0b6c685da7a3da7d60dc5145e3
5
+ SHA512:
6
+ metadata.gz: 2df2ecb5940484d8e6860fd605f15be109ec48ce2ef506b436b69b0911d310ccd22ec45a8328f8f3f55d9bafa2c5bdba0a46e00e431bef338f1e0b5aa5059106
7
+ data.tar.gz: 3d162bdd88acc9684dfe067c03a91c6718b9981f38de4c60edff56cdfc064837905229f6b1d71459a35039856117265f68c835ea4d895e0864c163ccc1c4f4c6
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2017 Leonardo Diez
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,124 @@
1
+ # Active Job Reporter
2
+ Monitoring and reporting for ActiveJob.
3
+
4
+ [![Gem](https://img.shields.io/gem/v/active_job_reporter.svg)](https://rubygems.org/gems/active_job_reporter)
5
+ [![Travis](https://img.shields.io/travis/podemos-info/active_job_reporter/master.svg)](https://travis-ci.org/podemos-info/active_job_reporter)
6
+ [![Codecov](https://img.shields.io/codecov/c/github/podemos-info/active_job_reporter.svg)](https://codecov.io/gh/podemos-info/active_job_reporter)
7
+
8
+ ## Features
9
+ * Minimalistic approach to ActiveJob monitoring, database based to avoid additional dependencies.
10
+ * Filter jobs by status (`enqueued`, `running` or `finished`), user, resource or result (`ok`, `error` or custom).
11
+ * Messages log by job.
12
+ * Automatic basic exception handling during errors.
13
+ * Allows to override built-in Job model.
14
+
15
+ ## Usage
16
+
17
+ 1. Add `ReportableJob` concern to your jobs. You can add to `ApplicationJob` to avoid adding to every job. Jobs will be tracked automatically.
18
+
19
+ ```ruby
20
+ include ActiveJobReporter::ReportableJob
21
+ ```
22
+
23
+ 2. Define `current_user` method in your jobs to relate them to users. Use `arguments` variable to retrieve `perform` call arguments. Using keyword arguments with the same name would allow you to define at `ApplicationJob`.
24
+
25
+ ```ruby
26
+ def current_user
27
+ arguments.first&.fetch(:admin_user, nil)
28
+ end
29
+ ```
30
+
31
+ 3. Define `related_objects` method in your jobs to relate them to other application records.
32
+
33
+ ```ruby
34
+ def related_objects
35
+ [ arguments.first&.fetch(:order, nil), *arguments.first&.fetch(:items, []) ].compact
36
+ end
37
+ ```
38
+
39
+ 4. Add log messages and result code inside your jobs `perform` methods. `log` method allows to specify type of message and complex messages (stored as JSON in database). Use `self.result` to store the result of the job (won't be saved until the end of the process). If not specified, result will be `:ok` or `:error`, when the `perform` method raises an exception.
40
+
41
+ ```ruby
42
+ def perform(**params)
43
+ if has_issues?
44
+ log :issues, raw: "raw test message"
45
+ self.result = :issues
46
+ end
47
+
48
+ if params[:raise]
49
+ a = 1 / 0
50
+ end
51
+
52
+ log :user, key: "test.user_message.#{result}", params: { user_id: 1, number: 12 }
53
+ end
54
+ ```
55
+
56
+ 5. Application models related to jobs can use the `HasJobs` concern to simplify access to them.
57
+
58
+ ```ruby
59
+ class Resource < ApplicationRecord
60
+ include ActiveJobReporter::HasJobs
61
+ end
62
+ ```
63
+
64
+ Then, access to jobs can be made from `jobs` association method.
65
+
66
+ ```ruby
67
+ 2.4.1 :001 > Resource.first.jobs.count
68
+ => 1
69
+ 2.4.1 :002 > Resource.first.jobs.running.count
70
+ => 0
71
+ ```
72
+
73
+ 6. If an application `Job` model is needed (to extend it or avoid using a qualified name), it can be defined using the `JobConcern` concern and specifying the class name in the initializer file.
74
+
75
+ ```ruby
76
+ # in app/models/job.rb
77
+ class Job < ActiveRecord::Base
78
+ include ActiveJobReporter::JobConcern
79
+ end
80
+
81
+ # in config/initializers/active_job_reporter.rb
82
+ ActiveJobReporter.configure do |config|
83
+ ...
84
+
85
+ # The class name for jobs
86
+ config.jobs_class_name = "Job"
87
+
88
+ ...
89
+ end
90
+ ```
91
+
92
+ ## Installation
93
+ 1. Add this line to your application's Gemfile:
94
+
95
+ ```ruby
96
+ gem 'active_job_reporter'
97
+ ```
98
+
99
+ 2. Update bundle
100
+
101
+ ```bash
102
+ $ bundle
103
+ ```
104
+
105
+ 3. Run installer
106
+
107
+ Add `jobs`, `job_objects` and `job_messages` tables to your database and an initializer file for configuration:
108
+
109
+ ```bash
110
+ $ bundle exec rails generate active_job_reporter:install
111
+ $ bundle exec rake db:migrate
112
+ ```
113
+
114
+ ## Changelog
115
+
116
+ #### 0.1.0
117
+
118
+ * First version.
119
+
120
+ ## Contributing
121
+ Issues and PRs are welcomed.
122
+
123
+ ## License
124
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require "bundler/setup"
5
+ rescue LoadError
6
+ puts "You must `gem install bundler` and `bundle install` to run rake tasks"
7
+ end
8
+
9
+ require "rdoc/task"
10
+
11
+ RDoc::Task.new(:rdoc) do |rdoc|
12
+ rdoc.rdoc_dir = "rdoc"
13
+ rdoc.title = "ActivejobReporter"
14
+ rdoc.options << "--line-numbers"
15
+ rdoc.rdoc_files.include("README.md")
16
+ rdoc.rdoc_files.include("lib/**/*.rb")
17
+ end
18
+
19
+ require "bundler/gem_tasks"
20
+ require "rspec/core/rake_task"
21
+
22
+ RSpec::Core::RakeTask.new("spec")
23
+ task default: :spec
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_job_reporter/version"
4
+ require "active_job_reporter/configuration"
5
+ require "active_job_reporter/core"
6
+ require "active_job_reporter/job_concern"
7
+ require "active_job_reporter/has_jobs"
8
+ require "active_job_reporter/reportable_job"
9
+ require "active_job_reporter/engine" if defined?(Rails::Engine)
10
+ require "active_job_reporter/defaults"
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJobReporter
4
+ class Configuration
5
+ attr_accessor :jobs_table_name, :user_class_name, :job_class_name
6
+
7
+ def user_class
8
+ @user_class ||= user_class_name.constantize
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJobReporter
4
+ module_function
5
+
6
+ def configuration
7
+ @configuration ||= Configuration.new
8
+ end
9
+
10
+ def configure
11
+ configuration.instance_eval(&Proc.new)
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ ActiveJobReporter.configure do |config|
4
+ config.jobs_table_name = "jobs"
5
+ config.user_class_name = "User"
6
+ config.job_class_name = "ActiveJobReporter::Job"
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJobReporter
4
+ class Engine < ::Rails::Engine
5
+ paths["app/models"] << "lib/active_job_reporter/models"
6
+ end
7
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module ActiveJobReporter
6
+ module HasJobs
7
+ extend ::ActiveSupport::Concern
8
+
9
+ included do
10
+ has_many :job_objects, as: :object, class_name: "ActiveJobReporter::JobObject"
11
+ has_many :jobs, through: :job_objects, class_name: ActiveJobReporter.configuration.job_class_name
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module ActiveJobReporter
6
+ module JobConcern
7
+ extend ::ActiveSupport::Concern
8
+
9
+ included do
10
+ self.table_name = ActiveJobReporter.configuration.jobs_table_name
11
+
12
+ enum status: [:enqueued, :running, :finished]
13
+
14
+ validates :job_id, :job_type, presence: true
15
+
16
+ has_many :job_objects
17
+
18
+ has_many :messages, foreign_key: "job_id", class_name: "ActiveJobReporter::JobMessage"
19
+
20
+ belongs_to :user, class_name: ActiveJobReporter.configuration.user_class, optional: true
21
+ end
22
+
23
+ def add_message(type:, message:)
24
+ messages << JobMessage.create(message_type: type, message: message)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJobReporter
4
+ class Job < ActiveRecord::Base
5
+ include ActiveJobReporter::JobConcern
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJobReporter
4
+ class JobMessage < ActiveRecord::Base
5
+ store :message, coder: JSON
6
+
7
+ belongs_to :job
8
+
9
+ validates :message_type, :message, presence: true
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJobReporter
4
+ class JobObject < ActiveRecord::Base
5
+ belongs_to :job
6
+ belongs_to :object, polymorphic: true
7
+ end
8
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module ActiveJobReporter
6
+ module ReportableJob
7
+ extend ::ActiveSupport::Concern
8
+
9
+ included do
10
+ before_enqueue do |job|
11
+ job.update_status(:enqueued)
12
+ end
13
+
14
+ around_perform do |job, block|
15
+ job.update_status(:running)
16
+ begin
17
+ job.result = :ok
18
+ block.call
19
+ rescue StandardError => err
20
+ job.log :error, raw: err.message
21
+ job.result = :error
22
+ raise
23
+ ensure
24
+ job.update_status(:finished)
25
+ end
26
+ end
27
+ end
28
+
29
+ def update_status(status)
30
+ job_record.status = status
31
+ job_record.save
32
+ end
33
+
34
+ def result
35
+ job_record.result.to_sym
36
+ end
37
+
38
+ def result=(result)
39
+ job_record.result = result
40
+ end
41
+
42
+ def log(type, **message)
43
+ job_record.add_message type: type, message: message
44
+ end
45
+
46
+ private
47
+
48
+ def job_record
49
+ @job_record ||= ActiveJobReporter::Job.find_or_initialize_by(job_id: job_id) do |job_record|
50
+ job_record.job_type = self.class.name
51
+ job_record.user = current_user if respond_to? :current_user
52
+ if respond_to? :related_objects
53
+ (related_objects || []).each do |object|
54
+ job_record.job_objects.build(object: object)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJobReporter
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActivejobReporter
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require "rails/generators/active_record"
5
+
6
+ module ActiveJobReporter
7
+ # Installs ActiveJobReporter in a rails app.
8
+ class InstallGenerator < ::Rails::Generators::Base
9
+ include ::Rails::Generators::Migration
10
+
11
+ source_root File.expand_path("../templates", __FILE__)
12
+
13
+ class_option(
14
+ :jobs_table_name,
15
+ type: :string,
16
+ default: "jobs",
17
+ desc: "Jobs table name, `jobs` by default."
18
+ )
19
+
20
+ desc "Generates an initializer file for configuring ActiveJobReporter." \
21
+ "Also generates a migration to add jobs tables."
22
+
23
+ def create_migration_file
24
+ migration_template "create_jobs.rb.erb", File.join("db", "migrate", "create_jobs.rb")
25
+ end
26
+
27
+ def create_initializer
28
+ template "active_job_reporter.rb.erb", File.join("config", "initializers", "active_job_reporter.rb")
29
+ end
30
+
31
+ def self.next_migration_number(dirname)
32
+ ::ActiveRecord::Generators::Base.next_migration_number(dirname)
33
+ end
34
+
35
+ def migration_version
36
+ "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
37
+ end
38
+
39
+ def jobs_table_name
40
+ options.jobs_table_name
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ ActiveJobReporter.configure do |config|
4
+ config.jobs_table_name = "<%= jobs_table_name %>"
5
+
6
+ # The class name for jobs
7
+ # config.jobs_class_name = "ActiveJobReporter::Job"
8
+
9
+ # The class name for users that will launch jobs
10
+ # config.user_class_name = "User"
11
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This migration creates the `<%= jobs_table_name %>` table.
4
+ class CreateJobs < ActiveRecord::Migration<%= migration_version %>
5
+ def change
6
+ create_table :<%= jobs_table_name %> do |t|
7
+ t.string :job_id, null: false
8
+ t.string :job_type, null: false
9
+ t.integer :status, null: false, index: true
10
+ t.text :result
11
+ t.integer :user_id, index: true
12
+ t.timestamps
13
+ end
14
+
15
+ add_index :<%= jobs_table_name %>, [:job_id], unique: true
16
+
17
+ create_table :<%= jobs_table_name.singularize %>_objects do |t|
18
+ t.belongs_to :job, foreign_key: { to_table: :<%= jobs_table_name %> }, index: true
19
+ t.belongs_to :object, polymorphic: true, index: true
20
+ end
21
+
22
+ create_table :<%= jobs_table_name.singularize %>_messages do |t|
23
+ t.belongs_to :job, foreign_key: { to_table: :<%= jobs_table_name %> }, index: true
24
+ t.string :message_type, null: false
25
+ t.datetime :created_at, null: false
26
+ t.text :message, null: false
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # desc "Explaining what the task does"
4
+ # task :activejob_reporter do
5
+ # # Task goes here
6
+ # end
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: active_job_reporter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Leonardo Diez
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-11-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 5.1.4
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 5.1.4
27
+ - !ruby/object:Gem::Dependency
28
+ name: codecov
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.1'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: generator_spec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.9.3
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.9.3
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.6'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.6'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.50'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.50'
83
+ - !ruby/object:Gem::Dependency
84
+ name: sqlite3
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Monitoring and reporting for ActiveJob.
98
+ email:
99
+ - leiodd@gmail.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - MIT-LICENSE
105
+ - README.md
106
+ - Rakefile
107
+ - lib/active_job_reporter.rb
108
+ - lib/active_job_reporter/configuration.rb
109
+ - lib/active_job_reporter/core.rb
110
+ - lib/active_job_reporter/defaults.rb
111
+ - lib/active_job_reporter/engine.rb
112
+ - lib/active_job_reporter/has_jobs.rb
113
+ - lib/active_job_reporter/job_concern.rb
114
+ - lib/active_job_reporter/models/active_job_reporter/job.rb
115
+ - lib/active_job_reporter/models/active_job_reporter/job_message.rb
116
+ - lib/active_job_reporter/models/active_job_reporter/job_object.rb
117
+ - lib/active_job_reporter/reportable_job.rb
118
+ - lib/active_job_reporter/version.rb
119
+ - lib/activejob_reporter/version.rb
120
+ - lib/generators/active_job_reporter/install_generator.rb
121
+ - lib/generators/active_job_reporter/templates/active_job_reporter.rb.erb
122
+ - lib/generators/active_job_reporter/templates/create_jobs.rb.erb
123
+ - lib/tasks/active_job_reporter_tasks.rake
124
+ homepage: https://github.com/podemos-info/active_job_reporter
125
+ licenses:
126
+ - MIT
127
+ metadata: {}
128
+ post_install_message:
129
+ rdoc_options: []
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ requirements: []
143
+ rubyforge_project:
144
+ rubygems_version: 2.6.12
145
+ signing_key:
146
+ specification_version: 4
147
+ summary: Monitoring and reporting for ActiveJob.
148
+ test_files: []