active_publisher 1.4.2 → 1.6.0.pre1

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: 29d5272d509cc5f9a8e2ff0de59457ef5de1a98e57db0d777feb9e27f6e4e75d
4
- data.tar.gz: 97b72119524a26af0caf2536f71e08547dbc3785ce6aacf3143a848a325a9cee
3
+ metadata.gz: c119d81b1c0b6d5f0f34ecc50fcfc5dd01a122b0fe4dc34c1e846532e763b88f
4
+ data.tar.gz: 23201174a88e23d15832806617ed3bfab36d4d0f8999fdbe27276654f995c1f1
5
5
  SHA512:
6
- metadata.gz: 83072d8997f470c99b02c683cddc669b57e6087576fae90ef957b79d414652785a1e4c9b1de384aa35a8c89be2276f539f1abcd17a88a67598496162c2bab4c1
7
- data.tar.gz: e388ff6b32215969e32f437f7663216e703ef53ccd03e792ac427604629e4e658313b095aec14ae18c2bd6b35c6a8e147e22f5130c776d50f7d6a459d164e63b
6
+ metadata.gz: 1d0ac9632558a9c27a18816855188d30b436734916c2c9e076c0608990b34e033eb5f8bfd3813b150f66543852e714680e8274dd7660dbdfd996a4aca9f81ab9
7
+ data.tar.gz: e4f244ab7ccdf4a3e5111de0c917885681e4763cd3b1f8f658cd46c8242129ec97fb06f18b469e4064b1caab3e49a3d97ada09d8ddad6aa118d5a3370b68e128
data/.circleci/config.yml CHANGED
@@ -1,57 +1,92 @@
1
- # Inspired by: http://mikebian.co/running-tests-against-multiple-ruby-versions-using-circleci/
2
-
3
1
  version: 2.1
4
2
 
5
- orbs:
6
- ruby: circleci/ruby@1.1
7
-
8
3
  jobs:
9
- test:
10
- parallelism: 1
4
+ build_and_test:
11
5
  parameters:
12
- ruby-image:
6
+ docker_image:
13
7
  type: string
8
+ description: "The Ruby or JRuby Docker image to test against"
9
+
14
10
  docker:
15
- - image: << parameters.ruby-image >>
16
- - image: rabbitmq
11
+ # 1. The Primary Container (where your code actually runs)
12
+ - image: << parameters.docker_image >>
13
+ environment:
14
+ JRUBY_OPTS: "-J-Xmx1024m"
15
+ RAILS_ENV: test
16
+ # Tell your app where to find RabbitMQ (if your app uses this ENV var)
17
+ RABBITMQ_URL: "amqp://guest:guest@localhost:5672"
18
+
19
+ # 2. The Service Container (runs in the background)
20
+ - image: rabbitmq:3
21
+ # If you need the management UI for debugging, use `rabbitmq:3-management` instead
22
+ # environment:
23
+ # RABBITMQ_DEFAULT_USER: guest
24
+ # RABBITMQ_DEFAULT_PASS: guest
25
+
26
+ working_directory: ~/project
17
27
 
18
28
  steps:
19
29
  - checkout
30
+
20
31
  - run:
21
- name: install dockerize
22
- command: wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz && sudo tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz && rm dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz
23
- environment:
24
- DOCKERIZE_VERSION: v0.3.0
25
- - run:
26
- name: Wait for rabbitmq
27
- command: dockerize -wait tcp://localhost:5672 -timeout 1m
28
- - run:
29
- name: Install bundler
30
- command: gem install bundler
32
+ name: Install System Dependencies
33
+ command: |
34
+ if [ "$(id -u)" = "0" ]; then
35
+ apt-get update && apt-get install -y build-essential git
36
+ else
37
+ sudo apt-get update && sudo apt-get install -y build-essential git
38
+ fi
39
+
40
+ # Note: We added the docker_image parameter to the cache key
41
+ # so MRI and JRuby gems don't conflict.
42
+ - restore_cache:
43
+ keys:
44
+ - v1-gems-<< parameters.docker_image >>-{{ checksum "Gemfile.lock" }}
45
+ - v1-gems-<< parameters.docker_image >>-
46
+
31
47
  - run:
