active_job_tracker 0.1.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3102a3e7bcb824b3db71003baa5f401f0598178c503b1f5b4b49f7c3e580d835
4
- data.tar.gz: e043943a466eb2d514a906acd8ae2b72c9fe0a294f0b080f0ddceb6e561affef
3
+ metadata.gz: 2b8342cf50be46737b9d191b7d631008c6cecad77fc81d1e0fcfca23c4ff6007
4
+ data.tar.gz: 02a1d61e46c41f6241b8be9d25ba311c42f882b1db71e94afc7d19062bbe3e31
5
5
  SHA512:
6
- metadata.gz: f030c69148089178e8d0dd8693835af4407bb9d62ea789f08b3875fff399d282603eae68411e1eb10acff0f0d707c0e6470f53114df0534f369816c49ca3d460
7
- data.tar.gz: 0146a953fee7b01f7e203eff001e974799f8e8ba364dcc79fa54a5a6b81eb6d13670354bd1fbb1dc59cf95b62d8b7b9c4b1bdb3f35103ba29be6414eae3cb7dc
6
+ metadata.gz: 1b46f5815fd0809154e222e50e388f6aa49bde11cb904d12bb8ff12fe9ecf1ccf2f41b0e250620b09accf18f0755e3e275b997380ee9284d9b1e290f6b2ead6b
7
+ data.tar.gz: f60e1e47250e60af0693f3a9f81cfcc8777289b2640e1a0b8f96b2b29bd3d61f9e42624148169fc2ba3b32ef186ee2e9c3c75f43784368020c36444b35d1f0e9
data/README.md CHANGED
@@ -1,8 +1,12 @@
1
+ ❤️ I'm looking for a full-time position. Please consider hiring me.
2
+
1
3
  # ActiveJobTracker
2
4
 
3
5
  ActiveJobTracker provides persisted, real-time tracking and monitoring of ActiveJob jobs in Ruby on Rails applications. It allows you to track job status, progress, and errors with a simple API and real-time UI updates via ActionCable.
4
6
 
5
- <img width="796" alt="Screenshot 2025-03-04 at 1 09 38 PM" src="https://github.com/user-attachments/assets/d34e6fb8-bb3c-4d71-a737-2f7597a23c43" />
7
+ <div align="center">
8
+ <img width="500" alt="Screenshot 2025-03-04 at 1 09 38 PM" src="https://github.com/user-attachments/assets/d34e6fb8-bb3c-4d71-a737-2f7597a23c43" />
9
+ </div>
6
10
 
7
11
  ## Features
8
12
 
@@ -10,7 +14,7 @@ ActiveJobTracker provides persisted, real-time tracking and monitoring of Active
10
14
  - Monitor job progress with percentage completion
11
15
  - Real-time UI updates via ActionCable
12
16
  - Error tracking and reporting
13
- - Efficient progress caching to minimize database updates
17
+ - Efficient progress write-behind caching to minimize database updates
14
18
  - Configurable options
15
19
 
16
20
  ## Installation
@@ -59,6 +63,9 @@ ActiveJobTracker.configure do |config|
59
63
  # When true, job updates are automatically broadcast via ActionCable
60
64
  config.auto_broadcast = true
61
65
 
66
+ # Whether to raise an error when progress increments the current value beyond the target value (default: false)
67
+ config.raise_error_when_target_exceeded = false
68
+
62
69
  # Default partial path for rendering job trackers
63
70
  # (default: 'active_job_tracker/active_job_tracker')
64
71
  config.default_partial = 'active_job_tracker/active_job_tracker'
@@ -66,6 +73,10 @@ ActiveJobTracker.configure do |config|
66
73
  # Whether to include the style in the job tracker (default: true)
67
74
  # When true, the gem's CSS styles are automatically included
68
75
  config.include_style = true
76
+
77
+ # Custom Turbo Stream channel name (default: 'active_job_tracker')
78
+ # Use this to customize the ActionCable channel name for real-time updates
79
+ config.turbo_stream_channel = 'Turbo::StreamsChannel'
69
80
  end
70
81
  ```
71
82
 
@@ -80,9 +91,9 @@ class CsvUpload < ApplicationRecord
80
91
  # Sets up polymorphic association to tie this record to the ActiveJobTracker
81
92
  has_one :job, as: :active_job_trackable, class_name: 'ActiveJobTrackerRecord'
82
93
 
83
- after_create :create_jobs
94
+ after_create :process_import
84
95
 
85
- def create_jobs
96
+ def process_import
86
97
  # The tracked record must be passed into the job as the first argument
87
98
  ProcessImportJob.perform_later(self)
88
99
  end
@@ -122,13 +133,27 @@ class ProcessImportJob < ApplicationJob
122
133
  records.each do |record|
123
134
  # Process item
124
135
 
125
- # Update progress (increments by 1)
136
+ # Update progress (increments by 1 by default)
126
137
  active_job_tracker_progress
127
138
  end
128
139
  end
129
140
  end
130
141
  ```
