gcpc 0.0.7 → 0.0.8

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: 5fdb3019e64a9e547b7fb58a1a5ebf45b82020029f047dc2f7fcaa237d720093
4
- data.tar.gz: 02a5b5b94f4bed91f1d49bd8c8bf0f97fa568b02bd05d543205b482c9fa47570
3
+ metadata.gz: d89748f1a7066c40f0b4c6c4477bab098ab45c206ca7f019d5f29f13be62c875
4
+ data.tar.gz: 76261a92198cd9e53629455aba3859117e649004838da3752ead8dbbe8445f14
5
5
  SHA512:
6
- metadata.gz: ff644c9d6d8257aa128e940547a31db1a9190e6a8165bf6ad0e776c3cc6aef00ed22f68f98812fa938186ea0cba069fb2d53c29e478ea5ec92a6de7b7bac5d5d
7
- data.tar.gz: c50b8e7e95f3c1651c0ecfdb6ef85e16ba4503eced5a74331eb6173ad2ebe87f5475287097b5ab3912ae20d0989e5462ab4578b0e866f4211843cb1b70f69bdc
6
+ metadata.gz: fdf792b95470615cc0e9967dab7efaccde16aa62a60dbde2c0c0728df37e13d51cc3f046585152fde3a528032ebe39b59fee8a05e0f86680ffafb37bfd4b5350
7
+ data.tar.gz: 77b9b3d6f3a61bfeef13b4094363aa98c1a91679dd532712753061abc761d4a13e31696b7036b9d84c9b78a9b6cd3e055b896923624859d8a82cf4693af2762b
@@ -0,0 +1,24 @@
1
+ name: test
2
+
3
+ on:
4
+ push:
5
+
6
+ jobs:
7
+ test:
8
+ runs-on: ubuntu-latest
9
+ strategy:
10
+ matrix:
11
+ ruby-version: ['3.2', '3.1', '3.0']
12
+ steps:
13
+ - uses: actions/checkout@v3
14
+ - name: Set up Ruby ${{ matrix.ruby-version }}
15
+ uses: ruby/setup-ruby@v1
16
+ with:
17
+ ruby-version: ${{ matrix.ruby-version }}
18
+ bundler-cache: true
19
+ - name: Run rspec
20
+ run: bundle exec rspec
21
+ - name: run pubsub emulator
22
+ run: docker run -d -p 8085:8085 -it gcr.io/google.com/cloudsdktool/google-cloud-cli:latest gcloud beta emulators pubsub start --host-port=0.0.0.0:8085
23
+ - name: Run rspec with emulator
24
+ run: bundle exec rspec --tag emulator
data/CHANGELOG.md CHANGED
@@ -4,16 +4,20 @@
4
4
  <!-- All changes (implementation, or doc changes) are worth noting. -->
5
5
  <!-- The changes listed above will go below when a new release is being prepared. -->
6
6
 
7
+ ## 0.0.8
8
+
9
+ - Add an API for heartbeat https://github.com/wantedly/gcpc/pull/25
10
+
7
11
  ## 0.0.7
8
12
 
9
- - Add explicit loading of forwardable https://github.com/south37/gcpc/pull/10
10
- - Add ruby 2.7 as a test target https://github.com/south37/gcpc/pull/12
13
+ - Add explicit loading of forwardable https://github.com/wantedly/gcpc/pull/10
14
+ - Add ruby 2.7 as a test target https://github.com/wantedly/gcpc/pull/12
11
15
 
12
16
  ## 0.0.6
13
17
 
14
- - Add test of interceptors https://github.com/south37/gcpc/pull/7
15
- - Add publish_batch https://github.com/south37/gcpc/pull/6
18
+ - Add test of interceptors https://github.com/wantedly/gcpc/pull/7
19
+ - Add publish_batch https://github.com/wantedly/gcpc/pull/6
16
20
 
17
21
  ## 0.0.5
18
22
 