32
- name: Which bundler?
33
- command: bundle -v
48
+ name: Install Ruby Dependencies
49
+ command: |
50
+ gem install bundler
51
+ bundle config set --local path 'vendor/bundle'
52
+ bundle install --jobs=4 --retry=3
53
+
54
+ - save_cache:
55
+ paths:
56
+ - ./vendor/bundle
57
+ key: v1-gems-<< parameters.docker_image >>-{{ checksum "Gemfile.lock" }}
58
+
59
+ # Wait for RabbitMQ to be ready before running tests.
60
+ # Service containers can sometimes take a few seconds to boot up.
34
61
  - run:
35
- name: bundle install
36
- command: bundle install
62
+ name: Wait for RabbitMQ
63
+ command: |
64
+ if [ "$(id -u)" = "0" ]; then
65
+ apt-get install -y netcat-openbsd
66
+ else
67
+ sudo apt-get install -y netcat-openbsd
68
+ fi
69
+
70
+ echo "Waiting for RabbitMQ to start..."
71
+ while ! nc -z localhost 5672; do
72
+ sleep 1
73
+ done
74
+ echo "RabbitMQ is ready!"
75
+
37
76
  - run:
38
- name: rspec
77
+ name: Run Tests
39
78
  command: bundle exec rspec
40
79
 
41
- # strangely, there seems to be very little documentation about exactly how martix builds work.
42
- # By defining a param inside your job definition, Circle CI will automatically spawn a job for
43
- # unique param value passed via `matrix`. Neat!
44
- # https://circleci.com/blog/circleci-matrix-jobs/
45
80
  workflows:
46
- build_and_test:
81
+ version: 2
82
+ ruby_compatibility_matrix:
47
83
  jobs:
48
- - test:
84
+ - build_and_test:
85
+ name: test-<< matrix.docker_image >>
49
86
  matrix:
50
87
  parameters:
51
- ruby-image:
52
- - circleci/ruby:2.6
53
- - circleci/ruby:2.7
54
- - cimg/ruby:3.0
55
- - cimg/ruby:3.1
56
- - circleci/jruby:9.2
57
- - circleci/jruby:9.3
88
+ docker_image:
89
+ - "cimg/ruby:3.1"
90
+ - "cimg/ruby:3.4"
91
+ - "jruby:9.4"
92
+ - "jruby:10"
@@ -0,0 +1,44 @@
1
+ name: Build and Test
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ ruby-version: ['3.1', '3.4', 'jruby-9.4', 'jruby-10']
16
+
17
+ services:
18
+ rabbitmq:
19
+ image: rabbitmq
20
+ ports:
21
+ - 5672:5672
22
+ # GHA natively waits for the service to be healthy, replacing `dockerize`
23
+ options: >-
24
+ --health-cmd "rabbitmq-diagnostics -q ping"
25
+ --health-interval 10s
26
+ --health-timeout 5s
27
+ --health-retries 5
28
+
29
+ steps:
30
+ - name: Checkout code
31
+ uses: actions/checkout@v4
32
+
33
+ - name: Set up Ruby
34
+ uses: ruby/setup-ruby@v1
35
+ with:
36
+ ruby-version: ${{ matrix.ruby-version }}
37
+ # This automatically runs `bundle install` and caches the gems for faster runs!
38
+ bundler-cache: true
39
+
40
+ - name: Which bundler?
41
+ run: bundle -v
42
+
43
+ - name: RSpec
44
+ run: bundle exec rspec
@@ -26,9 +26,10 @@ Gem::Specification.new do |spec|
26
26
  spec.add_dependency 'bunny', '~> 2.1'
27
27
  end
28
28
 
29
- spec.add_dependency 'activesupport', '>= 3.2'
29
+ spec.required_ruby_version = '>= 3.1.0'
30
+
31
+ spec.add_dependency 'activesupport', '>= 6.0'
30
32
  spec.add_dependency 'concurrent-ruby'
