estore 0.1.0 → 0.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 18db1ad6f67a5c73ecd75dbe6fc80f5f03b717f2
4
- data.tar.gz: 47b240aa7ce8fddbe969103718a42a1668575f8d
3
+ metadata.gz: 78dbb09be7de8d003f5e6c5241a96df71b47c2db
4
+ data.tar.gz: 2e5cc0c9440c44154542855e92c014fe11fa7e83
5
5
  SHA512:
6
- metadata.gz: b5d4d2f91f7e7c2296684ac876e11b9c3959db6988e5b48cf0a8e5888723cd048acf68b14ebe159b0e9c2d4494030d2179912ef1777c6a4b878b5c85fbebcb60
7
- data.tar.gz: abaeaa10b0ec1c4d623bddb40550cee7f8d8afe2eddf36f19baea5092548cd5a74b6dd8098329f6d07a5b2626c634e57ae45d3bb846d79868f57dd8e9bb6c035
6
+ metadata.gz: 852983cf3c549846b0638e2405531b4455e8fc8ef4961b0f65f3de1a4f4dd3e676446b3c7acd5b6aeb320ad91fe9cf5b2dc10c1931cb96244f27ee204c6113e3
7
+ data.tar.gz: 75bea923d74418ea433f5e03952cf76ba302daa82ec7d8704dde450154c86807049562f60038905f1e0c1de7d34d9abb54b183cd86f4c9b7f7097ebb17c5bcdc
@@ -26,15 +26,15 @@ module Estore
26
26
  end
27
27
 
28
28
  def handle(message, *)
29
+ remove!
30
+
29
31
  response = decode(WriteEventsCompleted, message)
30
32
 
31
- if response.result != OperationResult::Success
32
- # TODO: Create custom exceptions
33
- raise "WriteEvents command failed with uuid #{@uuid}"
33
+ if response.result == OperationResult::Success
34
+ promise.fulfill(response)
35
+ else
36
+ promise.reject Estore::WriteEventsError.new(response)
34
37
  end
35
-
36
- remove!
37
- promise.fulfill(response)
38
38
  end
39
39
 
40
40
  private
@@ -16,6 +16,10 @@ module Estore
16
16
  @connection.remove(self)
17
17
  end
18
18
 
19
+ def reject!(error)
20
+ @promise.reject(error) if @promise
21
+ end
22
+
19
23
  def write(command, message = nil)
20
24
  @connection.write(@uuid, command, message)
21
25
  end
@@ -4,11 +4,13 @@ module Estore
4
4
  include Command
5
5
 
6
6
  def call
7
+ register!
7
8
  write('Ping')
8
9
  promise
9
10
  end
10
11
 
11
12
  def handle(*)
13
+ remove!
12
14
  promise.fulfill('Pong')
13
15
  end
14
16
  end
@@ -5,12 +5,13 @@ module Estore
5
5
  class Connection
6
6
  extend Forwardable
7
7
 
8
+ attr_reader :host, :port
8
9
  delegate [:register, :remove] => :@context
9
10
 
10
- def initialize(host, port, context)
11
+ def initialize(host, port)
11
12
  @host = host
12
13
  @port = Integer(port)
13
- @context = context
14
+ @context = ConnectionContext.new
14
15
  @buffer = Buffer.new(&method(:on_received_package))
15
16
  @mutex = Mutex.new
16
17
  end
@@ -47,14 +48,11 @@ module Estore
47
48
 
48
49
  def connect
49
50
  @socket = TCPSocket.open(@host, @port)
50
- Thread.new do
51
- process_downstream
52
- end
51
+ Thread.new { process_downstream }
53
52
  @socket
54
53
  rescue TimeoutError, Errno::ECONNREFUSED, Errno::EHOSTDOWN,
55
54
  Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ETIMEDOUT
56
- raise CannotConnectError, "Error connecting to Eventstore on "\
57
- "#{@host.inspect}:#{@port.inspect} (#{$ERROR_INFO.class})"
55
+ raise CannotConnectError, "#{@host}:#{@port} (#{$ERROR_INFO.class})"
58
56
  end
59
57
 
60
58
  def process_downstream
@@ -62,21 +60,8 @@ module Estore
62
60
  @buffer << socket.sysread(4096)
63
61
  end
64
62
  rescue IOError, EOFError
65
- on_disconnect
63
+ @context.on_error(DisconnectionError.new) unless @terminating
66
64
  rescue => error
67
- on_exception(error)
68
- end
69
-
70
- def on_disconnect
71
- return if @terminating
72
- puts 'Eventstore disconnected'
73
- context.on_error(DisconnectionError.new('Eventstore disconnected'))
74
- end
75
-
76
- def on_exception(error)
77
- puts "process_downstream_error"
78
- puts error.message
79
- puts error.backtrace
80
65
  @context.on_error(error)
81
66
  end
82
67
  end
@@ -24,5 +24,12 @@ module Estore
24
24
  command = @commands[uuid]
25
25
  command.handle(message, type) if command
26
26
  end
27
+
28
+ def on_error(error)
29
+ # TODO: Error handling
30
+ @mutex.synchronize do
31
+ @commands.each { |_uuid, command| command.reject! error }
32
+ end
33
+ end
27
34
  end
28
35
  end
data/lib/estore/errors.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  module Estore
2
- CannotConnectError = Class.new(RuntimeError)
3
- DisconnectionError = Class.new(RuntimeError)
2
+ CannotConnectError = Class.new(StandardError)
3
+ DisconnectionError = Class.new(StandardError)
4
+ WriteEventsError = Class.new(StandardError)
4
5
  end
@@ -13,21 +13,16 @@ module Estore
13
13
  # To get maximum performance from the connection, it is recommended to use it
14
14
  # asynchronously.
15
15
  class Session
16
- attr_reader :host, :port, :connection, :context
16
+ extend Forwardable
17
17
 
18
- def initialize(host, port = 2113)
19
- @host = host
20
- @port = port
21
- @context = ConnectionContext.new
22
- @connection = Connection.new(host, port, context)
23
- end
18
+ delegate [:host, :post] => :@connection
24
19
 
25
- def on_error(error = nil, &block)
26
- context.on_error(error, &block)
20
+ def initialize(host, port = 2113)
21
+ @connection = Connection.new(host, port)
27
22
  end
28
23
 
29
24
  def close
30
- connection.close
25
+ @connection.close
31
26
  end
32
27
 
33
28
  def ping
@@ -68,7 +63,7 @@ module Estore
68
63
  private
69
64
 
70
65
  def command(command, *args)
71
- command.new(connection, *args)
66
+ command.new(@connection, *args)
72
67
  end
73
68
  end
74
69
  end
@@ -1,3 +1,3 @@
1
1
  module Estore
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.1'
3
3
  end
@@ -39,33 +39,22 @@ describe Estore::Session do
39
39
  stream
40
40
  end
41
41
 
42
- RSpec::Matchers.define :start_from do |start|
43
- match do |events|
44
- events.each_with_index do |event, index|
45
- expect(parse_data(event)).to eql('id' => index + start)
46
- end
47
- end
48
- end
49
-
50
42
  it 'reads all the events from a stream' do
51
- events = session.read(stream_with(200)).sync
43
+ stream = session.read(stream_with(200)).sync
52
44
 
53
- expect(events.size).to be(200)
54
- expect(events).to start_from(0)
45
+ expect(stream).to have(200).events.starting_at(0)
55
46
  end
56
47
 
57
48
  it 'reads all the events forward from a stream' do
58
- events = session.read(stream_with(100), from: 20).sync
49
+ stream = session.read(stream_with(100), from: 20).sync
59
50
 
60
- expect(events.size).to be(80)
61
- expect(events).to start_from(20)
51
+ expect(stream).to have(80).events.starting_at(20)
62
52
  end
63
53
 
64
54
  it 'reads a batch of events from a stream' do
65
- events = session.read(stream_with(30), from: 10, limit: 15).sync
55
+ stream = session.read(stream_with(30), from: 10, limit: 15).sync
66
56
 
67
- expect(events.size).to be(15)
68
- expect(events).to start_from(10)
57
+ expect(stream).to have(15).events.starting_at(10)
69
58
  end
70
59
 
71
60
  it 'allows to make a live subscription' do
@@ -80,15 +69,7 @@ describe Estore::Session do
80
69
 
81
70
  stream_with(50, stream)
82
71
 
83
- Timeout.timeout(5) do
84
- loop do
85
- break if received.size >= 50
86
- sleep(0.1)
87
- end
88
- end
89
-
90
- expect(received.size).to be(50)
91
- expect(received).to start_from(20)
72
+ expect(received).to have(50).events.starting_at(20).before(5.seconds)
92
73
  end
93
74
 
94
75
  it 'allows to make a catchup subscription' do
@@ -97,8 +78,11 @@ describe Estore::Session do
97
78
 
98
79
  stream_with(2100, stream)
99
80
 
100
- sub = session.subscription(stream, from: 20)
101
- sub.on_event { |event| received << event }
81
+ sub = session.subscription(stream, from: 30)
82
+ sub.on_event do |event|
83
+ received << event
84
+ puts "Receiving... #{received.size}"
85
+ end
102
86
  sub.start
103
87
 
104
88
  Thread.new do
@@ -107,14 +91,6 @@ describe Estore::Session do
107
91
  end
108
92
  end
109
93
 
110
- Timeout.timeout(5) do
111
- loop do
112
- break if received.size >= 2180
113
- sleep(0.1)
114
- end
115
- end
116
-
117
- expect(received.size).to be(2180)
118
- expect(received).to start_from(20)
94
+ expect(received).to have(2170).events.starting_at(30).before(20.seconds)
119
95
  end
120
96
  end
data/spec/spec_helper.rb CHANGED
@@ -13,3 +13,45 @@ trap 'TTIN' do
13
13
  puts "\n\n\n"
14
14
  end
15
15
  end
16
+
17
+ class Integer
18
+ # Just for readability
19
+ def seconds
20
+ self
21
+ end
22
+ end
23
+
24
+ RSpec::Matchers.define :have do |expectation|
25
+ match do |actual|
26
+ if @timeout
27
+ Timeout.timeout @timeout do
28
+ loop do
29
+ break if actual.to_a.size >= expectation
30
+ sleep(0.1)
31
+ end
32
+ end
33
+ end
34
+
35
+ expect(actual.to_a.size).to @bigger ? be >= expectation : be(expectation)
36
+
37
+ if @start
38
+ actual.each_with_index do |wrapper, index|
39
+ expect(wrapper.event.event_number).to be(index + @start)
40
+ end
41
+ end
42
+ end
43
+
44
+ chain(:events) {}
45
+
46
+ chain :before do |seconds|
47
+ @timeout = seconds
48
+ end
49
+
50
+ chain :or_more do
51
+ @bigger = true
52
+ end
53
+
54
+ chain :starting_at do |start|
55
+ @start = start
56
+ end
57
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: estore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mathieu Ravaux
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-04-03 00:00:00.000000000 Z
12
+ date: 2015-04-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: beefcake