pubsubc 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 688500fbb35695a35b4109e914ea2ba45277d64743d2372f865f65d5dd46ad6d
4
+ data.tar.gz: 8839a7ad9d76cfc88578ed8357c716fca88afe065e8bcfaa4e28806ccddd548f
5
+ SHA512:
6
+ metadata.gz: 4a8375467b9013c139fd84a371cb98a5b27782d9a802048dfada45d9cc8fab9384e826e4b1ef1b9779c4278772747d6540d838da21021f3610799ea723a0d3c6
7
+ data.tar.gz: b79699630a59e7e70639acc40b997442b7e273d9efabf873878b44c0110b4be010e2152e9d5b4682e3afe38099e53b0e9599e846a22dfb37e146ac309f990ab0
data/README.md ADDED
@@ -0,0 +1,236 @@
1
+ # pubsubc
2
+
3
+ [![CI status](https://github.com/ZimbiX/pubsubc/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/ZimbiX/pubsubc/actions/workflows/main.yml) [![Gem Version](https://badge.fury.io/rb/pubsubc.svg)](https://rubygems.org/gems/pubsubc)
4
+
5
+ A simple command-line client for [Google Cloud Pub/Sub](https://cloud.google.com/pubsub).
6
+
7
+ Unlike the `gcloud pubsub` utility, `pubsubc`:
8
+
9
+ - Supports the [Pub/Sub emulator](https://cloud.google.com/pubsub/docs/emulator)
10
+ - Provides a continuous subscribe command - to see all messages as they come in
11
+
12
+ Since this was originally created as a learning exercise for integrating to Pub/Sub, the source code should be simple enough for you to copy and adapt into your own application.
13
+
14
+ ## Contents
15
+
16
+ <!-- MarkdownTOC autolink=true -->
17
+
18
+ - [Intro](#intro)
19
+ - [Installation](#installation)
20
+ - [Direct](#direct)
21
+ - [Bundler](#bundler)
22
+ - [Usage](#usage)
23
+ - [Subscribe](#subscribe)
24
+ - [Publish message](#publish-message)
25
+ - [Publish generated messages](#publish-generated-messages)
26
+ - [Example](#example)
27
+ - [Communicating some messages](#communicating-some-messages)
28
+ - [Publishing from a message generator with several subscribers](#publishing-from-a-message-generator-with-several-subscribers)
29
+ - [Help info](#help-info)
30
+ - [Contributing](#contributing)
31
+ - [Development](#development)
32
+ - [Pub/Sub emulator](#pubsub-emulator)
33
+ - [Pre-push hook](#pre-push-hook)
34
+ - [Release](#release)
35
+
36
+ <!-- /MarkdownTOC -->
37
+
38
+ ## Intro
39
+
40
+ Features:
41
+
42
+ - Subscribe to a topic, continuously logging all messages as they arrive
43
+ - Publish a string message to a topic (creating a subscription automatically)
44
+ - Publish automatically-generated messages continuously at a given interval
45
+ - Supports connecting to either a local emulator or the remote real Pub/Sub
46
+
47
+ ## Installation
48
+
49
+ The executable is distributed through RubyGems.
50
+
51
+ ### Direct
52
+
53
+ You can install it to your system directly using:
54
+
55
+ ```bash
56
+ gem install pubsubc
57
+ ```
58
+
59
+ And then if you're using rbenv:
60
+
61
+ ```bash
62
+ rbenv rehash
63
+ ```
64
+
65
+ You can then run it with:
66
+
67
+ ```bash
68
+ pubsubc
69
+ ```
70
+
71
+ ### Bundler
72
+
73
+ Or, just add it to the `Gemfile` of your project:
74
+
75
+ ```ruby
76
+ gem 'pubsubc'
77
+ ```
78
+
79
+ And then run it with:
80
+
81
+ ```bash
82
+ bundle exec pubsubc
83
+ ```
84
+
85
+ ## Usage
86
+
87
+ ### Subscribe
88
+
89
+ To subscribe and continuously log all messages from the topic:
90
+
91
+ ```bash
92
+ pubsubc sub
93
+ ```
94
+
95
+ ### Publish message
96
+
97
+ To publish a single message to the topic:
98
+
99
+ ```bash
100
+ pubsubc pub msg "G'day"
101
+ ```
102
+
103
+ ### Publish generated messages
104
+
105
+ To publish a generated message to the topic every second:
106
+
107
+ ```bash
108
+ pubsubc pub gen --interval 1000
109
+ ```
110
+
111
+ ## Example
112
+
113
+ ### Communicating some messages
114
+
115
+ ```
116
+ ➜ pubsubc pub msg "Sup wigga"
117
+ Initialising Pub/Sub client for emulator (localhost:8085)... done
118
+ Checking existence of topic 'my-topic'... creating... done
119
+ Checking existence of subscription 'my-subscription'... creating... done
120
+ Published message: Sup wigga
121
+
122
+ ➜ pubsubc pub msg "Yo J-dog"
123
+ Initialising Pub/Sub client for emulator (localhost:8085)... done
124
+ Checking existence of topic 'my-topic'... exists
125
+ Checking existence of subscription 'my-subscription'... exists
126
+ Published message: Yo J-dog
127
+
128
+ ➜ pubsubc sub
129
+ Initialising Pub/Sub client for emulator (localhost:8085)... done
130
+ Checking existence of topic 'my-topic'... exists
131
+ Checking existence of subscription 'my-subscription'... exists
132
+ Listening for messages
133
+ Data: Sup wigga, published at 2021-07-30 23:19:06 +1000
134
+ Data: Yo J-dog, published at 2021-07-30 23:19:41 +1000
135
+ ^C
136
+ ```
137
+
138
+ ### Publishing from a message generator with several subscribers
139
+
140
+ ![](doc/example-with-generator-and-several-subscribers.png)
141
+
142
+ The generator was run with:
143
+
144
+ ```bash
145
+ pubsubc pub gen --interval 1
146
+ ```
147
+
148
+ And each subscriber:
149
+
150
+ ```bash
151
+ pubsubc sub
152
+ ```
153
+
154
+ ## Help info
155
+
156
+ Output of `pubsubc --help`:
157
+
158
+ <!-- Help -->
159
+
160
+ ```
161
+ Usage:
162
+ pubsubc [OPTIONS] SUBCOMMAND [ARG] ...
163
+
164
+ A simple command-line client for Google Cloud Pub/Sub.
165
+
166
+ Created as a learning exercise, but also useful since the 'gcloud pubsub' commands don't support the emulator, and it doesn't provide a continuous subscribe command.
167
+
168
+ To clean up:
169
+
170
+ gcloud pubsub topics delete my-topic
171
+ gcloud pubsub subscriptions delete my-subscription
172
+
173
+ Parameters:
174
+ SUBCOMMAND subcommand
175
+ [ARG] ... subcommand arguments
176
+
177
+ Subcommands:
178
+ pub Publishing messages to the topic
179
+ sub Subscribe to messages on the topic
180
+ shell Get a Ruby shell to interact with Pub/Sub
181
+
182
+ Options:
183
+ --topic TOPIC_NAME The name of the Pub/Sub topic (default: "my-topic")
184
+ --subscription SUBSCRIPTION_NAME The name of the Pub/Sub subscription within the topic (default: "my-subscription")
185
+ --remote Connect to the real Pub/Sub, rather than a local Pub/Sub emulator
186
+ --emulator-host EMULATOR_HOST The host and port of the Pub/Sub emulator (default: $PUBSUB_EMULATOR_HOST, or "localhost:8085")
187
+ -h, --help print help
188
+ ```
189
+
190
+ <!-- /Help -->
191
+
192
+ Suffix `--help` to any subcommand to see the usage info for it.
193
+
194
+ ## Contributing
195
+
196
+ Pull requests welcome! =)
197
+
198
+ However, I don't intend to duplicate functionality that exists in the `gcloud pubsub` utility, unless it's an improvement over what's in that.
199
+
200
+ ## Development
201
+
202
+ ### Pub/Sub emulator
203
+
204
+ To run the Pub/Sub emulator (with Docker):
205
+
206
+ ```bash
207
+ docker-compose up -d pubsub-emulator
208
+ ```
209
+
210
+ ### Pre-push hook
211
+
212
+ This hook runs style checks and tests.
213
+
214
+ To set up the pre-push hook:
215
+
216
+ ```bash
217
+ echo -e "#\!/bin/bash\n\$(dirname \$0)/../../auto/pre-push-hook" > .git/hooks/pre-push
218
+ chmod +x .git/hooks/pre-push
219
+ ```
220
+
221
+ ### Release
222
+
223
+ To release a new version:
224
+
225
+ ```bash
226
+ auto/release/update-version && auto/release/tag && auto/release/publish
227
+ ```
228
+
229
+ This takes care of the whole process:
230
+
231
+ - Incrementing the version number (the patch number by default)
232
+ - Tagging & pushing commits
233
+ - Publishing the gem to RubyGems
234
+ - Creating a draft GitHub release
235
+
236
+ To increment the minor or major versions instead of the patch number, run `auto/release/update-version` with `--minor` or `--major`.
data/exe/pubsubc ADDED
@@ -0,0 +1,176 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
5
+ ENV['GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS'] = 'true'
6
+
7
+ require 'google/cloud/pubsub'
8
+ require 'clamp'
9
+ require 'pry'
10
+
11
+ Clamp.allow_options_after_parameters = true
12
+
13
+ Clamp do # rubocop:disable Metrics/BlockLength
14
+ self.description = <<~TEXT
15
+ A simple command-line client for Google Cloud Pub/Sub.
16
+
17
+ Created as a learning exercise, but also useful since the 'gcloud pubsub' commands don't support the emulator, and it doesn't provide a continuous subscribe command.
18
+
19
+ To clean up:
20
+
21
+ gcloud pubsub topics delete my-topic
22
+ gcloud pubsub subscriptions delete my-subscription
23
+ TEXT
24
+
25
+ option '--topic',
26
+ 'TOPIC_NAME',
27
+ 'The name of the Pub/Sub topic',
28
+ attribute_name: :topic_name,
29
+ default: 'my-topic'
30
+
31
+ option '--subscription',
32
+ 'SUBSCRIPTION_NAME',
33
+ 'The name of the Pub/Sub subscription within the topic',
34
+ attribute_name: :subscription_name,
35
+ default: 'my-subscription'
36
+
37
+ option '--remote', :flag, 'Connect to the real Pub/Sub, rather than a local Pub/Sub emulator'
38
+
39
+ option '--emulator-host',
40
+ 'EMULATOR_HOST',
41
+ 'The host and port of the Pub/Sub emulator',
42
+ environment_variable: 'PUBSUB_EMULATOR_HOST',
43
+ default: 'localhost:8085' do |host|
44
+ ENV.delete('PUBSUB_EMULATOR_HOST')
45
+ ENV.delete('PUBSUB_PROJECT_ID')
46
+ host
47
+ end
48
+
49
+ subcommand 'pub', 'Publishing messages to the topic' do # rubocop:disable Metrics/BlockLength
50
+ subcommand 'msg', 'Publish one message' do
51
+ parameter 'MESSAGE', 'The message string to publish to the topic'
52
+
53
+ def execute
54
+ publish(message)
55
+ end
56
+ end
57
+
58
+ subcommand 'gen', 'Publish generated messages' do
59
+ option %w[-i --interval],
60
+ 'INTERVAL_MS',
61
+ 'How long we should sleep before generating each message',
62
+ attribute_name: :interval_ms,
63
+ required: true,
64
+ &method(:Integer)
65
+
66
+ def execute
67
+ (1..).each do |i|
68
+ message = "This is message #{i}"
69
+ publish(message)
70
+ sleep(interval_ms / 1000.0)
71
+ end
72
+ end
73
+ end
74
+
75
+ def publish(message)
76
+ # Ensure the subscription exists first so the message won't just get dropped
77
+ subscription
78
+
79
+ topic.publish(message)
80
+
81
+ puts "Published message: #{message}"
82
+ end
83
+ end
84
+
85
+ subcommand 'sub', 'Subscribe to messages on the topic' do
86
+ def execute
87
+ subscribe do |received_message|
88
+ puts "Data: #{received_message.message.data}, published at #{received_message.message.published_at}"
89
+ end
90
+ end
91
+
92
+ def subscribe
93
+ subscriber = subscription.listen(threads: { callback: 16 }) do |received_message|
94
+ yield received_message
95
+ received_message.acknowledge!
96
+ end
97
+
98
+ subscriber.on_error do |exception|
99
+ puts "Exception: #{exception.class} #{exception.message}"
100
+ end
101
+
102
+ # Gracefully shut down the subscriber on program exit, blocking until all received messages have been processed or 10 seconds have passed
103
+ at_exit do
104
+ subscriber.stop!(10)
105
+ end
106
+
107
+ puts 'Listening for messages'
108
+
109
+ # Start the background threads that will call the block passed to listen
110
+ subscriber.start
111
+
112
+ # Keep the program open while the threads handle receiving messages
113
+ sleep
114
+ end
115
+ end
116
+
117
+ subcommand 'shell', 'Get a Ruby shell to interact with Pub/Sub' do
118
+ def execute
119
+ binding.pry # rubocop:disable Lint/Debugger
120
+ end
121
+ end
122
+
123
+ def subscription
124
+ @subscription ||= get_or_create_topic_subscription(subscription_name)
125
+ end
126
+
127
+ def get_or_create_topic_subscription(subscription_name)
128
+ topic.tap do
129
+ print "Checking existence of subscription '%s'... " % subscription_name
130
+ end.get_subscription(subscription_name)&.tap do # rubocop:disable Style/MultilineBlockChain
131
+ puts 'exists'
132
+ end || begin
133
+ print 'creating... '
134
+ topic.create_subscription(subscription_name).tap { puts 'done' }
135
+ end
136
+ end
137
+
138
+ def topic
139
+ @topic ||= get_or_create_topic(topic_name)
140
+ end
141
+
142
+ def get_or_create_topic(topic_name)
143
+ pubsub.tap do
144
+ print "Checking existence of topic '%s'... " % topic_name
145
+ end.get_topic(topic_name)&.tap do # rubocop:disable Style/MultilineBlockChain
146
+ puts 'exists'
147
+ end || begin
148
+ print 'creating... '
149
+ pubsub.create_topic(topic_name).tap { puts 'done' }
150
+ end
151
+ end
152
+
153
+ def pubsub
154
+ @pubsub ||= begin
155
+ print 'Initialising Pub/Sub client for %s... ' % (remote? ? 'remote' : "emulator (#{emulator_host})")
156
+ Google::Cloud::PubSub.new(**pubsub_args).tap { puts 'done' }
157
+ end
158
+ end
159
+
160
+ def pubsub_args
161
+ remote? ? pubsub_remote_args : pubsub_emulator_args
162
+ end
163
+
164
+ def pubsub_remote_args
165
+ {
166
+ project_id: 'greensync-dex-dev',
167
+ }
168
+ end
169
+
170
+ def pubsub_emulator_args
171
+ {
172
+ project_id: 'greensync-dex-dev-nonexistent',
173
+ emulator_host: emulator_host,
174
+ }
175
+ end
176
+ end
data/lib/pubsubc.rb ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'pubsubc/version'
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Pubsubc
4
+ VERSION = '0.1.0'
5
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pubsubc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Brendan Weibrecht
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-07-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: clamp
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.3.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.3.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: google-cloud-pubsub
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.7.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 2.7.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: jazz_fingers
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 6.2.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 6.2.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: rainbow
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 3.0.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 3.0.0
69
+ description:
70
+ email:
71
+ - brendan@weibrecht.net.au
72
+ executables:
73
+ - pubsubc
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - README.md
78
+ - exe/pubsubc
79
+ - lib/pubsubc.rb
80
+ - lib/pubsubc/version.rb
81
+ homepage: https://github.com/ZimbiX/pubsubc
82
+ licenses:
83
+ - GPL-3.0
84
+ metadata:
85
+ homepage_uri: https://github.com/ZimbiX/pubsubc
86
+ source_code_uri: https://github.com/ZimbiX/pubsubc
87
+ changelog_uri: https://github.com/ZimbiX/pubsubc/releases
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 2.6.0
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubygems_version: 3.2.16
104
+ signing_key:
105
+ specification_version: 4
106
+ summary: A simple command-line client for Google Cloud Pub/Sub
107
+ test_files: []