131
142
 
143
+ Optionally, you can use a custom value to increment your progress by:
144
+
145
+ ```ruby
146
+ def perform
147
+ # Default target is 100
148
+
149
+ 10.times do
150
+ # Process item
151
+
152
+ active_job_tracker_progress(increment_by: 10)
153
+ end
154
+ end
155
+ ```
156
+
132
157
  For more efficient progress tracking with many updates, use threadsafe progress caching:
133
158
 
134
159
  ```ruby
@@ -167,6 +192,7 @@ This will render a default tracker UI with progress bar, status badge, and job i
167
192
  #### Custom Rendering
168
193
 
169
194
  You can customize the tracker UI by creating your own partials and using the ActiveJobTrackerRecord model attributes:
195
+
170
196
  - Make sure to set the `config.default_partial` to the new partial path
171
197
  - Each job block needs to be wrapped with `id="active_job_tracker_<%= tracker.id %>"` for turbo to update your frontend
172
198
 
@@ -260,7 +286,7 @@ end
260
286
 
261
287
  ## Development
262
288
 
263
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
289
+ After checking out the repo, run `bundle install` to install dependencies. Then, run `rails test` to run the tests.
264
290
 
265
291
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
266
292
 
@@ -43,14 +43,15 @@ class ActiveJobTrackerRecord < ApplicationRecord
43
43
  [ current.to_f / target.to_f, 1.0 ].min
44
44
  end
45
45
 
46
- def progress(use_cache = true)
46
+ def progress(use_cache: true, increment_by: 1)
47
47
  if use_cache
48
48
  key = progress_cache_key
49
49
  should_flush = false
50
50
 
51
51
  @@mutex.synchronize do
52
52
  current_value = Rails.cache.fetch(key, expires_in: 1.week) { 0 }.to_i
53
- new_value = current_value + 1
53
+ new_value = incremented_value(current_value: current_value, increment_by: increment_by)
54
+
54
55
  Rails.cache.write(key, new_value, expires_in: 1.week)
55
56
 
56
57
  should_flush = new_value >= self.cache_threshold
@@ -60,7 +61,7 @@ class ActiveJobTrackerRecord < ApplicationRecord
60
61
  flush_progress_cache if should_flush
61
62
  else
62
63
  with_lock do
63
- self.current += 1
64
+ self.current = incremented_value(current_value: current, increment_by: increment_by)
64
65
  save!
65
66
  end
66
67
  end
@@ -86,8 +87,24 @@ class ActiveJobTrackerRecord < ApplicationRecord
86
87
 
87
88
  private
88
89
 
90
+ def incremented_value(current_value:, increment_by:)
91
+ new_value = current_value + increment_by
92
+
93
+ if new_value > target
94
+ if ActiveJobTracker.configuration.raise_error_when_target_exceeded
95
+ raise ActiveJobTracker::Error::TargetExceeded.new(
96
+ "The current value of #{new_value} exceeds the target value of #{target}"
97
+ )
98
+ end
99
+
100
+ target
101
+ else
102
+ new_value
103
+ end
104
+ end
105
+
89
106
  def broadcast_changes
90
- broadcast_replace_to(
107
+ ActiveJobTracker.configuration.turbo_stream_channel.constantize.broadcast_replace_to(
91
108
  "active_job_trackers",
92
109
  target: "active_job_tracker_#{self.id}",
93
110
  partial: ActiveJobTracker.configuration.default_partial,
@@ -6,7 +6,7 @@
6
6
  html_options ||= {}
7
7
  css_class = html_options[:class] || "active_job_tracker-container"
8
8
  %>
9
- <%= turbo_stream_from "active_job_trackers" %>
9
+ <%= turbo_stream_from "active_job_trackers", channel: ActiveJobTracker.configuration.turbo_stream_channel %>
10
10
  <div class="<%= css_class %>" data-controller="active_job_tracker-container">
11
11
  <%= content %>
12
12
  </div>
@@ -0,0 +1,41 @@
1
+ <%
2
+ percentage = active_job_tracker_record.progress_percentage
3
+ status = active_job_tracker_record.status
4
+
5
+ # Calculate the stroke-dasharray and stroke-dashoffset for the circle
6
+ circumference = 2 * Math::PI * 45 # 45 is the radius of the circle
7
+ stroke_dashoffset = circumference * (1 - percentage / 100.0)
8
+ %>
9
+
10
+ <div class="active_job_tracker-radial-progress">
11
+ <svg width="100" height="100" viewBox="0 0 100 100">
12
+ <circle
13
+ class="active_job_tracker-radial-progress-bg"
14
+ cx="50"
15
+ cy="50"
16
+ r="45"
17
+ fill="none"
18
+ stroke-width="8"
19
+ />
20
+ <circle
21
+ class="active_job_tracker-radial-progress-fill active_job_tracker-radial-progress-<%= status %>"
22
+ cx="50"
23
+ cy="50"
24
+ r="45"
25
+ fill="none"
26
+ stroke-width="8"
27
+ stroke-dasharray="<%= circumference %>"
28
+ stroke-dashoffset="<%= stroke_dashoffset %>"
29
+ transform="rotate(-90 50 50)"
30
+ />
31
+ <text
32
+ class="active_job_tracker-radial-progress-text"
33
+ x="50"
34
+ y="50"
35
+ text-anchor="middle"
36
+ dominant-baseline="middle"
37
+ >
38
+ <%= percentage %>%
39
+ </text>
40
+ </svg>
41
+ </div>
@@ -19,17 +19,27 @@ module ActiveJobTracker
19
19
  # @return [String]
20
20
  attr_accessor :default_partial
21
21
 
22
+ # Whether to raise an error when progress increments the current value beyond the target value
23
+ # @return [Boolean]
24
+ attr_accessor :raise_error_when_target_exceeded
25
+
22
26
  # Whether to include the style in the job tracker
23
27
  # @return [Boolean]
24
28
  attr_accessor :include_style
25
29
 
30
+ # The turbo stream channel to use for broadcasting job tracker updates
31
+ # @return [String]
32
+ attr_accessor :turbo_stream_channel
33
+
26
34
  # Initialize with default values
27
35
  def initialize
28
36
  @default_target = 100
29
37
  @cache_threshold = 10
30
38
  @auto_broadcast = true
39
+ @raise_error_when_target_exceeded = false
31
40
  @default_partial = "active_job_tracker/active_job_tracker"
32
41
  @include_style = true
42
+ @turbo_stream_channel = "Turbo::StreamsChannel"
33
43
  end
34
44
  end
35
45
  end
@@ -1,3 +1,3 @@
1
1
  module ActiveJobTracker
2
- VERSION = "0.1.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -6,6 +6,7 @@ module ActiveJobTracker
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  class Error < StandardError
9
+ class TargetExceeded < Error; end
9
10
  end
10
11
 
11
12
  def self.configuration
@@ -35,8 +36,8 @@ module ActiveJobTracker
35
36
  active_job_tracker.update(target: target)
36
37
  end
37
38
 
38
- def active_job_tracker_progress(cache: false)
39
- active_job_tracker.progress(cache)
39
+ def active_job_tracker_progress(cache: false, increment_by: 1)
40
+ active_job_tracker.progress(use_cache: cache, increment_by: increment_by)
40
41
  end
41
42
 
42
43
  def active_job_tracker
@@ -15,6 +15,9 @@ ActiveJobTracker.configure do |config|
15
15
  # When true, job updates are automatically broadcast via ActionCable
16
16
  config.auto_broadcast = true
17
17
 
18
+ # Whether to raise an error when progress increments the current value beyond the target value
19
+ config.raise_error_when_target_exceeded = false
20
+
18
21
  # Default partial path for rendering job trackers
19
22
  # (default: 'active_job_tracker/shared/active_job_tracker')
20
23
  config.default_partial = "active_job_tracker/active_job_tracker"
@@ -22,4 +25,8 @@ ActiveJobTracker.configure do |config|
22
25
  # Whether to include the style in the job tracker (default: true)
23
26
  # When true, the gem's CSS styles are automatically included
24
27
  config.include_style = true
28
+
29
+ # The turbo stream channel to use for broadcasting job tracker updates
30
+ # (default: 'Turbo::StreamsChannel')
31
+ config.turbo_stream_channel = "Turbo::StreamsChannel"
25
32
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_job_tracker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Seena Sabti
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-03-06 00:00:00.000000000 Z
10
+ date: 2025-03-10 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: rails
@@ -23,6 +23,20 @@ dependencies:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
25
  version: 8.0.1
26
+ - !ruby/object:Gem::Dependency
27
+ name: turbo-rails
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.0.11
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: 2.0.11
26
40
  - !ruby/object:Gem::Dependency
27
41
  name: mocha
28
42
  requirement: !ruby/object:Gem::Requirement
@@ -120,6 +134,7 @@ files:
120
134
  - app/models/active_job_tracker_record.rb
121
135
  - app/views/active_job_tracker/_active_job_tracker.html.erb
122
136
  - app/views/active_job_tracker/_active_job_tracker_wrapper.html.erb
137
+ - app/views/active_job_tracker/_radial_progress.html.erb
123
138
  - lib/active_job_tracker.rb
124
139
  - lib/active_job_tracker/configuration.rb
125
140
  - lib/active_job_tracker/engine.rb