19
- - Add publish_async https://github.com/south37/gcpc/pull/5
23
+ - Add publish_async https://github.com/wantedly/gcpc/pull/5
data/Gemfile.lock CHANGED
@@ -1,74 +1,82 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gcpc (0.0.7)
4
+ gcpc (0.0.8)
5
5
  google-cloud-pubsub
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- addressable (2.7.0)
11
- public_suffix (>= 2.0.2, < 5.0)
10
+ addressable (2.8.5)
11
+ public_suffix (>= 2.0.2, < 6.0)
12
12
  coderay (1.1.3)
13
- concurrent-ruby (1.1.7)
13
+ concurrent-ruby (1.2.2)
14
14
  diff-lcs (1.3)
15
- faraday (1.3.0)
16
- faraday-net_http (~> 1.0)
17
- multipart-post (>= 1.2, < 3)
18
- ruby2_keywords
19
- faraday-net_http (1.0.0)
20
- gapic-common (0.3.4)
21
- google-protobuf (~> 3.12, >= 3.12.2)
22
- googleapis-common-protos (>= 1.3.9, < 2.0)
23
- googleapis-common-protos-types (>= 1.0.4, < 2.0)
24
- googleauth (~> 0.9)
25
- grpc (~> 1.25)
26
- google-cloud-core (1.5.0)
15
+ faraday (2.7.10)
16
+ faraday-net_http (>= 2.0, < 3.1)
17
+ ruby2_keywords (>= 0.0.4)
18
+ faraday-net_http (3.0.2)
19
+ faraday-retry (2.2.0)
20
+ faraday (~> 2.0)
21
+ gapic-common (0.19.1)
22
+ faraday (>= 1.9, < 3.a)
23
+ faraday-retry (>= 1.0, < 3.a)
24
+ google-protobuf (~> 3.14)
25
+ googleapis-common-protos (>= 1.3.12, < 2.a)
26
+ googleapis-common-protos-types (>= 1.3.1, < 2.a)
27
+ googleauth (~> 1.0)
28
+ grpc (~> 1.36)
29
+ google-cloud-core (1.6.0)
27
30
  google-cloud-env (~> 1.0)
28
31
  google-cloud-errors (~> 1.0)
29
- google-cloud-env (1.4.0)
30
- faraday (>= 0.17.3, < 2.0)
31
- google-cloud-errors (1.0.1)
32
- google-cloud-pubsub (2.3.0)
32
+ google-cloud-env (1.6.0)
33
+ faraday (>= 0.17.3, < 3.0)
34
+ google-cloud-errors (1.3.1)
35
+ google-cloud-pubsub (2.15.4)
33
36
  concurrent-ruby (~> 1.1)
34
37
  google-cloud-core (~> 1.5)
35
- google-cloud-pubsub-v1 (~> 0.0)
36
- google-cloud-pubsub-v1 (0.2.0)
37
- gapic-common (~> 0.3)
38
+ google-cloud-pubsub-v1 (~> 0.8)
39
+ retriable (~> 3.1)
40
+ google-cloud-pubsub-v1 (0.17.3)
41
+ gapic-common (>= 0.19.1, < 2.a)
38
42
  google-cloud-errors (~> 1.0)
39
- grpc-google-iam-v1 (>= 0.6.10, < 2.0)
40
- google-protobuf (3.14.0)
41
- googleapis-common-protos (1.3.10)
42
- google-protobuf (~> 3.11)
43
- googleapis-common-protos-types (>= 1.0.5, < 2.0)
43
+ google-iam-v1 (>= 0.4, < 2.a)
44
+ google-iam-v1 (0.5.2)
45
+ gapic-common (>= 0.19.1, < 2.a)
46
+ google-cloud-errors (~> 1.0)
47
+ grpc-google-iam-v1 (~> 1.1)
48
+ google-protobuf (3.23.4)
49
+ googleapis-common-protos (1.4.0)
50
+ google-protobuf (~> 3.14)
51
+ googleapis-common-protos-types (~> 1.2)
44
52
  grpc (~> 1.27)
45
- googleapis-common-protos-types (1.0.5)
46
- google-protobuf (~> 3.11)
47
- googleauth (0.14.0)
48
- faraday (>= 0.17.3, < 2.0)
53
+ googleapis-common-protos-types (1.8.0)
54
+ google-protobuf (~> 3.18)
55
+ googleauth (1.7.0)
56
+ faraday (>= 0.17.3, < 3.a)
49
57
  jwt (>= 1.4, < 3.0)
