bps-stan 0.1.2
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/bps-stan.gemspec +22 -0
- data/lib/bps-stan.rb +1 -0
- data/lib/bps/publisher/stan.rb +75 -0
- data/lib/bps/stan.rb +12 -0
- data/spec/bps/stan_spec.rb +60 -0
- metadata +76 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5d0143920a7d80cb269a5fd2d8f15ac90becad86b7177a808b6239a0bb77b0a9
|
4
|
+
data.tar.gz: 23eda94ef4b9e1baaa89a806f435c32f4a087bf7b243bd004484a9e97734377f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7c9d5fab51969ffe5d0c7b5799af272301d603810a7a37ec6593dbe71dc997ac9f3643dc3b2637f329857a616434f59f55733c215552b14f4b099fbe44fd6b67
|
7
|
+
data.tar.gz: 17448d25241e07c5608f3d4a80a9d8f5b5620059a84f02f4770a82d86124c8111dc4bfd0c2b634349ef2531b48e9f0570e50ca174bb7af57481be1867d1c8866
|
data/bps-stan.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'bps-stan'
|
3
|
+
s.version = File.read(File.expand_path('../../.version', __dir__)).strip
|
4
|
+
s.platform = Gem::Platform::RUBY
|
5
|
+
|
6
|
+
s.licenses = ['Apache-2.0']
|
7
|
+
s.summary = 'BPS adapter for nats-streaming'
|
8
|
+
s.description = 'https://github.com/bsm/bps'
|
9
|
+
|
10
|
+
s.authors = ['Black Square Media']
|
11
|
+
s.email = 'info@blacksquaremedia.com'
|
12
|
+
s.homepage = 'https://github.com/bsm/bps'
|
13
|
+
|
14
|
+
s.executables = []
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
17
|
+
s.require_paths = ['lib']
|
18
|
+
s.required_ruby_version = '>= 2.6.0'
|
19
|
+
|
20
|
+
s.add_dependency 'bps', s.version
|
21
|
+
s.add_dependency 'nats-streaming', '= 0.2.2'
|
22
|
+
end
|
data/lib/bps-stan.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bps/stan'
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'stan/client'
|
3
|
+
|
4
|
+
module BPS
|
5
|
+
module Publisher
|
6
|
+
class STAN < Abstract
|
7
|
+
class Topic < Abstract::Topic
|
8
|
+
def initialize(client, topic)
|
9
|
+
super()
|
10
|
+
|
11
|
+
@client = client
|
12
|
+
@topic = topic
|
13
|
+
end
|
14
|
+
|
15
|
+
def publish(message, **_opts)
|
16
|
+
@client.publish(@topic, message)
|
17
|
+
end
|
18
|
+
|
19
|
+
def flush(**)
|
20
|
+
# noop
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
CLIENT_OPTS = {
|
25
|
+
nats: {
|
26
|
+
servers: [:string],
|
27
|
+
dont_randomize_servers: :bool,
|
28
|
+
reconnect_time_wait: :float,
|
29
|
+
max_reconnect_attempts: :int,
|
30
|
+
connect_timeout: :float,
|
31
|
+
# TODO: review, list all of them: https://github.com/nats-io/nats.rb (there's tls config etc)
|
32
|
+
},
|
33
|
+
}.freeze
|
34
|
+
|
35
|
+
def self.parse_url(url)
|
36
|
+
port = url.port&.to_s || '4222'
|
37
|
+
servers = CGI.unescape(url.host).split(',').map do |host|
|
38
|
+
addr = "nats://#{host}"
|
39
|
+
addr << ':' << port unless addr.match(/:\d+$/)
|
40
|
+
addr
|
41
|
+
end
|
42
|
+
opts = CGI.parse(url.query).transform_values {|v| v.size == 1 ? v[0] : v }
|
43
|
+
cluster_id = opts.delete('cluster_id')
|
44
|
+
client_id = opts.delete('client_id')
|
45
|
+
[cluster_id, client_id, { nats: { servers: servers } }]
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [BPS::Coercer] the options coercer.
|
49
|
+
def self.coercer
|
50
|
+
@coercer ||= BPS::Coercer.new(CLIENT_OPTS).freeze
|
51
|
+
end
|
52
|
+
|
53
|
+
# @param [String] cluster ID.
|
54
|
+
# @param [String] client ID.
|
55
|
+
# @param [Hash] options.
|
56
|
+
def initialize(cluster_id, client_id, nats: {}, **opts)
|
57
|
+
super()
|
58
|
+
|
59
|
+
@topics = {}
|
60
|
+
@client = ::STAN::Client.new
|
61
|
+
@client.connect(cluster_id, client_id, nats: nats, **opts.slice(*CLIENT_OPTS.keys))
|
62
|
+
end
|
63
|
+
|
64
|
+
def topic(name)
|
65
|
+
@topics[name] ||= self.class::Topic.new(@client, name)
|
66
|
+
end
|
67
|
+
|
68
|
+
def close
|
69
|
+
# NATS/STAN do not survive multi-closes, so close only once:
|
70
|
+
@client&.close
|
71
|
+
@client = nil
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/bps/stan.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'bps'
|
2
|
+
require 'bps/publisher/stan'
|
3
|
+
|
4
|
+
module BPS
|
5
|
+
module Publisher
|
6
|
+
register('stan') do |url, **opts|
|
7
|
+
cluster_id, client_id, url_opts = STAN.parse_url(url)
|
8
|
+
url_opts.update(opts)
|
9
|
+
STAN.new(cluster_id, client_id, **STAN.coercer.coerce(url_opts))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'bps/stan'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
RSpec.describe 'STAN', stan: true do
|
5
|
+
context 'resolve addrs' do
|
6
|
+
let(:publisher) { double('BPS::Publisher::STAN') }
|
7
|
+
before { allow(BPS::Publisher::STAN).to receive(:new).and_return(publisher) }
|
8
|
+
|
9
|
+
it 'should resolve simple URLs' do
|
10
|
+
expect(BPS::Publisher::STAN)
|
11
|
+
.to receive(:new)
|
12
|
+
.with('CLUSTER', 'CLIENT', nats: { servers: ['nats://test.host:4222'] })
|
13
|
+
.and_return(publisher)
|
14
|
+
BPS::Publisher.resolve(URI.parse('stan://test.host:4222?cluster_id=CLUSTER&client_id=CLIENT'))
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should resolve URLs with multiple hosts' do
|
18
|
+
expect(BPS::Publisher::STAN)
|
19
|
+
.to receive(:new)
|
20
|
+
.with('CLUSTER', 'CLIENT', nats: { servers: ['nats://foo.host:4222', 'nats://bar.host:4222'] })
|
21
|
+
.and_return(publisher)
|
22
|
+
BPS::Publisher.resolve(URI.parse('stan://foo.host,bar.host:4222?cluster_id=CLUSTER&client_id=CLIENT'))
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should resolve URLs with multiple hosts/ports' do
|
26
|
+
expect(BPS::Publisher::STAN)
|
27
|
+
.to receive(:new)
|
28
|
+
.with('CLUSTER', 'CLIENT', nats: { servers: ['nats://foo.host:4223', 'nats://bar.host:4222'] })
|
29
|
+
.and_return(publisher)
|
30
|
+
BPS::Publisher.resolve(URI.parse('stan://foo.host%3A4223,bar.host?cluster_id=CLUSTER&client_id=CLIENT'))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context BPS::Publisher::STAN do
|
35
|
+
let(:cluster_id) { 'test-cluster' } # this is a default cluster for https://hub.docker.com/_/nats-streaming
|
36
|
+
let(:client_id) { 'bps-test' }
|
37
|
+
|
38
|
+
let(:nats_servers) { ENV.fetch('NATS_SERVERS', '127.0.0.1:4222').split(',') }
|
39
|
+
let(:nats_servers_with_scheme) { nats_servers.map {|s| "nats://#{s}" } }
|
40
|
+
|
41
|
+
let(:publisher_url) { "stan://#{CGI.escape(nats_servers.join(','))}/?cluster_id=#{cluster_id}&client_id=#{client_id}" }
|
42
|
+
|
43
|
+
def read_messages(topic_name, num_messages)
|
44
|
+
[].tap do |messages|
|
45
|
+
opts = {
|
46
|
+
servers: nats_servers_with_scheme,
|
47
|
+
dont_randomize_servers: true,
|
48
|
+
}
|
49
|
+
::STAN::Client.new.connect(cluster_id, client_id, nats: opts) do |client|
|
50
|
+
client.subscribe(topic_name, start_at: :first) do |msg|
|
51
|
+
messages << msg.data
|
52
|
+
next if messages.size == num_messages
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
it_behaves_like 'publisher'
|
59
|
+
end
|
60
|
+
end
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bps-stan
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Black Square Media
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-11-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bps
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.1.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.1.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: nats-streaming
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.2.2
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.2.2
|
41
|
+
description: https://github.com/bsm/bps
|
42
|
+
email: info@blacksquaremedia.com
|
43
|
+
executables: []
|
44
|
+
extensions: []
|
45
|
+
extra_rdoc_files: []
|
46
|
+
files:
|
47
|
+
- bps-stan.gemspec
|
48
|
+
- lib/bps-stan.rb
|
49
|
+
- lib/bps/publisher/stan.rb
|
50
|
+
- lib/bps/stan.rb
|
51
|
+
- spec/bps/stan_spec.rb
|
52
|
+
homepage: https://github.com/bsm/bps
|
53
|
+
licenses:
|
54
|
+
- Apache-2.0
|
55
|
+
metadata: {}
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 2.6.0
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
requirements: []
|
71
|
+
rubygems_version: 3.1.2
|
72
|
+
signing_key:
|
73
|
+
specification_version: 4
|
74
|
+
summary: BPS adapter for nats-streaming
|
75
|
+
test_files:
|
76
|
+
- spec/bps/stan_spec.rb
|