backburner 1.9.0 → 1.9.1

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: ad41e83594bda50d1b504a4e0e5777c477e5586dc88faddbbad476a81afb34d4
4
- data.tar.gz: f53ac6873638f40f627bbcd1326f50fbd642e5454bce2c083b809cdc6904863b
3
+ metadata.gz: 38f2e1a84e114710eb8a1e2e6e61e6fe1683c6e06963c69c065511b59ec41390
4
+ data.tar.gz: 89a22694c1cd5b1957b4cd6ad287bc8905166588723421c1b0cedbdc2b37ecb0
5
5
  SHA512:
6
- metadata.gz: '0384db95f53944823490c2105948153c8aac2d0fb5e8268c8c6f82895ae722bf293bb93f7a0536967a9ad91a138d37f02d92f4f2b0e6860a749cb830065dd668'
7
- data.tar.gz: 1e6cbde19cd41a7540346d5d66af0537af1fc53baec32466790217b0643b610cbd7d17f8ea74b1ed6aedd55a26c152d798df86f4ef6b21ac11b5bc848db9d175
6
+ metadata.gz: 8113a36c15482093961ac7d3e9fee24f30b9d549bc32f7553b518056dea93ab389a848975dd80c112e77aa68dc2c7fd11bfa7b51cdb015a410795e1b4b9ea8cc
7
+ data.tar.gz: 8165aac92f55de2d5e6d15ad1ac91266c37f9355a1d8e6e8a3bf878f5af94028e7ecba8b2b69955c957d9cf61d908ebe8980208f977511a27f56e7440c4bc485
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## Version 1.9.1 (Nov 5 2026)
4
+
5
+ * Faster hook lookup: finding a job class's hooks (`before_enqueue`, `before_perform` and the others) no longer lists every method each class has, so Backburner's own work per job is lighter: enqueueing takes about 30-40% less time and working a job about 15-30% less (more with Active Support loaded), measured with no-op jobs against a local beanstalkd. The same hooks run, in the same order
6
+
3
7
  ## Version 1.9.0 (Nov 1 2026)
4
8
 
5
9
  * The gem now ships only `lib/`, `bin/`, `README.md`, `HOOKS.md`, `CHANGELOG.md` and `LICENSE` (no tests, examples or CI files), and its rubygems.org page links the source, the changelog and the issue tracker. **Behaviour change for the gem's owners:** pushing a release to rubygems.org now requires MFA (`rubygems_mfa_required`); the release workflow's trusted publishing is unaffected. **What to do:** owners who push by hand need MFA enabled on their rubygems.org account
@@ -46,8 +46,53 @@ module Backburner
46
46
  # # => ['before_enqueue_foo', 'before_enqueue_bar']
47
47
  #
48
48
  def find_hook_events(hookable, event)
49
- (hookable.methods - Object.methods).grep(/^#{event}/).sort
49
+ pattern = HOOK_PATTERNS[event] || /^#{event}/
50
+ (class_hook_events(hookable, pattern) || (hookable.methods - Object.methods).grep(pattern)).sort
50
51
  end
52
+
53
+ # The names (hookable.methods - Object.methods).grep(pattern) gives for a class, without listing every method
54
+ # each class has: a class's methods are looked up in its own modules (its singleton class, its superclasses'
55
+ # and the modules they extend) and then in Object's, so a name none of its own modules define is looked up
56
+ # as on Object, and Object.methods has it too. nil for anything else (an instance, a module, a class that
57
+ # doesn't end in Object's modules, or a class or Object that doesn't list its methods with Kernel's own public
58
+ # #methods).
59
+ def class_hook_events(hookable, pattern)
60
+ return unless Class === hookable
61
+ singleton = SINGLETON_CLASS.bind_call(hookable)
62
+ object = SINGLETON_CLASS.bind_call(Object)
63
+ return unless kernel_listing?(singleton) && kernel_listing?(object)
64
+ ancestors = ANCESTORS.bind_call(singleton)
65
+ objects = ANCESTORS.bind_call(object)
66
+ own = ancestors.size - objects.size
67
+ return unless own > 0 && ancestors.last(objects.size) == objects
68
+ # a name the class lists is public or protected where it is looked up, so one of them lists it
69
+ names = ancestors.first(own).flat_map { |mod| INSTANCE_METHODS.bind_call(mod, false).grep(pattern) }
70
+ names.uniq.select { |name| listed?(singleton, name) && !listed?(object, name) }
71
+ end
72
+
73
+ # Whether an object whose singleton class is `singleton` lists its methods with Kernel's own public #methods
74
+ def kernel_listing?(singleton)
75
+ return false unless PUBLIC_METHOD_DEFINED.bind_call(singleton, :methods)
76
+ listing = INSTANCE_METHOD.bind_call(singleton, :methods)
77
+ listing.owner.equal?(Kernel) && listing.original_name == :methods && listing.source_location.nil?
78
+ end
79
+
80
+ # Whether an object whose singleton class is `singleton` lists the method in #methods (a public or protected one)
81
+ def listed?(singleton, name)
82
+ PUBLIC_METHOD_DEFINED.bind_call(singleton, name) || PROTECTED_METHOD_DEFINED.bind_call(singleton, name)
83
+ end
84
+
85
+ # The patterns of the events Backburner triggers, compiled once
86
+ HOOK_PATTERNS = %i[before_enqueue after_enqueue before_perform around_perform after_perform on_failure on_bury
87
+ on_retry on_reconnect].to_h { |event| [event, /^#{event}/] }.freeze
88
+
89
+ # Kernel's and Module's own reflection, whatever a class or module defines for itself
90
+ SINGLETON_CLASS = Kernel.instance_method(:singleton_class)
91
+ ANCESTORS = Module.instance_method(:ancestors)
92
+ INSTANCE_METHODS = Module.instance_method(:instance_methods)
93
+ INSTANCE_METHOD = Module.instance_method(:instance_method)
94
+ PUBLIC_METHOD_DEFINED = Module.instance_method(:public_method_defined?)
95
+ PROTECTED_METHOD_DEFINED = Module.instance_method(:protected_method_defined?)
51
96
  end
52
97
  end # Hooks
53
98
  end # Backburner
@@ -1,3 +1,3 @@
1
1
  module Backburner
2
- VERSION = "1.9.0"
2
+ VERSION = "1.9.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: backburner
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.0
4
+ version: 1.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Esquenazi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-11-01 00:00:00.000000000 Z
11
+ date: 2026-11-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: beaneater