50
58
  memoist (~> 0.16)
51
59
  multi_json (~> 1.11)
52
60
  os (>= 0.9, < 2.0)
53
- signet (~> 0.14)
54
- grpc (1.34.0)
55
- google-protobuf (~> 3.13)
61
+ signet (>= 0.16, < 2.a)
62
+ grpc (1.56.2)
63
+ google-protobuf (~> 3.23)
56
64
  googleapis-common-protos-types (~> 1.0)
57
- grpc-google-iam-v1 (0.6.10)
58
- google-protobuf (~> 3.11)
59
- googleapis-common-protos (>= 1.3.10, < 2.0)
60
- grpc (~> 1.27)
61
- jwt (2.2.2)
65
+ grpc-google-iam-v1 (1.3.0)
66
+ google-protobuf (~> 3.18)
67
+ googleapis-common-protos (~> 1.4)
68
+ grpc (~> 1.41)
69
+ jwt (2.7.1)
62
70
  memoist (0.16.2)
63
71
  method_source (1.0.0)
64
72
  multi_json (1.15.0)
65
- multipart-post (2.1.1)
66
- os (1.1.1)
73
+ os (1.1.4)
67
74
  pry (0.13.1)
68
75
  coderay (~> 1.1)
69
76
  method_source (~> 1.0)
70
- public_suffix (4.0.6)
77
+ public_suffix (5.0.3)
71
78
  rake (13.0.1)
79
+ retriable (3.1.2)
72
80
  rspec (3.8.0)
73
81
  rspec-core (~> 3.8.0)
74
82
  rspec-expectations (~> 3.8.0)
@@ -82,10 +90,10 @@ GEM
82
90
  diff-lcs (>= 1.2.0, < 2.0)
83
91
  rspec-support (~> 3.8.0)
84
92
  rspec-support (3.8.0)
85
- ruby2_keywords (0.0.2)
86
- signet (0.14.0)
87
- addressable (~> 2.3)
88
- faraday (>= 0.17.3, < 2.0)
93
+ ruby2_keywords (0.0.5)
94
+ signet (0.17.0)
95
+ addressable (~> 2.8)
96
+ faraday (>= 0.17.5, < 3.a)
89
97
  jwt (>= 1.5, < 3.0)
90
98
  multi_json (~> 1.10)
91
99
 
data/README.md CHANGED
@@ -154,7 +154,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
154
154
 
155
155
  ## Contributing
156
156
 
157
- Bug reports and pull requests are welcome on GitHub at https://github.com/south37/gcpc.
157
+ Bug reports and pull requests are welcome on GitHub at https://github.com/wantedly/gcpc.
158
158
 
159
159
  ## License
160
160
 
data/gcpc.gemspec CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
 
12
12
  spec.summary = %q{Google Cloud Pub/Sub Client}
13
13
  spec.description = %q{Google Cloud Pub/Sub Client}
14
- spec.homepage = "https://github.com/south37/gcpc"
14
+ spec.homepage = "https://github.com/wantedly/gcpc"
15
15
  spec.license = "MIT"
16
16
 
17
17
  # Specify which files should be added to the gem when it is released.
@@ -0,0 +1,18 @@
1
+ require "singleton"
2
+
3
+ module Gcpc
4
+ class Config
5
+ include Singleton
6
+ attr_reader :beat
7
+
8
+ def initialize
9
+ @beat = []
10
+ end
11
+
12
+ def on(event, &block)
13
+ raise ArgumentError, "Invalid event name: #{event}" if event != :beat
14
+
15
+ @beat << block
16
+ end
17
+ end
18
+ end
@@ -4,6 +4,9 @@ module Gcpc
4
4
  class Subscriber
5
5
  class Engine
6
6
  WAIT_INTERVAL = 1
7
+ WORKER_DEAD_THRESHOLD = 30 # second
8
+ BEAT_INTERVAL = 10
9
+ HEART_BEAT_WORKER_NAME = 'heartbeat-worker'
7
10
 
8
11
  # @param [Google::Cloud::Pubsub::Subscription] subscription
9
12
  # @param [<#handle, #on_error>] interceptors
