gcpc 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.rspec +1 -0
- data/.travis.yml +19 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +95 -0
- data/LICENSE.txt +21 -0
- data/README.md +161 -0
- data/Rakefile +2 -0
- data/bin/console +10 -0
- data/bin/setup +8 -0
- data/examples/publisher-example/README.md +11 -0
- data/examples/publisher-example/publisher-example.rb +35 -0
- data/examples/subscriber-example/README.md +11 -0
- data/examples/subscriber-example/subscriber-example.rb +73 -0
- data/gcpc.gemspec +31 -0
- data/lib/gcpc.rb +6 -0
- data/lib/gcpc/publisher.rb +42 -0
- data/lib/gcpc/publisher/base_interceptor.rb +14 -0
- data/lib/gcpc/publisher/engine.rb +48 -0
- data/lib/gcpc/publisher/topic_client.rb +33 -0
- data/lib/gcpc/subscriber.rb +50 -0
- data/lib/gcpc/subscriber/base_handler.rb +21 -0
- data/lib/gcpc/subscriber/base_interceptor.rb +23 -0
- data/lib/gcpc/subscriber/default_logger.rb +7 -0
- data/lib/gcpc/subscriber/engine.rb +144 -0
- data/lib/gcpc/subscriber/handle_engine.rb +83 -0
- data/lib/gcpc/subscriber/subscription_client.rb +35 -0
- data/lib/gcpc/version.rb +3 -0
- metadata +141 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d26d83b3ad1b3c23b83aa62eb8742e522eaa14df00d608e33b639848354081db
|
4
|
+
data.tar.gz: 74366ee318ca77cb08baaaf0d99c3021f72e30b744cc38cd66d6fb0bc33dc6b6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f2c90798e86df808662e2906e2ab5b073b102a7aacfb77803dd63f37b72fb559822e0b1b91d9afdd2f929fa6b02ed6f6714df7ca67fa17a74fd3491a2dd5840d
|
7
|
+
data.tar.gz: 4f659b9666d194f9317ab16cee630ba1698168557af6c9ea6bc15fa34e9ee399c3f31ae50fa6ace1db2511cb4192d487e7412ba37043aed590cd75cedd705f5a
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/.travis.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
---
|
2
|
+
sudo: false
|
3
|
+
language: ruby
|
4
|
+
cache: bundler
|
5
|
+
rvm:
|
6
|
+
- 2.6.2
|
7
|
+
before_install:
|
8
|
+
- gem install bundler -v 1.17.2
|
9
|
+
jobs:
|
10
|
+
include:
|
11
|
+
- name: 'test'
|
12
|
+
script:
|
13
|
+
- bundle exec rspec
|
14
|
+
- name: 'test with a emulator'
|
15
|
+
before_install:
|
16
|
+
# Start a Cloud Pub/Sub emulator. See https://cloud.google.com/pubsub/docs/emulator
|
17
|
+
- docker run -d -p 8085:8085 -it google/cloud-sdk:latest gcloud beta emulators pubsub start --host-port=0.0.0.0:8085
|
18
|
+
script:
|
19
|
+
- bundle exec rspec --tag emulator
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
gcpc (0.0.4)
|
5
|
+
google-cloud-pubsub
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
addressable (2.6.0)
|
11
|
+
public_suffix (>= 2.0.2, < 4.0)
|
12
|
+
coderay (1.1.2)
|
13
|
+
concurrent-ruby (1.1.5)
|
14
|
+
diff-lcs (1.3)
|
15
|
+
faraday (0.15.4)
|
16
|
+
multipart-post (>= 1.2, < 3)
|
17
|
+
google-cloud-core (1.3.0)
|
18
|
+
google-cloud-env (~> 1.0)
|
19
|
+
google-cloud-env (1.1.0)
|
20
|
+
faraday (~> 0.11)
|
21
|
+
google-cloud-pubsub (0.36.0)
|
22
|
+
concurrent-ruby (~> 1.0)
|
23
|
+
google-cloud-core (~> 1.2)
|
24
|
+
google-gax (~> 1.3)
|
25
|
+
googleapis-common-protos (>= 1.3.9, < 2.0)
|
26
|
+
grpc-google-iam-v1 (~> 0.6.9)
|
27
|
+
google-gax (1.6.3)
|
28
|
+
google-protobuf (~> 3.2)
|
29
|
+
googleapis-common-protos (>= 1.3.5, < 2.0)
|
30
|
+
googleauth (>= 0.6.2, < 0.10.0)
|
31
|
+
grpc (>= 1.7.2, < 2.0)
|
32
|
+
rly (~> 0.2.3)
|
33
|
+
google-protobuf (3.8.0)
|
34
|
+
googleapis-common-protos (1.3.9)
|
35
|
+
google-protobuf (~> 3.0)
|
36
|
+
googleapis-common-protos-types (~> 1.0)
|
37
|
+
grpc (~> 1.0)
|
38
|
+
googleapis-common-protos-types (1.0.4)
|
39
|
+
google-protobuf (~> 3.0)
|
40
|
+
googleauth (0.8.1)
|
41
|
+
faraday (~> 0.12)
|
42
|
+
jwt (>= 1.4, < 3.0)
|
43
|
+
memoist (~> 0.16)
|
44
|
+
multi_json (~> 1.11)
|
45
|
+
os (>= 0.9, < 2.0)
|
46
|
+
signet (~> 0.7)
|
47
|
+
grpc (1.21.0)
|
48
|
+
google-protobuf (~> 3.7)
|
49
|
+
googleapis-common-protos-types (~> 1.0)
|
50
|
+
grpc-google-iam-v1 (0.6.9)
|
51
|
+
googleapis-common-protos (>= 1.3.1, < 2.0)
|
52
|
+
grpc (~> 1.0)
|
53
|
+
jwt (2.2.1)
|
54
|
+
memoist (0.16.0)
|
55
|
+
method_source (0.9.2)
|
56
|
+
multi_json (1.13.1)
|
57
|
+
multipart-post (2.1.1)
|
58
|
+
os (1.0.1)
|
59
|
+
pry (0.12.2)
|
60
|
+
coderay (~> 1.1.0)
|
61
|
+
method_source (~> 0.9.0)
|
62
|
+
public_suffix (3.1.0)
|
63
|
+
rake (10.5.0)
|
64
|
+
rly (0.2.3)
|
65
|
+
rspec (3.8.0)
|
66
|
+
rspec-core (~> 3.8.0)
|
67
|
+
rspec-expectations (~> 3.8.0)
|
68
|
+
rspec-mocks (~> 3.8.0)
|
69
|
+
rspec-core (3.8.0)
|
70
|
+
rspec-support (~> 3.8.0)
|
71
|
+
rspec-expectations (3.8.2)
|
72
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
73
|
+
rspec-support (~> 3.8.0)
|
74
|
+
rspec-mocks (3.8.0)
|
75
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
76
|
+
rspec-support (~> 3.8.0)
|
77
|
+
rspec-support (3.8.0)
|
78
|
+
signet (0.11.0)
|
79
|
+
addressable (~> 2.3)
|
80
|
+
faraday (~> 0.9)
|
81
|
+
jwt (>= 1.5, < 3.0)
|
82
|
+
multi_json (~> 1.10)
|
83
|
+
|
84
|
+
PLATFORMS
|
85
|
+
ruby
|
86
|
+
|
87
|
+
DEPENDENCIES
|
88
|
+
bundler (~> 1.17)
|
89
|
+
gcpc!
|
90
|
+
pry
|
91
|
+
rake (~> 10.0)
|
92
|
+
rspec (~> 3.2)
|
93
|
+
|
94
|
+
BUNDLED WITH
|
95
|
+
1.17.2
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2019 Nao Minami
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
# Gcpc
|
2
|
+
|
3
|
+
**G**oogle **C**loud **P**ub/Sub **C**lient for Ruby.
|
4
|
+
|
5
|
+
Gcpc provides the implementation of the publisher / subscriber for [Google Cloud Pub/Sub](https://cloud.google.com/pubsub/). You can add some functionality to the publisher / subscriber as interceptors.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'gcpc'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install gcpc
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
`gcpc` have publisher and subscriber implementation of Google Cloud Pub/Sub.
|
26
|
+
|
27
|
+
### Publisher
|
28
|
+
|
29
|
+
To use `Gcpc::Publisher`, pleaese initialize `Gcpc::Publisher` with some configurations.
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
publisher = Gcpc::Publisher.new(
|
33
|
+
project_id: "<project id>",
|
34
|
+
topic: "<topic name>",
|
35
|
+
credentials: "/path/to/credentials",
|
36
|
+
)
|
37
|
+
```
|
38
|
+
|
39
|
+
Then, simply call `Gcpc::Publisher#publish` to post a message!
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
publisher.publish("<message payload>")
|
43
|
+
```
|
44
|
+
|
45
|
+
#### Interceptors
|
46
|
+
|
47
|
+
By using interceptors, you can add some functionality to the publisher.
|
48
|
+
|
49
|
+
For example, you can add logging functionality by adding `LogInterceptor` as shown below.
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
class LogInterceptor < Gcpc::Publisher::BaseInterceptor
|
53
|
+
MyLogger = Logger.new(STDOUT)
|
54
|
+
|
55
|
+
# @param [String] data
|
56
|
+
# @param [Hash] attributes
|
57
|
+
def publish(data, attributes)
|
58
|
+
MyLogger.info "[Interceptor Log] publish data: \"#{data}\", attributes: #{attributes}"
|
59
|
+
yield data, attributes
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
publisher = Gcpc::Publisher.new(
|
64
|
+
project_id: "<project id>",
|
65
|
+
topic: "<topic name>",
|
66
|
+
interceptors: [LogInterceptor],
|
67
|
+
credentials: "/path/to/credentials",
|
68
|
+
)
|
69
|
+
|
70
|
+
publisher.publish("<message payload>")
|
71
|
+
```
|
72
|
+
|
73
|
+
#### Publisher Example
|
74
|
+
A full example code is in [publisher-example](./examples/publisher-example). Please see it.
|
75
|
+
|
76
|
+
### Subscriber
|
77
|
+
|
78
|
+
To use `Gcpc::Subscriber`, pleaese initialize `Gcpc::Subscriber` with some configurations.
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
subscriber = Gcpc::Subscriber.new(
|
82
|
+
project_id: "<project id>",
|
83
|
+
subscription: "<subscription name>",
|
84
|
+
credentials: "/path/to/credentials",
|
85
|
+
)
|
86
|
+
```
|
87
|
+
|
88
|
+
Then, call `Gcpc::Subscriber#handle` to register a handler. A registered handler executes `#handle` callback for each published message.
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
class NopHandler < Gcpc::Subscriber::BaseHandler
|
92
|
+
# @param [String] data
|
93
|
+
# @param [Hash] attributes
|
94
|
+
# @param [Google::Cloud::Pubsub::ReceivedMessage] message
|
95
|
+
def handle(data, attributes, message)
|
96
|
+
# Do nothing. Consume only.
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
subscriber.handle(NopHandler)
|
101
|
+
```
|
102
|
+
|
103
|
+
To start subscribing, please call `Gcpc::Subscriber#start`. It does not return, and run subscribing loops in it.
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
subscriber.run
|
107
|
+
```
|
108
|
+
|
109
|
+
#### Signal Handling
|
110
|
+
|
111
|
+
By default, you can stop a subscriber process by sending `SIGINT`, `SIGTERM`, or `SIGKILL` signals.
|
112
|
+
|
113
|
+
If you want to use other signals, please pass signals to `#run`.
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
subscriber.run(['SIGINT', 'SIGTERM', 'SIGSTOP', 'SIGTSTP'])
|
117
|
+
```
|
118
|
+
|
119
|
+
#### Interceptors
|
120
|
+
|
121
|
+
By using interceptors, you can add some functionality to the subscriber.
|
122
|
+
|
123
|
+
For example, you can add logging functionality by adding `LogInterceptor` as shown below.
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
class LogInterceptor < Gcpc::Subscriber::BaseInterceptor
|
127
|
+
MyLogger = Logger.new(STDOUT)
|
128
|
+
|
129
|
+
# @param [String] data
|
130
|
+
# @param [Hash] attributes
|
131
|
+
# @param [Google::Cloud::Pubsub::ReceivedMessage] message
|
132
|
+
def handle(data, attributes, message)
|
133
|
+
MyLogger.info "[Interceptor Log] subscribed a message: #{message}"
|
134
|
+
yield data, attributes, message
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
subscriber = Gcpc::Subscriber.new(
|
139
|
+
project_id: "<project id>",
|
140
|
+
subscription: "<subscription name>",
|
141
|
+
interceptors: [LogInterceptor],
|
142
|
+
credentials: "/path/to/credentials",
|
143
|
+
)
|
144
|
+
```
|
145
|
+
|
146
|
+
#### Subscriber Example
|
147
|
+
A full example code is in [subscriber-example](./examples/subscriber-example). Please see it.
|
148
|
+
|
149
|
+
## Development
|
150
|
+
|
151
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
152
|
+
|
153
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
154
|
+
|
155
|
+
## Contributing
|
156
|
+
|
157
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/south37/gcpc.
|
158
|
+
|
159
|
+
## License
|
160
|
+
|
161
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
data/bin/setup
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
## publisher example
|
2
|
+
|
3
|
+
An example code of `Gcpc::Publisher`.
|
4
|
+
|
5
|
+
If you want to try `Gcpc`, please execute commands below in the root of this repository.
|
6
|
+
|
7
|
+
```
|
8
|
+
$ gcloud beta emulators pubsub start # Please install Cloud Pub/Sub emulator from https://cloud.google.com/pubsub/docs/emulator for executing this.
|
9
|
+
$ bundle exec ruby examples/subscriber-example/subscriber-example.rb
|
10
|
+
$ bundle exec ruby examples/publisher-example/publisher-example.rb
|
11
|
+
```
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "gcpc"
|
2
|
+
|
3
|
+
# Please execute commands below.
|
4
|
+
#
|
5
|
+
# ```
|
6
|
+
# $ gcloud beta emulators pubsub start
|
7
|
+
# $ bundle exec ruby examples/subscriber-example/subscriber-example.rb
|
8
|
+
# $ bundle exec ruby examples/publisher-example/publisher-example.rb
|
9
|
+
# ```
|
10
|
+
|
11
|
+
PROJECT_ID = "project-example-1"
|
12
|
+
TOPIC_NAME = "topic-example-1"
|
13
|
+
|
14
|
+
class LogInterceptor < Gcpc::Publisher::BaseInterceptor
|
15
|
+
MyLogger = Logger.new(STDOUT)
|
16
|
+
|
17
|
+
def publish(data, attributes)
|
18
|
+
MyLogger.info "[Interceptor Log] publish data: \"#{data}\", attributes: #{attributes}"
|
19
|
+
yield data, attributes
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def main
|
24
|
+
publisher = Gcpc::Publisher.new(
|
25
|
+
project_id: PROJECT_ID,
|
26
|
+
topic: TOPIC_NAME,
|
27
|
+
interceptors: [LogInterceptor],
|
28
|
+
emulator_host: "localhost:8085",
|
29
|
+
)
|
30
|
+
data = ARGV[0] || "message payload"
|
31
|
+
attributes = { publisher: "publisher-example" }
|
32
|
+
publisher.publish(data, attributes)
|
33
|
+
end
|
34
|
+
|
35
|
+
main
|
@@ -0,0 +1,11 @@
|
|
1
|
+
## subscriber example
|
2
|
+
|
3
|
+
An example code of `Gcpc::Subscriber`.
|
4
|
+
|
5
|
+
If you want to try `Gcpc`, please execute commands below in the root of this repository.
|
6
|
+
|
7
|
+
```
|
8
|
+
$ gcloud beta emulators pubsub start # Please install Cloud Pub/Sub emulator from https://cloud.google.com/pubsub/docs/emulator for executing this.
|
9
|
+
$ bundle exec ruby examples/subscriber-example/subscriber-example.rb
|
10
|
+
$ bundle exec ruby examples/publisher-example/publisher-example.rb
|
11
|
+
```
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require "gcpc"
|
2
|
+
|
3
|
+
# Please execute commands below.
|
4
|
+
#
|
5
|
+
# ```
|
6
|
+
# $ gcloud beta emulators pubsub start
|
7
|
+
# $ bundle exec ruby examples/subscriber-example/subscriber-example.rb
|
8
|
+
# $ bundle exec ruby examples/publisher-example/publisher-example.rb
|
9
|
+
# ```
|
10
|
+
|
11
|
+
PROJECT_ID = "project-example-1"
|
12
|
+
TOPIC_NAME = "topic-example-1"
|
13
|
+
SUBSCRIPTION_NAME = "subscription-example-1"
|
14
|
+
|
15
|
+
MyLogger = Logger.new(STDOUT)
|
16
|
+
|
17
|
+
class LogInterceptor < Gcpc::Subscriber::BaseInterceptor
|
18
|
+
def handle(data, attributes, message)
|
19
|
+
MyLogger.info "[Interceptor Log] #{message.inspect}"
|
20
|
+
MyLogger.info "[Interceptor Log] data: #{data}"
|
21
|
+
MyLogger.info "[Interceptor Log] attributes: #{attributes}"
|
22
|
+
yield data, attributes, message
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class LogHandler < Gcpc::Subscriber::BaseHandler
|
27
|
+
def handle(data, attributes, message)
|
28
|
+
MyLogger.info "[Handler Log] #{message.inspect}"
|
29
|
+
MyLogger.info "[Handler Log] data: #{data}"
|
30
|
+
MyLogger.info "[Handler Log] attributes: #{attributes}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# We create topic and subscription only for demonstration.
|
35
|
+
def with_setup_subscription(&block)
|
36
|
+
project = Google::Cloud::Pubsub.new(
|
37
|
+
project_id: PROJECT_ID,
|
38
|
+
emulator_host: "localhost:8085",
|
39
|
+
)
|
40
|
+
if (topic = project.topic(TOPIC_NAME)).nil?
|
41
|
+
# Create a topic if necessary
|
42
|
+
topic = project.create_topic(TOPIC_NAME)
|
43
|
+
end
|
44
|
+
if (subscription = topic.subscription(SUBSCRIPTION_NAME)).nil?
|
45
|
+
# Create a subscription if necessary
|
46
|
+
subscription = topic.create_subscription(SUBSCRIPTION_NAME)
|
47
|
+
end
|
48
|
+
|
49
|
+
yield
|
50
|
+
|
51
|
+
ensure
|
52
|
+
topic.delete
|
53
|
+
subscription.delete
|
54
|
+
end
|
55
|
+
|
56
|
+
def run
|
57
|
+
subscriber = Gcpc::Subscriber.new(
|
58
|
+
project_id: PROJECT_ID,
|
59
|
+
subscription: SUBSCRIPTION_NAME,
|
60
|
+
interceptors: [LogInterceptor],
|
61
|
+
emulator_host: "localhost:8085",
|
62
|
+
)
|
63
|
+
subscriber.handle(LogHandler)
|
64
|
+
subscriber.run
|
65
|
+
end
|
66
|
+
|
67
|
+
def main
|
68
|
+
with_setup_subscription do
|
69
|
+
run
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
main
|
data/gcpc.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "gcpc/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "gcpc"
|
8
|
+
spec.version = Gcpc::VERSION
|
9
|
+
spec.authors = ["Nao Minami"]
|
10
|
+
spec.email = ["south37777@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Google Cloud Pub/Sub Client}
|
13
|
+
spec.description = %q{Google Cloud Pub/Sub Client}
|
14
|
+
spec.homepage = "https://github.com/south37/gcpc"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
# Specify which files should be added to the gem when it is released.
|
18
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
19
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
20
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
21
|
+
end
|
22
|
+
spec.bindir = "exe"
|
23
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
24
|
+
spec.require_paths = ["lib"]
|
25
|
+
|
26
|
+
spec.add_development_dependency "bundler", "~> 1.17"
|
27
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
28
|
+
spec.add_development_dependency "rspec", "~> 3.2"
|
29
|
+
spec.add_development_dependency "pry"
|
30
|
+
spec.add_runtime_dependency "google-cloud-pubsub"
|
31
|
+
end
|
data/lib/gcpc.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require "gcpc/publisher/base_interceptor"
|
2
|
+
require "gcpc/publisher/engine"
|
3
|
+
require "gcpc/publisher/topic_client"
|
4
|
+
|
5
|
+
module Gcpc
|
6
|
+
class Publisher
|
7
|
+
# @param [String] project_id
|
8
|
+
# @param [String] topic
|
9
|
+
# @param [String, Google::Cloud::Pubsub::Credentials, nil] credentials Path
|
10
|
+
# of keyfile or Google::Cloud::Pubsub::Credentials or nil.
|
11
|
+
# @param [String, nil] emulator_host Emulator's host or nil.
|
12
|
+
# @param [<#publish>] interceptors
|
13
|
+
def initialize(
|
14
|
+
project_id:,
|
15
|
+
topic:,
|
16
|
+
credentials: nil,
|
17
|
+
emulator_host: nil,
|
18
|
+
interceptors: []
|
19
|
+
)
|
20
|
+
topic_client = TopicClient.new(
|
21
|
+
project_id: project_id,
|
22
|
+
topic_name: topic,
|
23
|
+
credentials: credentials,
|
24
|
+
emulator_host: emulator_host,
|
25
|
+
)
|
26
|
+
|
27
|
+
t = topic_client.get
|
28
|
+
if t.nil?
|
29
|
+
raise "Getting topic \"#{topic}\" from project \"#{project_id}\" failed! The topic \"#{topic}\" does not exist!"
|
30
|
+
end
|
31
|
+
|
32
|
+
@engine = Engine.new(
|
33
|
+
topic: t,
|
34
|
+
interceptors: interceptors,
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
extend Forwardable
|
39
|
+
|
40
|
+
def_delegators :@engine, :publish
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Interceptor must implement #publish. Gcpc::Publisher::BaseHandler is a base
|
2
|
+
# class to implement such a class. You don't have to inherit this, this is only
|
3
|
+
# for indicating interface.
|
4
|
+
module Gcpc
|
5
|
+
class Publisher
|
6
|
+
class BaseInterceptor
|
7
|
+
# @param [String] data
|
8
|
+
# @param [Hash] attributes
|
9
|
+
def publish(data, attributes, &block)
|
10
|
+
yield data, attributes
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Gcpc
|
2
|
+
class Publisher
|
3
|
+
class Engine
|
4
|
+
# @param [Google::Cloud::Pubsub::Topic] topic
|
5
|
+
# @param [<#publish>] interceptors
|
6
|
+
def initialize(topic:, interceptors:)
|
7
|
+
@topic = topic
|
8
|
+
@interceptors = interceptors.map { |i| (i.class == Class) ? i.new : i }
|
9
|
+
end
|
10
|
+
|
11
|
+
# @param [String] data
|
12
|
+
# @param [Hash] attributes
|
13
|
+
def publish(data, attributes = {})
|
14
|
+
d = data.dup
|
15
|
+
a = attributes.dup
|
16
|
+
|
17
|
+
intercept!(@interceptors, d, a) do |dd, aa|
|
18
|
+
publish_message(dd, aa)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
# @param [<#publish>] interceptors
|
25
|
+
# @param [String] data
|
26
|
+
# @param [Hash] attributes
|
27
|
+
# @param [Proc] block
|
28
|
+
def intercept!(interceptors, data, attributes, &block)
|
29
|
+
if interceptors.size == 0
|
30
|
+
return yield(data, attributes)
|
31
|
+
end
|
32
|
+
|
33
|
+
i = interceptors.first
|
34
|
+
rest = interceptors[1..-1]
|
35
|
+
|
36
|
+
i.publish(data, attributes) do |d, a|
|
37
|
+
intercept!(rest, d, a, &block)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# @param [String] data
|
42
|
+
# @param [Hash] attributes
|
43
|
+
def publish_message(data, attributes)
|
44
|
+
@topic.publish(data, attributes)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Gcpc
|
2
|
+
class Publisher
|
3
|
+
class TopicClient
|
4
|
+
DEFAULT_CONNECT_TIMEOUT = 5
|
5
|
+
|
6
|
+
# @param [String] project_id
|
7
|
+
# @param [String] topic_name
|
8
|
+
# @param [Google::Cloud::Pubsub::Credentials, String, nil]
|
9
|
+
# @param [String, nil] emulator_host
|
10
|
+
def initialize(project_id:, topic_name:, credentials:, emulator_host:, connect_timeout: DEFAULT_CONNECT_TIMEOUT)
|
11
|
+
project = Google::Cloud::Pubsub.new(
|
12
|
+
project_id: project_id,
|
13
|
+
credentials: credentials,
|
14
|
+
emulator_host: emulator_host,
|
15
|
+
)
|
16
|
+
@project = project
|
17
|
+
@topic_name = topic_name
|
18
|
+
@connect_timeout = connect_timeout
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Google::Cloud::Pubsub::Topic]
|
22
|
+
def get
|
23
|
+
t = nil
|
24
|
+
Timeout.timeout(@connect_timeout) do
|
25
|
+
t = @project.topic(@topic_name)
|
26
|
+
end
|
27
|
+
t
|
28
|
+
rescue Timeout::Error => e
|
29
|
+
raise "Getting topic \"#{@topic_name}\" from project \"#{@project.project_id}\" timed out!"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "gcpc/subscriber/base_handler"
|
2
|
+
require "gcpc/subscriber/base_interceptor"
|
3
|
+
require "gcpc/subscriber/default_logger"
|
4
|
+
require "gcpc/subscriber/engine"
|
5
|
+
require "gcpc/subscriber/subscription_client"
|
6
|
+
|
7
|
+
module Gcpc
|
8
|
+
class Subscriber
|
9
|
+
# @param [String] project_id
|
10
|
+
# @param [String] subscription
|
11
|
+
# @param [String, Google::Cloud::Pubsub::Credentials, nil] credentials Path
|
12
|
+
# of keyfile or Google::Cloud::Pubsub::Credentials or nil.
|
13
|
+
# @param [String, nil] emulator_host Emulator's host or nil.
|
14
|
+
# @param [<#handle, #on_error>] interceptors
|
15
|
+
# @param [bool] ack_immediately
|
16
|
+
# @param [Logger] logger
|
17
|
+
def initialize(
|
18
|
+
project_id:,
|
19
|
+
subscription:,
|
20
|
+
credentials: nil,
|
21
|
+
emulator_host: nil,
|
22
|
+
interceptors: [],
|
23
|
+
ack_immediately: false,
|
24
|
+
logger: DefaultLogger
|
25
|
+
)
|
26
|
+
subscription_client = SubscriptionClient.new(
|
27
|
+
project_id: project_id,
|
28
|
+
subscription_name: subscription,
|
29
|
+
credentials: credentials,
|
30
|
+
emulator_host: emulator_host,
|
31
|
+
)
|
32
|
+
|
33
|
+
s = subscription_client.get
|
34
|
+
if s.nil?
|
35
|
+
raise "Getting subscription \"#{subscription}\" from project \"#{project_id}\" failed! The subscription \"#{subscription}\" does not exist!"
|
36
|
+
end
|
37
|
+
|
38
|
+
@engine = Engine.new(
|
39
|
+
subscription: s,
|
40
|
+
interceptors: interceptors,
|
41
|
+
ack_immediately: ack_immediately,
|
42
|
+
logger: logger,
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
extend Forwardable
|
47
|
+
|
48
|
+
def_delegators :@engine, :handle, :run, :stop
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Handler must implement #handle and can implement #on_error.
|
2
|
+
# Gcpc::Subscriber::BaseHandler is a base class to implement such a class.
|
3
|
+
# You don't have to inherit this, this is only for indicating interface.
|
4
|
+
module Gcpc
|
5
|
+
class Subscriber
|
6
|
+
class BaseHandler
|
7
|
+
# @param [String] data
|
8
|
+
# @param [Hash] attributes
|
9
|
+
# @param [Google::Cloud::Pubsub::ReceivedMessage] message
|
10
|
+
def handle(data, attributes, message)
|
11
|
+
raise NotImplementedError.new("You must implement #{self.class}##{__method__}")
|
12
|
+
end
|
13
|
+
|
14
|
+
# You don't need to implement #on_error if it is not necessary.
|
15
|
+
# @param [Exception] error
|
16
|
+
# def on_error(error)
|
17
|
+
# raise NotImplementedError.new("You must implement #{self.class}##{__method__}")
|
18
|
+
# end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Interceptor must implement #handle and can implement #on_error.
|
2
|
+
# Gcpc::Subscriber::BaseHandler is a base class to implement such a class.
|
3
|
+
# You don't have to inherit this, this is only for indicating interface.
|
4
|
+
module Gcpc
|
5
|
+
class Subscriber
|
6
|
+
class BaseInterceptor
|
7
|
+
# @param [String] data
|
8
|
+
# @param [Hash] attributes
|
9
|
+
# @param [Google::Cloud::Pubsub::ReceivedMessage] message
|
10
|
+
# @param [Proc] block
|
11
|
+
def handle(data, attributes, message, &block)
|
12
|
+
yield data, attributes, message
|
13
|
+
end
|
14
|
+
|
15
|
+
# You don't need to implement #on_error is it is not necessary.
|
16
|
+
# @param [Exception] error
|
17
|
+
# @param [Plock] block
|
18
|
+
# def on_error(error, &block)
|
19
|
+
# yield error
|
20
|
+
# end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require "gcpc/subscriber/handle_engine"
|
2
|
+
|
3
|
+
module Gcpc
|
4
|
+
class Subscriber
|
5
|
+
class Engine
|
6
|
+
WAIT_INTERVAL = 1
|
7
|
+
|
8
|
+
# @param [Google::Cloud::Pubsub::Subscription] subscription
|
9
|
+
# @param [<#handle, #on_error>] interceptors
|
10
|
+
# @param [bool] ack_immediately
|
11
|
+
# @param [Logger] logger
|
12
|
+
def initialize(
|
13
|
+
subscription:,
|
14
|
+
interceptors: [],
|
15
|
+
ack_immediately: false,
|
16
|
+
logger: DefaultLogger
|
17
|
+
)
|
18
|
+
|
19
|
+
@subscription = subscription
|
20
|
+
@interceptors = interceptors
|
21
|
+
@ack_immediately = ack_immediately
|
22
|
+
@logger = logger
|
23
|
+
|
24
|
+
@subscriber = nil # @subscriber is created by calling `#run`
|
25
|
+
@handler = nil # @handler must be registered by `#handle`
|
26
|
+
|
27
|
+
@stopped_mutex = Mutex.new
|
28
|
+
@stopped = false
|
29
|
+
end
|
30
|
+
|
31
|
+
# @param [<String>] signals Signals which are used to shutdown subscriber
|
32
|
+
# gracefully.
|
33
|
+
def run(signals = ['SIGTERM', 'SIGINT'])
|
34
|
+
if @handler.nil?
|
35
|
+
raise "You must register handler by #handle before calling #run"
|
36
|
+
end
|
37
|
+
|
38
|
+
@logger.info("Starting to subscribe a subscription \"#{@subscription.name}\", will wait for background threads to start...")
|
39
|
+
|
40
|
+
@subscriber = @subscription.listen do |message|
|
41
|
+
handle_message(message)
|
42
|
+
end
|
43
|
+
@subscriber.on_error do |err|
|
44
|
+
handle_error(err)
|
45
|
+
end
|
46
|
+
@subscriber.start
|
47
|
+
|
48
|
+
@logger.info("Started")
|
49
|
+
|
50
|
+
loop_until_receiving_signals(signals)
|
51
|
+
end
|
52
|
+
|
53
|
+
def stop
|
54
|
+
if @subscriber.nil?
|
55
|
+
raise "You must call #run before stopping"
|
56
|
+
end
|
57
|
+
|
58
|
+
@stopped_mutex.synchronize do
|
59
|
+
# `#stop` may be called multiple times. Only first call can proceed.
|
60
|
+
return if @stopped
|
61
|
+
@stopped = true
|
62
|
+
end
|
63
|
+
|
64
|
+
@logger.info('Stopping, will wait for background threads to exit')
|
65
|
+
|
66
|
+
@subscriber.stop
|
67
|
+
@subscriber.wait!
|
68
|
+
|
69
|
+
@logger.info('Stopped, background threads are shutdown')
|
70
|
+
end
|
71
|
+
|
72
|
+
# We support registrion of only one handler
|
73
|
+
# @param [#handle, #on_error, Class] handler
|
74
|
+
def handle(handler)
|
75
|
+
@handler = HandleEngine.new(
|
76
|
+
handler: handler,
|
77
|
+
interceptors: @interceptors,
|
78
|
+
)
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def loop_until_receiving_signals(signals)
|
84
|
+
signal_received = false
|
85
|
+
signals.each do |signal|
|
86
|
+
Signal.trap(signal) { signal_received = true }
|
87
|
+
end
|
88
|
+
while !(signal_received || stopped?)
|
89
|
+
sleep WAIT_INTERVAL
|
90
|
+
end
|
91
|
+
|
92
|
+
stop unless stopped?
|
93
|
+
end
|
94
|
+
|
95
|
+
# @param [Google::Cloud::Pubsub::ReceivedMessage] message
|
96
|
+
def handle_message(message)
|
97
|
+
ack(message) if @ack_immediately
|
98
|
+
|
99
|
+
begin
|
100
|
+
worker_info("Started hanlding message")
|
101
|
+
@handler.handle(message)
|
102
|
+
worker_info("Finished hanlding message successfully")
|
103
|
+
rescue => e
|
104
|
+
nack(message) if !@ack_immediately
|
105
|
+
raise e # exception is handled in `#handle_error`
|
106
|
+
end
|
107
|
+
|
108
|
+
ack(message) if !@ack_immediately
|
109
|
+
end
|
110
|
+
|
111
|
+
def ack(message)
|
112
|
+
message.ack!
|
113
|
+
worker_info("Acked message")
|
114
|
+
end
|
115
|
+
|
116
|
+
def nack(message)
|
117
|
+
message.nack!
|
118
|
+
worker_info("Nacked message")
|
119
|
+
end
|
120
|
+
|
121
|
+
# @param [Exception] error
|
122
|
+
def handle_error(error)
|
123
|
+
worker_error(error)
|
124
|
+
@handler.on_error(error)
|
125
|
+
end
|
126
|
+
|
127
|
+
# @param [String] message
|
128
|
+
def worker_info(message)
|
129
|
+
@logger.info("[Worker #{Thread.current.object_id}] #{message}")
|
130
|
+
end
|
131
|
+
|
132
|
+
# @param [Exception] error
|
133
|
+
def worker_error(error)
|
134
|
+
e_str = "#{error.message}"
|
135
|
+
e_str += "\n#{error.backtrace.join("\n")}" if error.backtrace
|
136
|
+
@logger.error("[Worker #{Thread.current.object_id}] #{e_str}")
|
137
|
+
end
|
138
|
+
|
139
|
+
def stopped?
|
140
|
+
@stopped_mutex.synchronize { @stopped }
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Gcpc
|
2
|
+
class Subscriber
|
3
|
+
# HandleEngine handle messages and exceptions with interceptors.
|
4
|
+
class HandleEngine
|
5
|
+
# @param [#handle, #on_error, Class] handler
|
6
|
+
# @param [<#handle, #on_error, Class>] interceptors
|
7
|
+
def initialize(handler:, interceptors:)
|
8
|
+
@handler = (handler.class == Class) ? handler.new : handler
|
9
|
+
@interceptors = interceptors.map { |i| (i.class == Class) ? i.new : i }
|
10
|
+
end
|
11
|
+
|
12
|
+
# @param [Google::Cloud::Pubsub::ReceivedMessage] message
|
13
|
+
def handle(message)
|
14
|
+
d = message.data.dup
|
15
|
+
a = message.attributes.dup
|
16
|
+
|
17
|
+
intercept_message!(@interceptors, d, a, message) do |dd, aa, m|
|
18
|
+
handle_message(dd, aa, m)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param [Exception] error
|
23
|
+
def on_error(error)
|
24
|
+
intercept_error!(@interceptors, error) do |e|
|
25
|
+
handle_on_error(e)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# @param [<#handle>] interceptors
|
32
|
+
# @param [String] data
|
33
|
+
# @param [Hash] attributes
|
34
|
+
# @param [Google::Cloud::Pubsub::ReceivedMessage] message
|
35
|
+
# @param [Proc] block
|
36
|
+
def intercept_message!(interceptors, data, attributes, message, &block)
|
37
|
+
if interceptors.size == 0
|
38
|
+
return yield(data, attributes, message)
|
39
|
+
end
|
40
|
+
|
41
|
+
i = interceptors.first
|
42
|
+
rest = interceptors[1..-1]
|
43
|
+
|
44
|
+
i.handle(data, attributes, message) do |d, a, m|
|
45
|
+
intercept_message!(rest, d, a, m, &block)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# @param [<#on_error>] interceptors
|
50
|
+
# @param [Exception] error
|
51
|
+
# @param [Proc] block
|
52
|
+
def intercept_error!(interceptors, error, &block)
|
53
|
+
return yield(error) if interceptors.size == 0
|
54
|
+
|
55
|
+
i = interceptors.first
|
56
|
+
rest = interceptors[1..-1]
|
57
|
+
|
58
|
+
if !i.respond_to?(:on_error)
|
59
|
+
# If #on_error is not implemented in the interceptor, it is simply
|
60
|
+
# skipped.
|
61
|
+
return intercept_error!(rest, error, &block)
|
62
|
+
end
|
63
|
+
|
64
|
+
i.on_error(error) do |e|
|
65
|
+
intercept_error!(rest, e, &block)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# @param [String] data
|
70
|
+
# @param [Hash] attributes
|
71
|
+
# @param [Google::Cloud::Pubsub::ReceivedMessage] message
|
72
|
+
def handle_message(data, attributes, message)
|
73
|
+
@handler.handle(data, attributes, message)
|
74
|
+
end
|
75
|
+
|
76
|
+
# @param [Exception] error
|
77
|
+
def handle_on_error(error)
|
78
|
+
return if !@handler.respond_to?(:on_error)
|
79
|
+
@handler.on_error(error)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "google/cloud/pubsub"
|
2
|
+
|
3
|
+
module Gcpc
|
4
|
+
class Subscriber
|
5
|
+
class SubscriptionClient
|
6
|
+
DEFAULT_CONNECT_TIMEOUT = 5
|
7
|
+
|
8
|
+
# @param [String] project_id
|
9
|
+
# @param [String] subscription_name
|
10
|
+
# @param [Google::Cloud::Pubsub::Credentials, String, nil]
|
11
|
+
# @param [String, nil] emulator_host
|
12
|
+
def initialize(project_id:, subscription_name:, credentials:, emulator_host:, connect_timeout: DEFAULT_CONNECT_TIMEOUT)
|
13
|
+
project = Google::Cloud::Pubsub.new(
|
14
|
+
project_id: project_id,
|
15
|
+
credentials: credentials,
|
16
|
+
emulator_host: emulator_host,
|
17
|
+
)
|
18
|
+
@project = project
|
19
|
+
@subscription_name = subscription_name
|
20
|
+
@connect_timeout = connect_timeout
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [Google::Cloud::Pubsub::Subscription]
|
24
|
+
def get
|
25
|
+
t = nil
|
26
|
+
Timeout.timeout(@connect_timeout) do
|
27
|
+
t = @project.subscription(@subscription_name)
|
28
|
+
end
|
29
|
+
t
|
30
|
+
rescue Timeout::Error => e
|
31
|
+
raise "Getting subscription \"#{@subscription_name}\" from project \"#{@project.project_id}\" timed out!"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/gcpc/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gcpc
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nao Minami
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-06-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.17'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.17'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.2'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: google-cloud-pubsub
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: Google Cloud Pub/Sub Client
|
84
|
+
email:
|
85
|
+
- south37777@gmail.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- ".rspec"
|
92
|
+
- ".travis.yml"
|
93
|
+
- Gemfile
|
94
|
+
- Gemfile.lock
|
95
|
+
- LICENSE.txt
|
96
|
+
- README.md
|
97
|
+
- Rakefile
|
98
|
+
- bin/console
|
99
|
+
- bin/setup
|
100
|
+
- examples/publisher-example/README.md
|
101
|
+
- examples/publisher-example/publisher-example.rb
|
102
|
+
- examples/subscriber-example/README.md
|
103
|
+
- examples/subscriber-example/subscriber-example.rb
|
104
|
+
- gcpc.gemspec
|
105
|
+
- lib/gcpc.rb
|
106
|
+
- lib/gcpc/publisher.rb
|
107
|
+
- lib/gcpc/publisher/base_interceptor.rb
|
108
|
+
- lib/gcpc/publisher/engine.rb
|
109
|
+
- lib/gcpc/publisher/topic_client.rb
|
110
|
+
- lib/gcpc/subscriber.rb
|
111
|
+
- lib/gcpc/subscriber/base_handler.rb
|
112
|
+
- lib/gcpc/subscriber/base_interceptor.rb
|
113
|
+
- lib/gcpc/subscriber/default_logger.rb
|
114
|
+
- lib/gcpc/subscriber/engine.rb
|
115
|
+
- lib/gcpc/subscriber/handle_engine.rb
|
116
|
+
- lib/gcpc/subscriber/subscription_client.rb
|
117
|
+
- lib/gcpc/version.rb
|
118
|
+
homepage: https://github.com/south37/gcpc
|
119
|
+
licenses:
|
120
|
+
- MIT
|
121
|
+
metadata: {}
|
122
|
+
post_install_message:
|
123
|
+
rdoc_options: []
|
124
|
+
require_paths:
|
125
|
+
- lib
|
126
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '0'
|
131
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- - ">="
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: '0'
|
136
|
+
requirements: []
|
137
|
+
rubygems_version: 3.0.3
|
138
|
+
signing_key:
|
139
|
+
specification_version: 4
|
140
|
+
summary: Google Cloud Pub/Sub Client
|
141
|
+
test_files: []
|