que-unique 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 +7 -0
- data/lib/que/unique/constants.rb +8 -0
- data/lib/que/unique/transaction_class_methods.rb +52 -0
- data/lib/que/unique/version.rb +7 -0
- data/lib/que/unique.rb +58 -0
- metadata +182 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 35fee9d8dc2566367c0f06c98b1722091cf493b396e32207993fec7fdb30e0a0
|
4
|
+
data.tar.gz: 370ac9d00fa7553ff7e5aec3a7654eae9e15653260c45437cea23a021e22eac5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cb3fdd1122a99c323e48b4cd9e7fe6b0fd1a275df64b1e66f2035674875802d1f1c82d3e34d69b18b6e16b1225427246b475ca8f95273b295568c95f84b59f0f
|
7
|
+
data.tar.gz: bc174ee7bfa80ffc48c21b47de63db05ee2131278a507d0b477bd964511d92fba37769b5daa474557b1bfb52b7bc0b53381996e94dc62db5eeb53644ccf127af
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record"
|
4
|
+
require_relative "constants"
|
5
|
+
|
6
|
+
# This block adds the wrapping around all transactions to either start the thread local, or
|
7
|
+
# increment it so we know how deep we are in the transaction nesting.
|
8
|
+
module Que
|
9
|
+
module Unique
|
10
|
+
module TransactionClassMethods
|
11
|
+
def transaction_with_unique_que(*args, &block)
|
12
|
+
start_que_unique_handled_transaction
|
13
|
+
transaction_without_unique_que(*args, &block)
|
14
|
+
ensure
|
15
|
+
end_que_unique_handled_transaction
|
16
|
+
end
|
17
|
+
|
18
|
+
class << self
|
19
|
+
def extended(base)
|
20
|
+
base.class_eval do
|
21
|
+
class << self
|
22
|
+
alias_method :transaction_without_unique_que, :transaction
|
23
|
+
alias_method :transaction, :transaction_with_unique_que
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def start_que_unique_handled_transaction
|
32
|
+
# Set the defaults for the thread local, then delegate to the real block.
|
33
|
+
Thread.current[Que::Unique::THREAD_LOCAL_KEY] ||= {}
|
34
|
+
# We keep track of the nested depth, so we know when to clear the array
|
35
|
+
Thread.current[Que::Unique::THREAD_LOCAL_DEPTH_KEY] ||= 0
|
36
|
+
# Now we know we are initialised, increment the transaction counter
|
37
|
+
Thread.current[Que::Unique::THREAD_LOCAL_DEPTH_KEY] += 1
|
38
|
+
end
|
39
|
+
|
40
|
+
def end_que_unique_handled_transaction
|
41
|
+
# Note the depth. When we are back to zero, assume all the Que jobs have been committed,
|
42
|
+
# so reset the hash.
|
43
|
+
Thread.current[Que::Unique::THREAD_LOCAL_DEPTH_KEY] -= 1
|
44
|
+
return unless Thread.current[Que::Unique::THREAD_LOCAL_DEPTH_KEY].zero?
|
45
|
+
|
46
|
+
Thread.current[Que::Unique::THREAD_LOCAL_KEY] = {}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
ActiveRecord::Base.extend Que::Unique::TransactionClassMethods
|
data/lib/que/unique.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "que"
|
4
|
+
require_relative "unique/version"
|
5
|
+
require_relative "unique/constants"
|
6
|
+
require_relative "unique/transaction_class_methods"
|
7
|
+
|
8
|
+
# This block wraps the enqueue method of Que::Unique jobs.
|
9
|
+
# For each json of args, we store in a hash.
|
10
|
+
module Que
|
11
|
+
module Unique
|
12
|
+
extend ActiveSupport::Concern
|
13
|
+
|
14
|
+
included do
|
15
|
+
singleton_class.class_eval do
|
16
|
+
def enqueue_before_unique(*args)
|
17
|
+
thread_local_hash = Thread.current[Que::Unique::THREAD_LOCAL_KEY]
|
18
|
+
unless thread_local_hash
|
19
|
+
raise "UniqueQueJob #{self} being scheduled outside a transaction"
|
20
|
+
end
|
21
|
+
|
22
|
+
# Once the args are canonicalised, we convert it to a JSON string to match against.
|
23
|
+
canonicalised_args = args.map { |arg| Que::Unique.canonicalise_que_unique_arg(arg) }
|
24
|
+
args_key = { self => canonicalised_args }.to_json
|
25
|
+
# If this is already known then don't enqueue it again. Otherwise, add it to the last
|
26
|
+
# element of the array.
|
27
|
+
if thread_local_hash.key?(args_key)
|
28
|
+
::Rails.logger.debug "Que::Unique - #{self} - Already scheduled: #{args_key}"
|
29
|
+
else
|
30
|
+
::Rails.logger.debug "Que::Unique - #{self} - Enqueuing #{args_key}"
|
31
|
+
thread_local_hash[args_key] = true
|
32
|
+
enqueue_after_unique(*canonicalised_args)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
alias_method :enqueue_after_unique, :enqueue
|
37
|
+
alias_method :enqueue, :enqueue_before_unique
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class << self
|
42
|
+
def canonicalise_que_unique_arg(value)
|
43
|
+
case value
|
44
|
+
when Class
|
45
|
+
# When we try to enqueue a Class as an arg (very common), to_json chokes.
|
46
|
+
# We must convert it to a string manually.
|
47
|
+
value.to_s
|
48
|
+
when Hash
|
49
|
+
# Hashes are sorted by insertion order by default, so instead, create a new
|
50
|
+
# hash sorted by key/value pairs.
|
51
|
+
value.sort.to_h
|
52
|
+
else
|
53
|
+
value
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
metadata
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: que-unique
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bamboo Engineering
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-12-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.0'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '6.0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '4.0'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '6.0'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: que
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0.12'
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0.12'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: combustion
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: pg
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: pry-byebug
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: que-testing
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: rspec
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: rubocop
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
type: :development
|
125
|
+
prerelease: false
|
126
|
+
version_requirements: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '0'
|
131
|
+
- !ruby/object:Gem::Dependency
|
132
|
+
name: rubocop-rake
|
133
|
+
requirement: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
type: :development
|
139
|
+
prerelease: false
|
140
|
+
version_requirements: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
description:
|
146
|
+
email:
|
147
|
+
- dev@bambooloans.com
|
148
|
+
executables: []
|
149
|
+
extensions: []
|
150
|
+
extra_rdoc_files: []
|
151
|
+
files:
|
152
|
+
- lib/que/unique.rb
|
153
|
+
- lib/que/unique/constants.rb
|
154
|
+
- lib/que/unique/transaction_class_methods.rb
|
155
|
+
- lib/que/unique/version.rb
|
156
|
+
homepage: https://github.com/bambooengineering/que-unique
|
157
|
+
licenses:
|
158
|
+
- MIT
|
159
|
+
metadata:
|
160
|
+
homepage_uri: https://github.com/bambooengineering/que-unique
|
161
|
+
source_code_uri: https://github.com/bambooengineering/que-unique
|
162
|
+
changelog_uri: https://github.com/bambooengineering/que-unique/CHANGELOG.md
|
163
|
+
post_install_message:
|
164
|
+
rdoc_options: []
|
165
|
+
require_paths:
|
166
|
+
- lib
|
167
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - ">="
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '0'
|
172
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
173
|
+
requirements:
|
174
|
+
- - ">="
|
175
|
+
- !ruby/object:Gem::Version
|
176
|
+
version: '0'
|
177
|
+
requirements: []
|
178
|
+
rubygems_version: 3.2.7
|
179
|
+
signing_key:
|
180
|
+
specification_version: 4
|
181
|
+
summary: A gem that removes duplicates when multiple copies of a que job are enqueued.
|
182
|
+
test_files: []
|