@@ -20,6 +23,9 @@ module Gcpc
20
23
  @interceptors = interceptors
21
24
  @ack_immediately = ack_immediately
22
25
  @logger = logger
26
+ @subscriber_thread_status = {}
27
+ @subscriber_thread_status_mutex = Mutex.new
28
+ @heartbeat_worker_thread = nil
23
29
 
24
30
  @subscriber = nil # @subscriber is created by calling `#run`
25
31
  @handler = nil # @handler must be registered by `#handle`
@@ -47,6 +53,8 @@ module Gcpc
47
53
 
48
54
  @logger.info("Started")
49
55
 
56
+ run_heartbeat_worker
57
+
50
58
  loop_until_receiving_signals(signals)
51
59
  end
52
60
 
@@ -64,6 +72,16 @@ module Gcpc
64
72
  @logger.info('Stopping, will wait for background threads to exit')
65
73
 
66
74
  @subscriber.stop
75
+
76
+ begin
77
+ @heartbeat_worker_thread&.wakeup
78
+ # ThreadError exeption will be raised when the thread already dead
79
+ rescue ThreadError => e
80
+ @logger.error(e.message)
81
+ end
82
+
83
+ @heartbeat_worker_thread&.join
84
+
67
85
  @subscriber.wait!
68
86
 
69
87
  @logger.info('Stopped, background threads are shutdown')
@@ -92,12 +110,51 @@ module Gcpc
92
110
  stop unless stopped?
93
111
  end
94
112
 
113
+ def run_heartbeat_worker
114
+ @heartbeat_worker_thread = Thread.new do
115
+ @logger.info("Starting heartbeat worker...")
116
+ begin
117
+ loop do
118
+ break if stopped?
119
+
120
+ next unless alive?
121
+
122
+ Gcpc::Config.instance.beat.each(&:call)
123
+
124
+ sleep BEAT_INTERVAL
125
+ end
126
+ ensure
127
+ @logger.info("heartbeat worker stopped")
128
+ end
129
+ end
130
+
131
+ @heartbeat_worker_thread.name = HEART_BEAT_WORKER_NAME
132
+ end
133
+
134
+ def alive?
135
+ # ・When processing a message, write the thread_id and timestamp at the start time into @subscriber_thread_status,
136
+ # and remove that information from @subscriber_thread_status when the processing within that thread is finished.
137
+ # @subscriber_thread_status = {#<Thread:0x000000010302cd40 run>=>1690757417}
138
+ # ・If the processing of the message gets stuck, the key, value will not be removed from @subscriber_thread_status.
139
+ # ・Since the application holds as many callback_threads as @subscriber.callback_threads with Subscription,
140
+ # if the number of threads that have gotten stuck exceeds that callback_threads, it is considered that the worker unable to process Subscription queue.
141
+ return false unless @subscriber && @subscriber.started?
142
+ return false if @subscriber.stopped?
143
+
144
+ number_of_dead_threads = @subscriber_thread_status.count { |_, v| v < Time.now.to_i - WORKER_DEAD_THRESHOLD }
145
+
146
+ return @subscriber.callback_threads > number_of_dead_threads
147
+ end
148
+
149
+
95
150
  # @param [Google::Cloud::Pubsub::ReceivedMessage] message
96
151
  def handle_message(message)
152
+ write_heartbeat_to_subscriber_thread_status
153
+
97
154
  ack(message) if @ack_immediately
98
155
 
99
156
  begin
100
- worker_info("Started hanlding message")
157
+ worker_info("Started handling message")
101
158
  @handler.handle(message)
102
159
  worker_info("Finished hanlding message successfully")
103
160
  rescue => e
@@ -110,11 +167,13 @@ module Gcpc
110
167
 
111
168
  def ack(message)
112
169
  message.ack!
170
+ cleanup_subscriber_thread_status
113
171
  worker_info("Acked message")
114
172
  end
115
173
 
116
174
  def nack(message)
117
175
  message.nack!
176
+ cleanup_subscriber_thread_status
118
177
  worker_info("Nacked message")
119
178
  end
120
179
 
@@ -139,6 +198,27 @@ module Gcpc
139
198
  def stopped?
140
199
  @stopped_mutex.synchronize { @stopped }
