faymora 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/Gemfile +42 -0
- data/LICENSE.md +375 -0
- data/README.md +13 -0
- data/faymora.gemspec +35 -0
- data/lib/faymora/client.rb +26 -0
- data/lib/faymora/connection.rb +33 -0
- data/lib/faymora/instance.rb +120 -0
- data/lib/faymora/item.rb +29 -0
- data/lib/faymora/link.rb +55 -0
- data/lib/faymora/node.rb +52 -0
- data/lib/faymora/provision.rb +14 -0
- data/lib/faymora/rectifier.rb +18 -0
- data/lib/faymora/rpc.rb +17 -0
- data/lib/faymora/service.rb +59 -0
- data/lib/faymora/throughput.rb +46 -0
- data/lib/faymora/version.rb +3 -0
- data/lib/faymora.rb +17 -0
- data/spec/faymora/client_spec.rb +56 -0
- data/spec/faymora/connection_spec.rb +89 -0
- data/spec/faymora/item_spec.rb +80 -0
- data/spec/faymora/link_spec.rb +140 -0
- data/spec/faymora/node_spec.rb +107 -0
- data/spec/faymora/provision_spec.rb +33 -0
- data/spec/faymora/rpc_spec.rb +43 -0
- data/spec/faymora/service_spec.rb +102 -0
- data/spec/faymora/throughput_spec.rb +125 -0
- data/spec/spec_helper.rb +30 -0
- data/spec/support/gloox/node.rb +21 -0
- data/spec/support/gloox.rb +12 -0
- data/spec/support/slotz.rb +10 -0
- metadata +127 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe Faymora::Node do
|
|
4
|
+
describe '#initialize' do
|
|
5
|
+
it 'inherits from GlooX::Node and forces serializer to MessagePack' do
|
|
6
|
+
expect(described_class < GlooX::Node).to be true
|
|
7
|
+
|
|
8
|
+
n = described_class.new(url: 'u', serializer: :other, extra: 1)
|
|
9
|
+
expect(n).to be_a(GlooX::Node)
|
|
10
|
+
expect(n.opts[:serializer]).to be(MessagePack)
|
|
11
|
+
expect(n.opts[:url]).to eq('u')
|
|
12
|
+
expect(n.opts[:extra]).to eq(1)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe '.connect' do
|
|
17
|
+
it 'builds a Faymora::Client with handler: :node merged into options' do
|
|
18
|
+
client = instance_double(Faymora::Client)
|
|
19
|
+
expect(Faymora::Client).to receive(:new)
|
|
20
|
+
.with(hash_including(host: 'h', handler: :node))
|
|
21
|
+
.and_return(client)
|
|
22
|
+
|
|
23
|
+
result = described_class.connect(host: 'h')
|
|
24
|
+
expect(result).to eq(client)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe '.start' do
|
|
29
|
+
it 'instantiates a node, calls #start and returns the instance' do
|
|
30
|
+
instance = instance_double(described_class)
|
|
31
|
+
expect(described_class).to receive(:new).with(foo: 1).and_return(instance)
|
|
32
|
+
expect(instance).to receive(:start)
|
|
33
|
+
|
|
34
|
+
expect(described_class.start(foo: 1)).to eq(instance)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
describe '.boot' do
|
|
39
|
+
it 'calls .start and then .connect using the started node url' do
|
|
40
|
+
started = instance_double(described_class, url: 'xmpp://example')
|
|
41
|
+
expect(described_class).to receive(:start).with(role: 'worker').and_return(started)
|
|
42
|
+
|
|
43
|
+
client = instance_double(Faymora::Client)
|
|
44
|
+
expect(Faymora::Client).to receive(:new)
|
|
45
|
+
.with(hash_including(url: 'xmpp://example', handler: :node))
|
|
46
|
+
.and_return(client)
|
|
47
|
+
|
|
48
|
+
expect(described_class.boot(role: 'worker')).to eq(client)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
describe '.when_ready' do
|
|
53
|
+
# A tiny fake reactor to drive the polling loop deterministically
|
|
54
|
+
class FakeReactor
|
|
55
|
+
def initialize
|
|
56
|
+
@calls = 0
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def run_in_thread; end
|
|
60
|
+
|
|
61
|
+
# Call the provided block immediately, passing the block itself as `task`
|
|
62
|
+
def delay(_seconds, &blk)
|
|
63
|
+
blk.call(blk)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Expose a toggling state through the same instance
|
|
67
|
+
def rpc_exception?
|
|
68
|
+
@calls += 1
|
|
69
|
+
@calls == 1
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'polls client.alive? until success, then closes client and yields' do
|
|
74
|
+
# Replace Raktr constant with our fake reactor
|
|
75
|
+
stub_const('Raktr', Class.new do
|
|
76
|
+
def initialize; end
|
|
77
|
+
def run_in_thread; end
|
|
78
|
+
def delay(_s)
|
|
79
|
+
# Provide a task proc to the block and let the block control rescheduling
|
|
80
|
+
yield(proc {})
|
|
81
|
+
end
|
|
82
|
+
end)
|
|
83
|
+
|
|
84
|
+
reactor = double('reactor', run_in_thread: true)
|
|
85
|
+
allow(Raktr).to receive(:new).and_return(reactor)
|
|
86
|
+
|
|
87
|
+
# The `alive?` callback receives an object responding to `rpc_exception?` and `delay`.
|
|
88
|
+
poller = FakeReactor.new
|
|
89
|
+
|
|
90
|
+
client = instance_double(Faymora::Client)
|
|
91
|
+
expect(Faymora::Client).to receive(:new)
|
|
92
|
+
.with(hash_including(url: 'xmpp://n', handler: :node, client_max_retries: 0, connection_pool_size: 1))
|
|
93
|
+
.and_return(client)
|
|
94
|
+
|
|
95
|
+
# Simulate two polls: first with exception, then success
|
|
96
|
+
expect(client).to receive(:alive?) do |&blk|
|
|
97
|
+
blk.call(poller)
|
|
98
|
+
end.twice
|
|
99
|
+
|
|
100
|
+
expect(client).to receive(:close)
|
|
101
|
+
|
|
102
|
+
yielded = false
|
|
103
|
+
described_class.when_ready('xmpp://n') { yielded = true }
|
|
104
|
+
expect(yielded).to be true
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe Faymora::Provision do
|
|
4
|
+
# Host class to include the module under test
|
|
5
|
+
class HostForProvision
|
|
6
|
+
include Faymora::Provision
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
describe 'inclusion' do
|
|
10
|
+
it 'adds a .provision class method to the host' do
|
|
11
|
+
expect(HostForProvision).to respond_to(:provision)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe '.provision' do
|
|
16
|
+
it 'delegates to Slotz::Reservation.provision with the host class and options' do
|
|
17
|
+
options = { size: 3, region: 'eu' }
|
|
18
|
+
expect(Slotz::Reservation).to receive(:provision)
|
|
19
|
+
.with(HostForProvision, options)
|
|
20
|
+
.and_return(:token)
|
|
21
|
+
|
|
22
|
+
expect(HostForProvision.provision(options)).to eq(:token)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'passes an empty hash when options are omitted' do
|
|
26
|
+
expect(Slotz::Reservation).to receive(:provision)
|
|
27
|
+
.with(HostForProvision, {})
|
|
28
|
+
.and_return(:ok)
|
|
29
|
+
|
|
30
|
+
expect(HostForProvision.provision).to eq(:ok)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe Faymora::RPC do
|
|
4
|
+
# Minimal host including the module under test
|
|
5
|
+
class DummyRPC
|
|
6
|
+
include Faymora::RPC
|
|
7
|
+
|
|
8
|
+
def initialize(url)
|
|
9
|
+
@url = url
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def url
|
|
13
|
+
@url
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
let(:url) { 'xmpp://example' }
|
|
18
|
+
let(:host) { DummyRPC.new(url) }
|
|
19
|
+
|
|
20
|
+
describe '#client' do
|
|
21
|
+
it 'builds a Faymora::Client with the instance url and handler: :instance' do
|
|
22
|
+
client = instance_double(Faymora::Client)
|
|
23
|
+
expect(Faymora::Client).to receive(:new)
|
|
24
|
+
.with(hash_including(url: url, handler: :instance))
|
|
25
|
+
.and_return(client)
|
|
26
|
+
|
|
27
|
+
expect(host.client).to be(client)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe '#server' do
|
|
32
|
+
it 'returns self' do
|
|
33
|
+
expect(host.server).to be(host)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe '#node' do
|
|
38
|
+
it 'is defined (abstract) and returns nil by default' do
|
|
39
|
+
expect(host).to respond_to(:node)
|
|
40
|
+
expect(host.node).to be_nil
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe Faymora::Service do
|
|
4
|
+
# Dummy host including the module under test
|
|
5
|
+
class DummyService
|
|
6
|
+
include Faymora::Service
|
|
7
|
+
|
|
8
|
+
# Provide a minimal client to satisfy Link expectations if ever invoked
|
|
9
|
+
def client
|
|
10
|
+
:client
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
let(:service_class) { Class.new(DummyService) }
|
|
15
|
+
let(:service) { service_class.new }
|
|
16
|
+
|
|
17
|
+
describe 'class DSL' do
|
|
18
|
+
it 'defaults would_interest? to true when no predicate set' do
|
|
19
|
+
c = Class.new(DummyService)
|
|
20
|
+
expect(c.would_interest?(Faymora::Item.new(foo: 1))).to be true
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'allows setting an interest predicate via .interested_in' do
|
|
24
|
+
service_class.interested_in { |item| item.respond_to?(:foo) && item.foo == 2 }
|
|
25
|
+
|
|
26
|
+
expect(service_class.would_interest?(Faymora::Item.new(foo: 2))).to be true
|
|
27
|
+
expect(service_class.would_interest?(Faymora::Item.new(foo: 1))).to be false
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'stores a consumer via .upon and exposes it via ._upon' do
|
|
31
|
+
blk = proc { |i| [:handled, i] }
|
|
32
|
+
service_class.upon(&blk)
|
|
33
|
+
|
|
34
|
+
stored = service_class._upon
|
|
35
|
+
expect(stored).to be_a(Proc)
|
|
36
|
+
item = Faymora::Item.new
|
|
37
|
+
expect(stored.call(item)).to eq([:handled, item])
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'toggles ignore state via .ignore! and .ignore?' do
|
|
41
|
+
expect(service_class.ignore?).to be false
|
|
42
|
+
service_class.ignore!
|
|
43
|
+
expect(service_class.ignore?).to be true
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe '#join' do
|
|
48
|
+
it 'yields to the provided block and returns its result' do
|
|
49
|
+
yielded = nil
|
|
50
|
+
result = service.join { yielded = :ok; 123 }
|
|
51
|
+
expect(yielded).to eq(:ok)
|
|
52
|
+
expect(result).to eq(123)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
describe '#interested?' do
|
|
57
|
+
it 'delegates to the class-level would_interest? with the item' do
|
|
58
|
+
service_class.interested_in { |i| i.foo == 'y' }
|
|
59
|
+
yes = Faymora::Item.new(foo: 'y')
|
|
60
|
+
no = Faymora::Item.new(foo: 'n')
|
|
61
|
+
|
|
62
|
+
expect(service.interested?(yes)).to be true
|
|
63
|
+
expect(service.interested?(no)).to be false
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
describe '#interested!' do
|
|
68
|
+
it 'marks the item as interesting' do
|
|
69
|
+
item = Faymora::Item.new
|
|
70
|
+
service.interested!(item)
|
|
71
|
+
expect(item.interesting).to be true
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
describe '#consume' do
|
|
76
|
+
it 'invokes the class-level consumer with the item and returns its result' do
|
|
77
|
+
service_class.upon { |i| i.processed = true; :done }
|
|
78
|
+
item = Faymora::Item.new
|
|
79
|
+
expect(service.consume(item)).to eq(:done)
|
|
80
|
+
expect(item.processed).to be true
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
describe '#process' do
|
|
85
|
+
it 'converts non-Item data via Item.from_data and consumes when interested' do
|
|
86
|
+
# Predicate always true
|
|
87
|
+
service_class.interested_in { |_i| true }
|
|
88
|
+
service_class.upon { |i| [i.class, i.foo] }
|
|
89
|
+
|
|
90
|
+
result = service.process({ foo: 5 })
|
|
91
|
+
expect(result).to eq([Faymora::Item, 5])
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it 'returns nil and does not consume when not interested' do
|
|
95
|
+
service_class.interested_in { |_i| false }
|
|
96
|
+
expect(service_class).not_to receive(:_upon)
|
|
97
|
+
|
|
98
|
+
res = service.process(Faymora::Item.new(foo: 1))
|
|
99
|
+
expect(res).to be_nil
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe Faymora::Throughput do
|
|
4
|
+
# Minimal host including the module under test
|
|
5
|
+
class DummyThroughput
|
|
6
|
+
include Faymora::Throughput
|
|
7
|
+
|
|
8
|
+
attr_accessor :input
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
super
|
|
12
|
+
@clock_counter = 0
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def has_input?
|
|
16
|
+
!!@input
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Expose counters for assertions in specs
|
|
20
|
+
def click_counter
|
|
21
|
+
@click_counter
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def clock_counter
|
|
25
|
+
@clock_counter
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
let(:host) { DummyThroughput.new }
|
|
30
|
+
|
|
31
|
+
before do
|
|
32
|
+
# Avoid running real GC during specs
|
|
33
|
+
allow(GC).to receive(:start)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe '#clock' do
|
|
37
|
+
it 'yields the item, appends a pass with class name, and always calls click!' do
|
|
38
|
+
item = Faymora::Item.new(passes: [])
|
|
39
|
+
|
|
40
|
+
# Verify it yields and records a pass
|
|
41
|
+
yielded = nil
|
|
42
|
+
expect(host).to receive(:click!).and_call_original
|
|
43
|
+
|
|
44
|
+
host.clock(item) { |i| yielded = i }
|
|
45
|
+
|
|
46
|
+
expect(yielded).to be(item)
|
|
47
|
+
expect(item.passes).not_to be_empty
|
|
48
|
+
last = item.passes.last
|
|
49
|
+
expect(last).to be_a(Faymora::Item::Pass)
|
|
50
|
+
expect(last.path).to eq(DummyThroughput.to_s)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'still calls click! when the block raises (ensure)' do
|
|
54
|
+
item = Faymora::Item.new(passes: [])
|
|
55
|
+
expect(host).to receive(:click!).and_call_original
|
|
56
|
+
|
|
57
|
+
expect do
|
|
58
|
+
host.clock(item) { raise 'boom' }
|
|
59
|
+
end.to raise_error(RuntimeError, 'boom')
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe '#click!' do
|
|
64
|
+
it 'increments the click counter and triggers GC' do
|
|
65
|
+
expect(host.click_counter).to eq 0
|
|
66
|
+
host.click!
|
|
67
|
+
expect(host.click_counter).to eq(1)
|
|
68
|
+
expect(GC).to have_received(:start)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'calls rectify when bottleneck? is true and not otherwise', focus: true do
|
|
72
|
+
allow(host).to receive(:bottleneck?).and_return(true)
|
|
73
|
+
expect(host).to receive(:rectify)
|
|
74
|
+
host.click!
|
|
75
|
+
|
|
76
|
+
allow(host).to receive(:bottleneck?).and_return(false)
|
|
77
|
+
expect(host).not_to receive(:rectify)
|
|
78
|
+
host.click!
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
describe '#throughput' do
|
|
83
|
+
it 'returns nil until warmed up, then clicks per clock_counter' do
|
|
84
|
+
# Not warmed up initially
|
|
85
|
+
expect(host.throughput).to be_nil
|
|
86
|
+
|
|
87
|
+
# Manually set counters to simulate warm state
|
|
88
|
+
host.instance_variable_set(:@clock_counter, 10)
|
|
89
|
+
host.instance_variable_set(:@click_counter, described_class::WARMED_UP_CLICKS)
|
|
90
|
+
|
|
91
|
+
t = host.throughput
|
|
92
|
+
expect(t).not_to be_nil
|
|
93
|
+
expect(t).to eq(described_class::WARMED_UP_CLICKS / 10.0)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
describe '#bottleneck?' do
|
|
98
|
+
it 'is false when there is no input or throughput is nil' do
|
|
99
|
+
# No input
|
|
100
|
+
allow(host).to receive(:throughput).and_return(100.0)
|
|
101
|
+
expect(host.bottleneck?).to be false
|
|
102
|
+
|
|
103
|
+
# With input but no throughput
|
|
104
|
+
host.input = instance_double('Upstream', throughput: 200.0)
|
|
105
|
+
allow(host).to receive(:throughput).and_return(nil)
|
|
106
|
+
expect(host.bottleneck?).to be false
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it 'returns true when input throughput is higher than own throughput' do
|
|
110
|
+
host.input = instance_double('Upstream', throughput: 10.0)
|
|
111
|
+
allow(host).to receive(:throughput).and_return(5.0)
|
|
112
|
+
expect(host.bottleneck?).to be true
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it 'returns false when input throughput is lower or equal' do
|
|
116
|
+
host.input = instance_double('Upstream', throughput: 5.0)
|
|
117
|
+
allow(host).to receive(:throughput).and_return(10.0)
|
|
118
|
+
expect(host.bottleneck?).to be false
|
|
119
|
+
|
|
120
|
+
host.input = instance_double('Upstream', throughput: 10.0)
|
|
121
|
+
allow(host).to receive(:throughput).and_return(10.0)
|
|
122
|
+
expect(host.bottleneck?).to be false
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Ensure our support files (including a stub for `gloox`) are available to `require`.
|
|
4
|
+
$LOAD_PATH.unshift File.expand_path('support', __dir__)
|
|
5
|
+
|
|
6
|
+
# Provide a minimal `symbolize_keys` to match expectations in the library if it's not available.
|
|
7
|
+
unless {}.respond_to?(:symbolize_keys)
|
|
8
|
+
class Hash
|
|
9
|
+
def symbolize_keys
|
|
10
|
+
each_with_object({}) do |(k, v), h|
|
|
11
|
+
h[(k.is_a?(String) ? k.to_sym : k)] = v
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
require 'rspec'
|
|
18
|
+
require 'faymora'
|
|
19
|
+
|
|
20
|
+
RSpec.configure do |config|
|
|
21
|
+
config.expect_with :rspec do |expectations|
|
|
22
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
config.mock_with :rspec do |mocks|
|
|
26
|
+
mocks.verify_partial_doubles = true
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
config.shared_context_metadata_behavior = :apply_to_host_groups
|
|
30
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Minimal stub for `require 'gloox/node'` used by Faymora::Node
|
|
2
|
+
module GlooX
|
|
3
|
+
class Node
|
|
4
|
+
attr_reader :opts
|
|
5
|
+
|
|
6
|
+
def initialize(options = {})
|
|
7
|
+
# Mirror the `@opts` behavior used across the library
|
|
8
|
+
@opts = options.dup
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Provide a no-op start to satisfy Faymora::Node.start
|
|
12
|
+
def start
|
|
13
|
+
self
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Provide a basic url accessor used by .boot in specs (when not stubbed)
|
|
17
|
+
def url
|
|
18
|
+
@opts[:url]
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Minimal stub for the external `gloox` gem used by the library during specs.
|
|
2
|
+
module GlooX
|
|
3
|
+
class Client
|
|
4
|
+
attr_reader :opts
|
|
5
|
+
|
|
6
|
+
def initialize(options = {})
|
|
7
|
+
# Store a dup so mutation outside won’t affect internals, and keep the
|
|
8
|
+
# exact semantics the library relies on: the ivar name is `@opts`.
|
|
9
|
+
@opts = options.dup
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Minimal stub for the external `slotz` gem used by the Provision module in specs.
|
|
2
|
+
module Slotz
|
|
3
|
+
module Reservation
|
|
4
|
+
# Placeholder to be stubbed in specs. Keeping a default no-op implementation
|
|
5
|
+
# to avoid unexpected NameErrors when not explicitly stubbed.
|
|
6
|
+
def self.provision(_klass, _options = {})
|
|
7
|
+
:ok
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: faymora
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: '0.1'
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Tasos Laskos
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 2026-01-06 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: gloox
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: ostruct
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: logger
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
description: ''
|
|
55
|
+
email: tasos.laskos@gmail.com
|
|
56
|
+
executables: []
|
|
57
|
+
extensions: []
|
|
58
|
+
extra_rdoc_files:
|
|
59
|
+
- LICENSE.md
|
|
60
|
+
- README.md
|
|
61
|
+
files:
|
|
62
|
+
- Gemfile
|
|
63
|
+
- LICENSE.md
|
|
64
|
+
- README.md
|
|
65
|
+
- faymora.gemspec
|
|
66
|
+
- lib/faymora.rb
|
|
67
|
+
- lib/faymora/client.rb
|
|
68
|
+
- lib/faymora/connection.rb
|
|
69
|
+
- lib/faymora/instance.rb
|
|
70
|
+
- lib/faymora/item.rb
|
|
71
|
+
- lib/faymora/link.rb
|
|
72
|
+
- lib/faymora/node.rb
|
|
73
|
+
- lib/faymora/provision.rb
|
|
74
|
+
- lib/faymora/rectifier.rb
|
|
75
|
+
- lib/faymora/rpc.rb
|
|
76
|
+
- lib/faymora/service.rb
|
|
77
|
+
- lib/faymora/throughput.rb
|
|
78
|
+
- lib/faymora/version.rb
|
|
79
|
+
- spec/faymora/client_spec.rb
|
|
80
|
+
- spec/faymora/connection_spec.rb
|
|
81
|
+
- spec/faymora/item_spec.rb
|
|
82
|
+
- spec/faymora/link_spec.rb
|
|
83
|
+
- spec/faymora/node_spec.rb
|
|
84
|
+
- spec/faymora/provision_spec.rb
|
|
85
|
+
- spec/faymora/rpc_spec.rb
|
|
86
|
+
- spec/faymora/service_spec.rb
|
|
87
|
+
- spec/faymora/throughput_spec.rb
|
|
88
|
+
- spec/spec_helper.rb
|
|
89
|
+
- spec/support/gloox.rb
|
|
90
|
+
- spec/support/gloox/node.rb
|
|
91
|
+
- spec/support/slotz.rb
|
|
92
|
+
homepage: https://github.com/faymora/faymora
|
|
93
|
+
licenses:
|
|
94
|
+
- MPL v2
|
|
95
|
+
metadata: {}
|
|
96
|
+
rdoc_options:
|
|
97
|
+
- "--charset=UTF-8"
|
|
98
|
+
require_paths:
|
|
99
|
+
- lib
|
|
100
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
101
|
+
requirements:
|
|
102
|
+
- - ">="
|
|
103
|
+
- !ruby/object:Gem::Version
|
|
104
|
+
version: '0'
|
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - ">="
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '0'
|
|
110
|
+
requirements: []
|
|
111
|
+
rubygems_version: 3.6.9
|
|
112
|
+
specification_version: 4
|
|
113
|
+
summary: ''
|
|
114
|
+
test_files:
|
|
115
|
+
- spec/faymora/client_spec.rb
|
|
116
|
+
- spec/faymora/connection_spec.rb
|
|
117
|
+
- spec/faymora/item_spec.rb
|
|
118
|
+
- spec/faymora/link_spec.rb
|
|
119
|
+
- spec/faymora/node_spec.rb
|
|
120
|
+
- spec/faymora/provision_spec.rb
|
|
121
|
+
- spec/faymora/rpc_spec.rb
|
|
122
|
+
- spec/faymora/service_spec.rb
|
|
123
|
+
- spec/faymora/throughput_spec.rb
|
|
124
|
+
- spec/spec_helper.rb
|
|
125
|
+
- spec/support/gloox.rb
|
|
126
|
+
- spec/support/gloox/node.rb
|
|
127
|
+
- spec/support/slotz.rb
|