31
- spec.add_dependency 'multi_op_queue', '>= 0.2.0'
32
33
 
33
34
  spec.add_development_dependency "benchmark-ips"
34
35
  spec.add_development_dependency "bundler"
@@ -20,7 +20,7 @@ module ActivePublisher
20
20
  self.back_pressure_strategy = back_pressure_strategy
21
21
  @max_queue_size = max_queue_size
22
22
  @supervisor_interval = supervisor_interval
23
- @queue = ::MultiOpQueue::Queue.new
23
+ @queue = ::ActivePublisher::MultiOpQueue::Queue.new
24
24
  @consumers = {}
25
25
  create_and_supervise_consumers!
26
26
  end
@@ -1,9 +1,9 @@
1
- require "active_publisher/message"
2
1
  require "active_publisher/async/in_memory_adapter/async_queue"
3
2
  require "active_publisher/async/in_memory_adapter/channel"
4
3
  require "active_publisher/async/in_memory_adapter/consumer_thread"
4
+ require "active_publisher/message"
5
+ require "active_publisher/multi_op_queue"
5
6
  require "concurrent"
6
- require "multi_op_queue"
7
7
 
8
8
  module ActivePublisher
9
9
  module Async
@@ -1,7 +1,7 @@
1
1
  require "active_publisher"
2
- require "active_publisher/message"
3
2
  require "active_publisher/async/redis_adapter/consumer"
4
- require "multi_op_queue"
3
+ require "active_publisher/message"
4
+ require "active_publisher/multi_op_queue"
5
5
 
6
6
  module ActivePublisher
7
7
  module Async
@@ -26,7 +26,7 @@ module ActivePublisher
26
26
  # do something with supervision ?
27
27
  @redis_pool = new_redis_pool
28
28
  @async_queue = ::ActivePublisher::Async::RedisAdapter::Consumer.new(redis_pool)
29
- @queue = ::MultiOpQueue::Queue.new
29
+ @queue = ::ActivePublisher::MultiOpQueue::Queue.new
30
30
  @flush_max = ::ActivePublisher.configuration.messages_per_batch
31
31
  @flush_min = @flush_max / 2
32
32
 
@@ -84,9 +84,9 @@ module ActivePublisher
84
84
  absolute_config_path = ::File.expand_path(::File.join("config", "active_publisher.yml"))
85
85
  action_subscriber_config_file = ::File.expand_path(::File.join("config", "action_subscriber.yml"))
86
86
 
87
- if ::File.exists?(absolute_config_path)
87
+ if ::File.exist?(absolute_config_path)
88
88
  yaml_config = load_yaml_config_from_file(absolute_config_path)[env]
89
- elsif ::File.exists?(action_subscriber_config_file)
89
+ elsif ::File.exist?(action_subscriber_config_file)
90
90
  yaml_config = load_yaml_config_from_file(action_subscriber_config_file)[env]
91
91
  end
92
92
 
@@ -0,0 +1,203 @@
1
+ module ActivePublisher
2
+ module MultiOpQueue
3
+ # Original Queue implementation from Ruby-2.0.0
4
+ # https://github.com/ruby/ruby/blob/ruby_2_0_0/lib/thread.rb
5
+ #
6
+ # This class provides a way to synchronize communication between threads.
7
+ #
8
+ # Example:
9
+ #
10
+ # require 'thread'
11
+ #
12
+ # queue = Queue.new
13
+ #
14
+ # producer = Thread.new do
15
+ # 5.times do |i|
16
+ # sleep rand(i) # simulate expense
17
+ # queue << i
18
+ # puts "#{i} produced"
19
+ # end
20
+ # end
21
+ #
22
+ # consumer = Thread.new do
23
+ # 5.times do |i|
24
+ # value = queue.pop
25
+ # sleep rand(i/2) # simulate expense
26
+ # puts "consumed #{value}"
27
+ # end
28
+ # end
29
+ #
30
+ # consumer.join
31
+ #
32
+ class Queue
33
+ #
34
+ # Creates a new queue.
35
+ #
36
+ def initialize
37
+ @que = []
38
+ @num_waiting = 0
39
+ @mutex = Mutex.new
40
+ @cond = ConditionVariable.new
41
+ end
42
+
43
+ #
44
+ # Concatenates +ary+ onto the queue.
45
+ #
46
+ def concat(ary)
47
+ handle_interrupt do
48
+ @mutex.synchronize do
49
+ @que.concat ary
50
+ @cond.signal
51
+ end
52
+ end
53
+ end
54
+
55
+ #
56
+ # Pushes +obj+ to the queue.
57
+ #
58
+ def push(obj)
59
+ handle_interrupt do
60
+ @mutex.synchronize do
61
+ @que.push obj
62
+ @cond.signal
63
+ end
64
+ end
65
+ end
66
+
67
+ #
68
+ # Alias of push
69
+ #
70
+ alias << push
71
+
72
+ #
73
+ # Alias of push
74
+ #
75
+ alias enq push
76
+
77
+ #
78
+ # Retrieves data from the queue. If the queue is empty, the calling thread is
79
+ # suspended until data is pushed onto the queue. If +non_block+ is true, the
80
+ # thread isn't suspended, and an exception is raised.
81
+ #
82
+ def pop(non_block=false)
83
+ handle_interrupt do
84
+ @mutex.synchronize do
85
+ while true
86
+ if @que.empty?
87
+ if non_block
88
+ raise ThreadError, "queue empty"
89
+ else
90
+ begin
91
+ @num_waiting += 1
92
+ @cond.wait @mutex
93
+ ensure
94
+ @num_waiting -= 1
95
+ end
96
+ end
97
+ else
98
+ return @que.shift
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ #
106
+ # Alias of pop
107
+ #
108
+ alias shift pop
109
+
110
+ #
111
+ # Alias of pop
112
+ #
113
+ alias deq pop
114
+
115
+ #
116
+ # Retrieves data from the queue and returns array of contents.
117
+ # If +num_to_pop+ are available in the queue then multiple elements are returned in array response
118
+ # If the queue is empty, the calling thread is
119
+ # suspended until data is pushed onto the queue. If +non_block+ is true, the
120
+ # thread isn't suspended, and an exception is raised.
121
+ #
122
+ def pop_up_to(num_to_pop = 1, opts = {})
123
+ case opts
124
+ when TrueClass, FalseClass
125
+ non_bock = opts
126
+ when Hash
127
+ timeout = opts.fetch(:timeout, nil)
128
+ non_block = opts.fetch(:non_block, false)
129
+ end
130
+
131
+ handle_interrupt do
132
+ @mutex.synchronize do
133
+ while true
134
+ if @que.empty?
135
+ if non_block
136
+ raise ThreadError, "queue empty"
137
+ else
138
+ begin
139
+ @num_waiting += 1
140
+ @cond.wait(@mutex, timeout)
141
+ return nil if @que.empty?
142
+ ensure
143
+ @num_waiting -= 1
144
+ end
145
+ end
146
+ else
147
+ return @que.shift(num_to_pop)
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
153
+
154
+ #
155
+ # Returns +true+ if the queue is empty.
156
+ #
157
+ def empty?
158
+ @que.empty?
159
+ end
160
+
161
+ #
162
+ # Removes all objects from the queue.
163
+ #
164
+ def clear
165
+ @que.clear
166
+ end
167
+
168
+ #
169
+ # Returns the length of the queue.
170
+ #
171
+ def length
172
+ @que.length
173
+ end
174
+
175
+ #
176
+ # Alias of length.
177
+ #
178
+ alias size length
179
+
180
+ #
181
+ # Returns the number of threads waiting on the queue.
182
+ #
183
+ def num_waiting
184
+ @num_waiting
185
+ end
186
+
187
+ private
188
+
189
+ def handle_interrupt
190
+ @handle_interrupt = Thread.respond_to?(:handle_interrupt) if @handle_interrupt.nil?
191
+
192
+ if @handle_interrupt
193
+ Thread.handle_interrupt(StandardError => :on_blocking) do
194
+ yield
195
+ end
196
+ else
197
+ yield
198
+ end
199
+ end
200
+ end
201
+ end
202
+
203
+ end
@@ -1,3 +1,3 @@
1
1
  module ActivePublisher
2
- VERSION = "1.4.2"
2
+ VERSION = "1.6.0.pre1"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_publisher
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.2
4
+ version: 1.6.0.pre1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Stien
@@ -9,10 +9,9 @@ authors:
9
9
  - Brandon Dewitt
10
10
  - Devin Christensen
11
11
  - Michael Ries
12
- autorequire:
13
12
  bindir: exe
14
13
  cert_chain: []
15
- date: 2022-05-10 00:00:00.000000000 Z
14
+ date: 1980-01-02 00:00:00.000000000 Z
16
15
  dependencies:
17
16
  - !ruby/object:Gem::Dependency
18
17
  name: bunny
@@ -34,14 +33,14 @@ dependencies:
34
33
  requirements:
35
34
  - - ">="
36
35
  - !ruby/object:Gem::Version
37
- version: '3.2'
36
+ version: '6.0'
38
37
  type: :runtime
39
38
  prerelease: false
40
39
  version_requirements: !ruby/object:Gem::Requirement
41
40
  requirements:
42
41
  - - ">="
43
42
  - !ruby/object:Gem::Version
44
- version: '3.2'
43
+ version: '6.0'
45
44
  - !ruby/object:Gem::Dependency
46
45
  name: concurrent-ruby
47
46
  requirement: !ruby/object:Gem::Requirement
@@ -56,20 +55,6 @@ dependencies:
56
55
  - - ">="
57
56
  - !ruby/object:Gem::Version
58
57
  version: '0'
59
- - !ruby/object:Gem::Dependency
60
- name: multi_op_queue
61
- requirement: !ruby/object:Gem::Requirement
62
- requirements:
63
- - - ">="
64
- - !ruby/object:Gem::Version
65
- version: 0.2.0
66
- type: :runtime
67
- prerelease: false
68
- version_requirements: !ruby/object:Gem::Requirement
69
- requirements:
70
- - - ">="
71
- - !ruby/object:Gem::Version
72
- version: 0.2.0
73
58
  - !ruby/object:Gem::Dependency
74
59
  name: benchmark-ips
75
60
  requirement: !ruby/object:Gem::Requirement
@@ -180,6 +165,7 @@ extensions: []
180
165
  extra_rdoc_files: []
181
166
  files:
182
167
  - ".circleci/config.yml"
168
+ - ".github/workflows/ruby.yaml"
183
169
  - ".gitignore"
184
170
  - ".rspec"
185
171
  - CODE_OF_CONDUCT.md
@@ -203,12 +189,12 @@ files:
203
189
  - lib/active_publisher/connection.rb
204
190
  - lib/active_publisher/logging.rb
205
191
  - lib/active_publisher/message.rb
192
+ - lib/active_publisher/multi_op_queue.rb
206
193
  - lib/active_publisher/version.rb
207
194
  homepage: https://github.com/mxenabled/active_publisher
208
195
  licenses:
209
196
  - MIT
210
197
  metadata: {}
211
- post_install_message:
212
198
  rdoc_options: []
213
199
  require_paths:
214
200
  - lib
@@ -216,15 +202,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
216
202
  requirements:
217
203
  - - ">="
218
204
  - !ruby/object:Gem::Version
219
- version: '0'
205
+ version: 3.1.0
220
206
  required_rubygems_version: !ruby/object:Gem::Requirement
221
207
  requirements:
222
208
  - - ">="
223
209
  - !ruby/object:Gem::Version
224
210
  version: '0'
225
211
  requirements: []
226
- rubygems_version: 3.3.13
227
- signing_key:
212
+ rubygems_version: 3.6.9
228
213
  specification_version: 4
229
214
  summary: Aims to make publishing work across MRI and jRuby painless and add some nice
230
215
  features like automatially publishing lifecycle events for ActiveRecord models.