141
200
  end
201
+
202
+ def write_heartbeat_to_subscriber_thread_status
203
+ begin
204
+ @subscriber_thread_status_mutex.synchronize do
205
+ @subscriber_thread_status[Thread.current] = Time.now.to_i
206
+ end
207
+ rescue ThreadError => e
208
+ @logger.info("Falied to write subscriber_thread_status. thread_id: #{Thread.current.object_id}, subscriber_thread_status: #{@subscriber_thread_status}, error: #{e.message}")
209
+ end
210
+ end
211
+
212
+ def cleanup_subscriber_thread_status
213
+ begin
214
+ @subscriber_thread_status_mutex.synchronize do
215
+ # cleanup to avoid memory leak
216
+ @subscriber_thread_status.delete(Thread.current)
217
+ end
218
+ rescue ThreadError => e
219
+ @logger.info("Falied to cleanup subscriber_thread_status. thread_id: #{Thread.current.object_id}, subscriber_thread_status: #{@subscriber_thread_status}, error: #{e.message}")
220
+ end
221
+ end
142
222
  end
143
223
  end
144
224
  end
data/lib/gcpc/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Gcpc
2
- VERSION = "0.0.7"
2
+ VERSION = "0.0.8"
3
3
  end
data/lib/gcpc.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require "gcpc/version"
2
2
  require "gcpc/publisher"
3
3
  require "gcpc/subscriber"
4
+ require "gcpc/config"
4
5
 
5
6
  module Gcpc
6
7
  end
data/renovate.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": [
3
+ "config:base"
4
+ ]
5
+ }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gcpc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nao Minami
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-12 00:00:00.000000000 Z
11
+ date: 2023-08-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -87,9 +87,9 @@ executables: []
87
87
  extensions: []
88
88
  extra_rdoc_files: []
89
89
  files:
90
+ - ".github/workflows/ci.yml"
90
91
  - ".gitignore"
91
92
  - ".rspec"
92
- - ".travis.yml"
93
93
  - CHANGELOG.md
94
94
  - Gemfile
95
95
  - Gemfile.lock
@@ -104,6 +104,7 @@ files:
104
104
  - examples/subscriber-example/subscriber-example.rb
105
105
  - gcpc.gemspec
106
106
  - lib/gcpc.rb
107
+ - lib/gcpc/config.rb
107
108
  - lib/gcpc/publisher.rb
108
109
  - lib/gcpc/publisher/base_interceptor.rb
109
110
  - lib/gcpc/publisher/engine.rb
@@ -118,7 +119,8 @@ files:
118
119
  - lib/gcpc/subscriber/handle_engine.rb
119
120
  - lib/gcpc/subscriber/subscription_client.rb
120
121
  - lib/gcpc/version.rb
121
- homepage: https://github.com/south37/gcpc
122
+ - renovate.json
123
+ homepage: https://github.com/wantedly/gcpc
122
124
  licenses:
123
125
  - MIT
124
126
  metadata: {}
@@ -137,7 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
137
139
  - !ruby/object:Gem::Version
138
140
  version: '0'
139
141
  requirements: []
140
- rubygems_version: 3.1.4
142
+ rubygems_version: 3.4.10
141
143
  signing_key:
142
144
  specification_version: 4
143
145
  summary: Google Cloud Pub/Sub Client
data/.travis.yml DELETED
@@ -1,21 +0,0 @@
1
- ---
2
- sudo: false
3
- language: ruby
4
- cache: bundler
5
- rvm:
6
- - 2.6.6
7
- - 2.7.3
8
- before_install:
9
- - gem install bundler
10
- jobs:
11
- include:
12
- - name: 'test'
13
- script:
14
- - bundle exec rspec
15
- - name: 'test with a emulator'
16
- before_install:
17
- # Start a Cloud Pub/Sub emulator. See https://cloud.google.com/pubsub/docs/emulator
18
- # We use `google/cloud-sdk:321.0.0` because we can't start pubsub with the latest.
19
- - docker run -d -p 8085:8085 -it google/cloud-sdk:321.0.0 gcloud beta emulators pubsub start --host-port=0.0.0.0:8085
20
- script:
21
- - bundle exec rspec --tag emulator