undertow 0.2.1 → 0.4.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: bf230477188804dcf6c63e0c97c615defb3577c78f85e930449d7dba6d9d965e
4
- data.tar.gz: 6653637c116fff79ba2a2806326882f7e7e939acdf1ca0f01a653e22530dd3c7
3
+ metadata.gz: 1aa09fe4d1c2e088f4b7ca874175db916486f8a6296d49af88544bec8ec254be
4
+ data.tar.gz: 30115bb681233cf045251670a9f2ed369e6290340414f5f031f292cd2e26fe23
5
5
  SHA512:
6
- metadata.gz: 74aca2058a93a4474bd275de1ab3d077b7e83e5a6449cb0921938585821c29f39ab531240eabbfb89d28ba7ac4a73cd4f3c58183e001992847d1a3ebae6e89b2
7
- data.tar.gz: 6c18ad42284eb95008c44bfd6240e79ae14c7d99aa50befa8c1ccb417d07286a55049c1467f6e4f66a66d8f93df8e7c1b613cc045217df6ba81c9334af3cf368
6
+ metadata.gz: a68ec79086258526eb24fbd2690b5df15701975706ee4ae09bbbd800d4e024d1b9c4546d7df03f465de7bbdcd4efc6252b73ac2244252b74d6f93707ea5dff1b
7
+ data.tar.gz: 9406d057b05d1a76fade09a0d3b3b698d3503a11bccfdd68591f4eead07bce128dfd3b431fbf4e6078eac092bc4f641a51d0dda036bdd200ab928dbec24155af
@@ -5,7 +5,7 @@ module Undertow
5
5
  # each model's configured on_drain handler.
6
6
  #
7
7
  # Publishes two ActiveSupport::Notifications events:
8
- # drain.undertow , after a successful on_drain call ({ model:, ids:, deleted_ids: })
8
+ # drain.undertow , after a successful on_drain call ({ model:, upserted_ids:, deleted_ids:, duration_ms: })
9
9
  # error.undertow , when on_drain raises ({ model:, exception: })
10
10
  class DrainJob < ActiveJob::Base
11
11
  queue_as { Undertow.configuration.queue_name }
@@ -30,9 +30,9 @@ module Undertow
30
30
  # preventing the race where srem fires after a concurrent sadd.
31
31
  Buffer.deregister_model(model_name)
32
32
 
33
- ids = Buffer.pop_pending(model_name, max)
34
- deleted_ids = Buffer.pop_deleted(model_name, max)
35
- return if ids.empty? && deleted_ids.empty?
33
+ upserted_ids = Buffer.pop_pending(model_name, max)
34
+ deleted_ids = Buffer.pop_deleted(model_name, max)
35
+ return if upserted_ids.empty? && deleted_ids.empty?
36
36
 
37
37
  # If the batch was capped, re-register so the next scheduler tick picks up.
38
38
  Buffer.reregister_model(model_name) if Buffer.remaining(model_name).positive?
@@ -41,19 +41,26 @@ module Undertow
41
41
  raise "No Undertow config registered for #{model_name}" unless config
42
42
  raise "#{model_name} is missing undertow_on_drain" unless config.on_drain
43
43
 
44
- config.on_drain.call(model_name, ids, deleted_ids)
44
+ duration_ms = measure_ms { config.on_drain.call(model_name, upserted_ids, deleted_ids) }
45
45
 
46
46
  ActiveSupport::Notifications.instrument('drain.undertow', {
47
47
  model: model_name,
48
- ids: ids,
49
- deleted_ids: deleted_ids
48
+ upserted_ids: upserted_ids,
49
+ deleted_ids: deleted_ids,
50
+ duration_ms: duration_ms
50
51
  })
51
52
  rescue StandardError => e
52
- Buffer.restore_pending(model_name, ids) if ids&.any?
53
- Buffer.restore_deleted(model_name, deleted_ids) if deleted_ids&.any?
53
+ Buffer.restore_pending(model_name, upserted_ids) if upserted_ids&.any?
54
+ Buffer.restore_deleted(model_name, deleted_ids) if deleted_ids&.any?
54
55
  Buffer.reregister_model(model_name)
55
56
  ActiveSupport::Notifications.instrument('error.undertow', { model: model_name, exception: e })
56
57
  Rails.logger.error("[Undertow::DrainJob] #{model_name}: #{e.message}") if defined?(Rails)
57
58
  end
59
+
60
+ def measure_ms
61
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
62
+ yield
63
+ ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - start) * 1000).round(2)
64
+ end
58
65
  end
59
66
  end
data/lib/undertow/dsl.rb CHANGED
@@ -5,14 +5,14 @@ module Undertow
5
5
  # that calls these methods automatically registers itself with Undertow and
6
6
  # gets Trackable behavior wired in at boot, no include needed.
7
7
  #
8
- # class Activity < ApplicationRecord
9
- # undertow_on_drain ->(model_name, ids, deleted_ids) { ActivityReindexJob.perform_later(ids, deleted_ids) }
10
- # undertow_skip %w[lock_version searchkick_reindexing]
8
+ # class Post < ApplicationRecord
9
+ # undertow_on_drain ->(model_name, upserted_ids, deleted_ids) { PostSyncJob.perform_later(upserted_ids, deleted_ids) }
10
+ # undertow_skip %w[view_count updated_at]
11
11
  #
12
- # undertow_depends_on :provider, foreign_key: :provider_id, watched_columns: %w[approved mobile]
13
- # undertow_depends_on :location_series,
14
- # resolver: ->(ls) { Activity.where(series_id: ls.series_id) },
15
- # watched_columns: %w[location_id hidden]
12
+ # undertow_depends_on :author, foreign_key: :author_id, watched_columns: %w[name bio]
13
+ # undertow_depends_on :tag,
14
+ # resolver: ->(tag) { Post.joins(:post_tags).where(post_tags: { tag_id: tag.id }) },
15
+ # watched_columns: %w[name slug]
16
16
  # end
17
17
  #
18
18
  module DSL
@@ -39,6 +39,23 @@ module Undertow
39
39
  Buffer.push_deleted(name, ids)
40
40
  end
41
41
 
42
+ # Enqueues records into the pending buffer without going through AR
43
+ # callbacks. Use this to replay a batch through the drain handler without
44
+ # triggering other model lifecycle callbacks, e.g. from a console or a
45
+ # data migration.
46
+ #
47
+ # Post.undertow_requeue(Post.where(author_id: 123))
48
+ # Post.undertow_requeue([136543, 136544])
49
+ # Post.undertow_requeue # all records
50
+ def undertow_requeue(scope_or_ids = :all)
51
+ ids = case scope_or_ids
52
+ when :all then pluck(:id)
53
+ when ActiveRecord::Relation then scope_or_ids.pluck(:id)
54
+ else Array(scope_or_ids)
55
+ end
56
+ _push_undertow_pending(ids)
57
+ end
58
+
42
59
  def _push_dep_pending(record, dep)
43
60
  ids = _dep_ids_for(record, dep)
44
61
  _push_undertow_pending(ids) if ids.any?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Undertow
4
- VERSION = '0.2.1'
4
+ VERSION = '0.4.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: undertow
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Allen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-06-13 00:00:00.000000000 Z
11
+ date: 2026-07-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord