bps 0.0.1
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.gemspec +19 -0
- data/lib/bps.rb +52 -0
- data/lib/bps/coercer.rb +64 -0
- data/lib/bps/publisher/abstract.rb +24 -0
- data/lib/bps/subscriber/abstract.rb +14 -0
- data/spec/bps/coercer_spec.rb +42 -0
- metadata +49 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5de5e6e993f0b96c93224163f85fc0cd3ef5a9ecf7d03487df35315ee3bd153b
|
4
|
+
data.tar.gz: cfaa3b821549d70bee5094321553123493d9e66fca4cf15fa50ccdb0f4c5a04d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c4d068aa91b285af2a124a258a13207298c3c0f9202fe39f197e21a9fd49a53f433de12cf4817b78b265b2920deeaa402a014cba0fe74da3b258570688b8fb1e
|
7
|
+
data.tar.gz: 4b7f0fa9bf89e079e05312e4d202af107b102c51079166704ca4641146942a0b3a692a0605d52bf0e46bbb8d8847b0969a8c8c20e763308d160988cff1c7d9c5
|
data/bps.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'bps'
|
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 = 'Multi-platform pubsub adapter'
|
8
|
+
s.description = 'Minimalist abstraction for publish-subscribe'
|
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
|
+
end
|
data/lib/bps.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'cgi'
|
3
|
+
|
4
|
+
module BPS
|
5
|
+
autoload :Coercer, 'bps/coercer'
|
6
|
+
|
7
|
+
module Publisher
|
8
|
+
autoload :Abstract, 'bps/publisher/abstract'
|
9
|
+
|
10
|
+
def self.register(*schemes, &resolver)
|
11
|
+
@registry ||= {}
|
12
|
+
schemes.each do |scheme|
|
13
|
+
@registry[scheme] = resolver
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.resolve(url)
|
18
|
+
url = url.is_a?(::URI) ? url.dup : URI.parse(url)
|
19
|
+
rsl = @registry[url.scheme]
|
20
|
+
raise ArgumentError, "Unable to resolve publisher #{url}, scheme #{url.scheme} is not registered" unless rsl
|
21
|
+
|
22
|
+
opts = {}
|
23
|
+
CGI.parse(url.query.to_s).each do |key, values|
|
24
|
+
opts[key.to_sym] = values.first
|
25
|
+
end
|
26
|
+
rsl.call(url, opts)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module Subscriber
|
31
|
+
autoload :Abstract, 'bps/subscriber/abstract'
|
32
|
+
|
33
|
+
def self.register(*schemes, &resolver)
|
34
|
+
@registry ||= {}
|
35
|
+
schemes.each do |scheme|
|
36
|
+
@registry[scheme] = resolver
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.resolve(url)
|
41
|
+
url = url.is_a?(::URI) ? url.dup : URI.parse(url)
|
42
|
+
rsl = @registry[url.scheme]
|
43
|
+
raise ArgumentError, "Unable to resolve subscriber #{url}, scheme #{url.scheme} is not registered" unless rsl
|
44
|
+
|
45
|
+
opts = {}
|
46
|
+
CGI.parse(url.query.to_s).each do |key, values|
|
47
|
+
opts[key.to_sym] = values.first
|
48
|
+
end
|
49
|
+
rsl.call(url, opts)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/bps/coercer.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module BPS
|
4
|
+
class Coercer
|
5
|
+
TRUE_VALUES = [true, 'TRUE', 'true', 'T', 't', 1, '1'].to_set
|
6
|
+
|
7
|
+
attr_reader :schema
|
8
|
+
|
9
|
+
def initialize(schema)
|
10
|
+
validate!(schema)
|
11
|
+
@schema = schema
|
12
|
+
end
|
13
|
+
|
14
|
+
def coerce(hash)
|
15
|
+
coerce_with(@schema, hash)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def validate!(schema)
|
21
|
+
schema.each do |key, type|
|
22
|
+
case type
|
23
|
+
when :string, :symbol, :int, :float, :bool
|
24
|
+
# OK
|
25
|
+
when Hash
|
26
|
+
validate!(type)
|
27
|
+
when Array
|
28
|
+
raise ArgumentError, "Array types must have exactly one entry, but was (#{key} => #{type.inspect})" unless type.size == 1
|
29
|
+
else
|
30
|
+
raise ArgumentError, "Unknown type #{type.inspect}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def coerce_with(schema, hash)
|
36
|
+
clone = {}
|
37
|
+
schema.each do |key, type|
|
38
|
+
next unless hash.key?(key)
|
39
|
+
|
40
|
+
clone[key] = coerce_value(type, hash[key])
|
41
|
+
end
|
42
|
+
clone
|
43
|
+
end
|
44
|
+
|
45
|
+
def coerce_value(type, val)
|
46
|
+
case type
|
47
|
+
when :string
|
48
|
+
val&.to_s
|
49
|
+
when :symbol
|
50
|
+
val&.to_sym
|
51
|
+
when :int
|
52
|
+
val&.to_i
|
53
|
+
when :float
|
54
|
+
val&.to_f
|
55
|
+
when :bool
|
56
|
+
val.nil? ? nil : TRUE_VALUES.include?(val)
|
57
|
+
when Hash
|
58
|
+
val.is_a?(Hash) ? coerce_with(type, val) : nil
|
59
|
+
when Array
|
60
|
+
Array(val).map {|v| coerce_value(type[0], v) }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module BPS
|
2
|
+
module Publisher
|
3
|
+
class Abstract
|
4
|
+
class Topic
|
5
|
+
# Publish a message.
|
6
|
+
def publish(_message, **_opts)
|
7
|
+
raise 'not implemented'
|
8
|
+
end
|
9
|
+
|
10
|
+
# Flush any remaining buffer.
|
11
|
+
def flush(**); end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Retrieve a topic handle.
|
15
|
+
# @params [String] name the topic name.
|
16
|
+
def topic(_name)
|
17
|
+
raise 'not implemented'
|
18
|
+
end
|
19
|
+
|
20
|
+
# Close the publisher.
|
21
|
+
def close; end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe BPS::Coercer do
|
4
|
+
subject do
|
5
|
+
described_class.new(
|
6
|
+
name: :string,
|
7
|
+
codec: :symbol,
|
8
|
+
retries: :int,
|
9
|
+
backoff: :float,
|
10
|
+
idempotent: :bool,
|
11
|
+
tags: [:string],
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
let :options do
|
16
|
+
{
|
17
|
+
name: 123,
|
18
|
+
codec: 'snappy',
|
19
|
+
retries: '4',
|
20
|
+
backoff: '10',
|
21
|
+
idempotent: '1',
|
22
|
+
tags: [:foo, 33],
|
23
|
+
extra: 'foo',
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should validate' do
|
28
|
+
expect { described_class.new(name: :unknown) }.to raise_error(ArgumentError, /Unknown type :unknown/)
|
29
|
+
expect { described_class.new(bad: []) }.to raise_error(ArgumentError, /Array types must have exactly one entry/)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should coerce options' do
|
33
|
+
expect(subject.coerce(options)).to eq(
|
34
|
+
name: '123',
|
35
|
+
codec: :snappy,
|
36
|
+
retries: 4,
|
37
|
+
backoff: 10.0,
|
38
|
+
idempotent: true,
|
39
|
+
tags: %w[foo 33],
|
40
|
+
)
|
41
|
+
end
|
42
|
+
end
|
metadata
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bps
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Black Square Media
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-07-01 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Minimalist abstraction for publish-subscribe
|
14
|
+
email: info@blacksquaremedia.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- bps.gemspec
|
20
|
+
- lib/bps.rb
|
21
|
+
- lib/bps/coercer.rb
|
22
|
+
- lib/bps/publisher/abstract.rb
|
23
|
+
- lib/bps/subscriber/abstract.rb
|
24
|
+
- spec/bps/coercer_spec.rb
|
25
|
+
homepage: https://github.com/bsm/bps
|
26
|
+
licenses:
|
27
|
+
- Apache-2.0
|
28
|
+
metadata: {}
|
29
|
+
post_install_message:
|
30
|
+
rdoc_options: []
|
31
|
+
require_paths:
|
32
|
+
- lib
|
33
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
34
|
+
requirements:
|
35
|
+
- - ">="
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 2.6.0
|
38
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
requirements: []
|
44
|
+
rubygems_version: 3.1.4
|
45
|
+
signing_key:
|
46
|
+
specification_version: 4
|
47
|
+
summary: Multi-platform pubsub adapter
|
48
|
+
test_files:
|
49
|
+
- spec/bps/coercer_spec.rb
|