http_eventstore 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 +7 -0
- data/.gitignore +12 -0
- data/Gemfile +4 -0
- data/README.md +134 -0
- data/Rakefile +2 -0
- data/http_eventstore.gemspec +29 -0
- data/lib/http_eventstore/actions/append_event_to_stream.rb +38 -0
- data/lib/http_eventstore/actions/delete_stream.rb +24 -0
- data/lib/http_eventstore/actions/read_all_stream_events.rb +34 -0
- data/lib/http_eventstore/actions/read_all_stream_events_backward.rb +43 -0
- data/lib/http_eventstore/actions/read_all_stream_events_forward.rb +43 -0
- data/lib/http_eventstore/actions/read_stream_events_backward.rb +29 -0
- data/lib/http_eventstore/actions/read_stream_events_forward.rb +29 -0
- data/lib/http_eventstore/api/client.rb +49 -0
- data/lib/http_eventstore/api/connection.rb +29 -0
- data/lib/http_eventstore/api/errors_handler.rb +19 -0
- data/lib/http_eventstore/connection.rb +47 -0
- data/lib/http_eventstore/endpoint.rb +16 -0
- data/lib/http_eventstore/errors.rb +20 -0
- data/lib/http_eventstore/event.rb +14 -0
- data/lib/http_eventstore/helpers/parse_entries.rb +22 -0
- data/lib/http_eventstore.rb +15 -0
- metadata +176 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a6d79d7fa69ffc2f0244660f573a7abe3df25867
|
4
|
+
data.tar.gz: 48e64de34b0a6465cb652695a2753c635511376f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f4c08e0f66ab32e400083f93dc0d9a992ca21cd07711b430884752ed5aa934bc6f6cc2dea373225fbf39fee14473ea3fea970021f3f2da149913e2e8bf6e7105
|
7
|
+
data.tar.gz: 942926179e12ef3ab9a2ddca512ad2dff6a1595cf82dae2915f9dd0ac55f5140e0c711dc44423e127f2f30305ea761aa665cc16d9db16f7b45b02d632c471ea3
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
# HttpEventstore
|
2
|
+
|
3
|
+
HttpEventstore is a HTTP connector to the Greg's [Event Store](https://geteventstore.com/).
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'http_eventstore'
|
11
|
+
```
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
To communicate with ES you have to create instance of `HttpEventstore::Connection` class. After configuring a client, you can do the following things.
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
client = HttpEventstore::Connection.new do |config|
|
19
|
+
#default value is '127.0.0.1'
|
20
|
+
config.endpoint = 'your_endpoint'
|
21
|
+
#default value is 2113
|
22
|
+
config.port = 'your_port'
|
23
|
+
#default value is 20 entries per page
|
24
|
+
config.page_size = 'your_page_size'
|
25
|
+
end
|
26
|
+
```
|
27
|
+
|
28
|
+
#### Creating new event
|
29
|
+
|
30
|
+
Creating a single event:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
stream_name = "order_1"
|
34
|
+
event_data = { event_type: "OrderCreated",
|
35
|
+
data: { data: "sample" },
|
36
|
+
event_id: "b2d506fd-409d-4ec7-b02f-c6d2295c7edd" }
|
37
|
+
client.append_to_stream(stream_name, event_data)
|
38
|
+
```
|
39
|
+
|
40
|
+
OR
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
EventData = Struct.new(:data, :event_type)
|
44
|
+
stream_name = "order_1"
|
45
|
+
event_data = EventData.new({ data: "sample" }, "OrderCreated")
|
46
|
+
client.append_to_stream(stream_name, event_data)
|
47
|
+
```
|
48
|
+
|
49
|
+
Creating a single event with optimistic locking:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
stream_name = "order_1"
|
53
|
+
event_data = { event_type: "OrderCreated", data: { data: "sample" }}
|
54
|
+
expected_version = 1
|
55
|
+
client.append_to_stream(stream_name, event_data, expected_version)
|
56
|
+
```
|
57
|
+
|
58
|
+
#### Deleting stream
|
59
|
+
|
60
|
+
The soft delete of single stream:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
stream_name = "order_1"
|
64
|
+
client.delete_stream("stream_name")
|
65
|
+
```
|
66
|
+
|
67
|
+
The hard delete of single stream:
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
stream_name = "order_1"
|
71
|
+
hard_delete = true
|
72
|
+
client.delete_stream("stream_name", hard_delete)
|
73
|
+
```
|
74
|
+
|
75
|
+
The soft delete cause that you will be allowed to recreate the stream by creating new event. If you recreate soft deleted stream all events are lost.
|
76
|
+
After an hard delete any try to load the stream or create event will result in a 410 response.
|
77
|
+
|
78
|
+
#### Reading stream's event forward
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
stream_name = "order_1"
|
82
|
+
start = 21
|
83
|
+
count = 40
|
84
|
+
client.read_events_forward(stream_name, start, count)
|
85
|
+
```
|
86
|
+
|
87
|
+
If you call following method to get the newest entries and no data is available the server wait some specified period of time.
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
stream_name = "order_1"
|
91
|
+
start = 21
|
92
|
+
count = 40
|
93
|
+
pool_time = 15
|
94
|
+
client.read_events_forward(stream_name, start, count, poll_time)
|
95
|
+
```
|
96
|
+
|
97
|
+
#### Reading stream's event backward
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
stream_name = "order_1"
|
101
|
+
start = 21
|
102
|
+
count = 40
|
103
|
+
client.read_events_backward(stream_name, start, count)
|
104
|
+
```
|
105
|
+
|
106
|
+
#### Reading all stream's event forward
|
107
|
+
|
108
|
+
This method allows us to load all stream's events ascending.
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
stream_name = "order_1"
|
112
|
+
client.read_all_events_forward(stream_name)
|
113
|
+
```
|
114
|
+
|
115
|
+
#### Reading all stream's event backward
|
116
|
+
|
117
|
+
This method allows us to load all stream's events descending.
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
stream_name = "order_1"
|
121
|
+
client.read_all_events_backward(stream_name)
|
122
|
+
```
|
123
|
+
|
124
|
+
## Supported version's of Event Store
|
125
|
+
|
126
|
+
To take advantage of all the functionality offered by our gem the minimum recommended version of Event Store is **2.1**
|
127
|
+
|
128
|
+
## Contributing
|
129
|
+
|
130
|
+
1. Fork it ( https://github.com/[my-github-username]/http_eventstore/fork )
|
131
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
132
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
133
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
134
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'http_eventstore'
|
7
|
+
spec.version = '0.1.0'
|
8
|
+
spec.authors = ['Arkency']
|
9
|
+
spec.email = ['andrzejkrzywda@gmail.com']
|
10
|
+
|
11
|
+
spec.summary = %q{HttpEventstore is a HTTP connector to the Greg's Event Store.}
|
12
|
+
spec.description = %q{HttpEventstore is a HTTP connector to the Greg's Event Store.}
|
13
|
+
spec.homepage = "https://github.com/arkency/http_eventstore"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
16
|
+
spec.bindir = 'exe'
|
17
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
|
+
spec.require_paths = ['lib']
|
19
|
+
|
20
|
+
spec.add_development_dependency 'bundler', '~> 1.8'
|
21
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
22
|
+
spec.add_development_dependency 'rspec'
|
23
|
+
spec.add_development_dependency 'pry'
|
24
|
+
|
25
|
+
spec.add_dependency 'faraday'
|
26
|
+
spec.add_dependency 'faraday_middleware'
|
27
|
+
spec.add_dependency 'json'
|
28
|
+
spec.add_dependency 'hashie'
|
29
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module HttpEventstore
|
2
|
+
module Actions
|
3
|
+
class AppendEventToStream
|
4
|
+
|
5
|
+
def initialize(client)
|
6
|
+
@client = client
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(stream_name, event_data, expected_version = nil)
|
10
|
+
event_data = OpenStruct.new(event_data) if event_data.is_a?(Hash)
|
11
|
+
event = create_event(event_data)
|
12
|
+
raise IncorrectStreamData if event.validate || stream_name_incorrect?(stream_name)
|
13
|
+
create_event_in_es(stream_name, event, expected_version)
|
14
|
+
rescue ClientError => e
|
15
|
+
raise WrongExpectedEventNumber if e.code == 400
|
16
|
+
raise StreamAlreadyDeleted if e.code == 410
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
attr_reader :client
|
21
|
+
|
22
|
+
def create_event(event_data)
|
23
|
+
type = event_data.event_type
|
24
|
+
data = event_data.data
|
25
|
+
event_id = event_data.event_id if event_data.respond_to?(:event_id)
|
26
|
+
Event.new(type, data, event_id)
|
27
|
+
end
|
28
|
+
|
29
|
+
def create_event_in_es(stream_name, event, expected_version)
|
30
|
+
client.append_to_stream(stream_name, event, expected_version)
|
31
|
+
end
|
32
|
+
|
33
|
+
def stream_name_incorrect?(stream_name)
|
34
|
+
stream_name.nil? || stream_name.empty?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module HttpEventstore
|
2
|
+
module Actions
|
3
|
+
class DeleteStream
|
4
|
+
|
5
|
+
def initialize(client)
|
6
|
+
@client = client
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(stream_name, hard_delete)
|
10
|
+
raise IncorrectStreamData if stream_name.nil? || stream_name.empty?
|
11
|
+
delete_stream(stream_name, hard_delete)
|
12
|
+
rescue ClientError => e
|
13
|
+
raise StreamAlreadyDeleted
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
attr_reader :client
|
18
|
+
|
19
|
+
def delete_stream(stream_name, hard_delete)
|
20
|
+
client.delete_stream(stream_name, hard_delete)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module HttpEventstore
|
2
|
+
module Actions
|
3
|
+
class ReadAllStreamEvents
|
4
|
+
|
5
|
+
def initialize(client)
|
6
|
+
@client = client
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(stream_name)
|
10
|
+
raise IncorrectStreamData if stream_name.nil? || stream_name.empty?
|
11
|
+
entries = get_all_stream_entries(stream_name)
|
12
|
+
return_events(entries)
|
13
|
+
rescue ClientError => e
|
14
|
+
raise StreamAlreadyDeleted if e.code == 410
|
15
|
+
raise StreamNotFound if e.code == 404
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
attr_reader :client
|
20
|
+
|
21
|
+
def get_all_stream_entries(stream_name, start_point = nil, entries = [])
|
22
|
+
stream_data = get_stream_batch(stream_name, start_point)
|
23
|
+
entries = append_entries(entries, stream_data['entries'])
|
24
|
+
start_point = get_next_start_point(stream_data['links'])
|
25
|
+
return entries if start_point.nil?
|
26
|
+
get_all_stream_entries(stream_name, start_point, entries)
|
27
|
+
end
|
28
|
+
|
29
|
+
def return_events(entries)
|
30
|
+
Helpers::ParseEntries.new.call(entries)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module HttpEventstore
|
2
|
+
module Actions
|
3
|
+
class ReadAllStreamEventsBackward < ReadAllStreamEvents
|
4
|
+
|
5
|
+
def initialize(client, page_size)
|
6
|
+
super(client)
|
7
|
+
@start_point = :head
|
8
|
+
@count = page_size
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
attr_reader :start_point, :count
|
13
|
+
|
14
|
+
def append_entries(entries, batch)
|
15
|
+
entries + batch
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_stream_batch(stream_name, start)
|
19
|
+
if start.nil?
|
20
|
+
read_stream_backward(stream_name, start_point, count)
|
21
|
+
else
|
22
|
+
read_stream_by_url(start)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def read_stream_backward(stream_name, next_id, count)
|
27
|
+
client.read_stream_backward(stream_name, next_id, count)
|
28
|
+
end
|
29
|
+
|
30
|
+
def read_stream_by_url(uri)
|
31
|
+
client.read_stream_page(uri)
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_next_start_point(links)
|
35
|
+
link = links.detect { |link| link['relation'] == 'next' }
|
36
|
+
unless link.nil?
|
37
|
+
link['uri'].slice! client.endpoint.url
|
38
|
+
link['uri']
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module HttpEventstore
|
2
|
+
module Actions
|
3
|
+
class ReadAllStreamEventsForward < ReadAllStreamEvents
|
4
|
+
|
5
|
+
def initialize(client, page_size)
|
6
|
+
super(client)
|
7
|
+
@start_point = 0
|
8
|
+
@count = page_size
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
attr_reader :start_point, :count
|
13
|
+
|
14
|
+
def append_entries(entries, batch)
|
15
|
+
entries + batch.reverse!
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_stream_batch(stream_name, start)
|
19
|
+
if start.nil?
|
20
|
+
read_stream_forward(stream_name, start_point, count)
|
21
|
+
else
|
22
|
+
read_stream_by_url(start)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def read_stream_forward(stream_name, next_id, count)
|
27
|
+
client.read_stream_forward(stream_name, next_id, count)
|
28
|
+
end
|
29
|
+
|
30
|
+
def read_stream_by_url(uri)
|
31
|
+
client.read_stream_page(uri)
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_next_start_point(links)
|
35
|
+
link = links.detect { |link| link['relation'] == 'previous' }
|
36
|
+
unless link.nil?
|
37
|
+
link['uri'].slice! client.endpoint.url
|
38
|
+
link['uri']
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module HttpEventstore
|
2
|
+
module Actions
|
3
|
+
class ReadStreamEventsBackward
|
4
|
+
|
5
|
+
def initialize(client)
|
6
|
+
@client = client
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(stream_name, start, count)
|
10
|
+
response = get_stream_batch(stream_name, start, count)
|
11
|
+
return_events(response['entries'])
|
12
|
+
rescue ClientError => e
|
13
|
+
raise StreamAlreadyDeleted if e.code == 410
|
14
|
+
raise StreamNotFound if e.code == 404
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
attr_reader :client
|
19
|
+
|
20
|
+
def get_stream_batch(stream_name, start, count)
|
21
|
+
client.read_stream_backward(stream_name, start, count)
|
22
|
+
end
|
23
|
+
|
24
|
+
def return_events(entries)
|
25
|
+
Helpers::ParseEntries.new.call(entries)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module HttpEventstore
|
2
|
+
module Actions
|
3
|
+
class ReadStreamEventsForward
|
4
|
+
|
5
|
+
def initialize(client)
|
6
|
+
@client = client
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(stream_name, start, count, pool)
|
10
|
+
response = get_stream_batch(stream_name, start, count, pool)
|
11
|
+
return_events(response['entries'])
|
12
|
+
rescue ClientError => e
|
13
|
+
raise StreamAlreadyDeleted if e.code == 410
|
14
|
+
raise StreamNotFound if e.code == 404
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
attr_reader :client
|
19
|
+
|
20
|
+
def get_stream_batch(stream_name, start, count, pool)
|
21
|
+
client.read_stream_forward(stream_name, start, count, pool)
|
22
|
+
end
|
23
|
+
|
24
|
+
def return_events(entries)
|
25
|
+
Helpers::ParseEntries.new.call(entries)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module HttpEventstore
|
2
|
+
module Api
|
3
|
+
class Client
|
4
|
+
|
5
|
+
def initialize(endpoint, port, page_size)
|
6
|
+
@endpoint = Endpoint.new(endpoint, port)
|
7
|
+
@page_size = page_size
|
8
|
+
end
|
9
|
+
attr_reader :endpoint, :page_size
|
10
|
+
|
11
|
+
def append_to_stream(stream_name, event, expected_version = nil)
|
12
|
+
headers = {"ES-EventType" => event.type, "ES-EventId" => event.event_id, "ES-ExpectedVersion" => "#{expected_version}"}.reject { |key, val| val.empty? }
|
13
|
+
make_request(:post, "/streams/#{stream_name}", event.data, headers)
|
14
|
+
end
|
15
|
+
|
16
|
+
def delete_stream(stream_name, hard_delete)
|
17
|
+
headers = {"ES-HardDelete" => "#{hard_delete}"}
|
18
|
+
make_request(:delete, "/streams/#{stream_name}", {}, headers)
|
19
|
+
end
|
20
|
+
|
21
|
+
def read_stream_backward(stream_name, start, count)
|
22
|
+
make_request(:get, "/streams/#{stream_name}/#{start}/backward/#{count}")
|
23
|
+
end
|
24
|
+
|
25
|
+
def read_stream_forward(stream_name, start, count, long_pool = 0)
|
26
|
+
headers = long_pool > 0 ? {"ES-LongPoll" => "#{long_pool}"} : {}
|
27
|
+
make_request(:get, "/streams/#{stream_name}/#{start}/forward/#{count}", {}, headers)
|
28
|
+
end
|
29
|
+
|
30
|
+
def read_stream_page(uri)
|
31
|
+
make_request(:get, uri)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def make_request(method, path, body={}, headers={})
|
37
|
+
connection.send(method, path) do |req|
|
38
|
+
req.headers = req.headers.merge(headers)
|
39
|
+
req.body = body.to_json
|
40
|
+
req.params['embed'] = 'body' if method == :get
|
41
|
+
end.body
|
42
|
+
end
|
43
|
+
|
44
|
+
def connection
|
45
|
+
@connection ||= Api::Connection.new(endpoint).call
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module HttpEventstore
|
2
|
+
module Api
|
3
|
+
class Connection
|
4
|
+
APP_JSON = 'application/json'.freeze
|
5
|
+
|
6
|
+
def initialize(endpoint)
|
7
|
+
@endpoint = endpoint
|
8
|
+
end
|
9
|
+
|
10
|
+
def call
|
11
|
+
Faraday.new(
|
12
|
+
url: endpoint.url,
|
13
|
+
headers: {
|
14
|
+
accept: APP_JSON,
|
15
|
+
content_type: APP_JSON
|
16
|
+
}
|
17
|
+
) do |builder|
|
18
|
+
builder.adapter Faraday.default_adapter
|
19
|
+
builder.response :json, content_type: APP_JSON
|
20
|
+
builder.response :mashify
|
21
|
+
builder.use ErrorsHandler
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
attr_reader :endpoint
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday_middleware'
|
3
|
+
|
4
|
+
module HttpEventstore
|
5
|
+
module Api
|
6
|
+
class ErrorsHandler < Faraday::Response::Middleware
|
7
|
+
|
8
|
+
def on_complete(env)
|
9
|
+
code = env[:status]
|
10
|
+
case code
|
11
|
+
when (400..499)
|
12
|
+
raise ClientError.new(code)
|
13
|
+
when (500..599)
|
14
|
+
raise ServerError.new(code)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module HttpEventstore
|
2
|
+
class Connection
|
3
|
+
attr_accessor :endpoint, :port, :page_size
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
setup_defaults
|
7
|
+
yield(self) if block_given?
|
8
|
+
end
|
9
|
+
|
10
|
+
def append_to_stream(stream_name, event_data, expected_version = nil)
|
11
|
+
Actions::AppendEventToStream.new(client).call(stream_name, event_data, expected_version)
|
12
|
+
end
|
13
|
+
|
14
|
+
def delete_stream(stream_name, hard_delete = false)
|
15
|
+
Actions::DeleteStream.new(client).call(stream_name, hard_delete)
|
16
|
+
end
|
17
|
+
|
18
|
+
def read_events_forward(stream_name, start, count, pool = 0)
|
19
|
+
Actions::ReadStreamEventsForward.new(client).call(stream_name, start, count, pool)
|
20
|
+
end
|
21
|
+
|
22
|
+
def read_events_backward(stream_name, start, count)
|
23
|
+
Actions::ReadStreamEventsBackward.new(client).call(stream_name, start, count)
|
24
|
+
end
|
25
|
+
|
26
|
+
def read_all_events_forward(stream_name)
|
27
|
+
Actions::ReadAllStreamEventsForward.new(client, page_size).call(stream_name)
|
28
|
+
end
|
29
|
+
|
30
|
+
def read_all_events_backward(stream_name)
|
31
|
+
Actions::ReadAllStreamEventsBackward.new(client, page_size).call(stream_name)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def client
|
37
|
+
@client ||= Api::Client.new(endpoint, port, page_size)
|
38
|
+
end
|
39
|
+
|
40
|
+
def setup_defaults
|
41
|
+
@endpoint = 'localhost'
|
42
|
+
@port = 2113
|
43
|
+
@page_size = 20
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module HttpEventstore
|
2
|
+
class ClientError < StandardError
|
3
|
+
attr_accessor :code
|
4
|
+
def initialize(code)
|
5
|
+
@code = code
|
6
|
+
super()
|
7
|
+
end
|
8
|
+
end
|
9
|
+
class ServerError < StandardError
|
10
|
+
attr_accessor :code
|
11
|
+
def initialize(code)
|
12
|
+
@code = code
|
13
|
+
super()
|
14
|
+
end
|
15
|
+
end
|
16
|
+
IncorrectStreamData = Class.new(StandardError)
|
17
|
+
WrongExpectedEventNumber = Class.new(StandardError)
|
18
|
+
StreamAlreadyDeleted = Class.new(StandardError)
|
19
|
+
StreamNotFound = Class.new(StandardError)
|
20
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class Event < Struct.new(:type, :data, :event_id, :id)
|
2
|
+
def initialize(type, data, event_id = nil, id = nil)
|
3
|
+
event_id = SecureRandom.uuid if event_id.nil?
|
4
|
+
super
|
5
|
+
end
|
6
|
+
|
7
|
+
def validate
|
8
|
+
[self.event_id, self.type, self.data].any? { |var| var.nil? || var.empty? }
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_json(options)
|
12
|
+
self.to_h.to_json
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module HttpEventstore
|
2
|
+
module Helpers
|
3
|
+
class ParseEntries
|
4
|
+
|
5
|
+
def call(entries)
|
6
|
+
entries.collect do |entry|
|
7
|
+
create_event(entry)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def create_event(entry)
|
14
|
+
id = entry['positionEventNumber']
|
15
|
+
event_id = entry['eventId']
|
16
|
+
type = entry['eventType']
|
17
|
+
data = JSON.parse(entry['data'])
|
18
|
+
Event.new(type, data, event_id, id)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'http_eventstore/api/client'
|
2
|
+
require 'http_eventstore/api/connection'
|
3
|
+
require 'http_eventstore/api/errors_handler'
|
4
|
+
require 'http_eventstore/connection'
|
5
|
+
require 'http_eventstore/event'
|
6
|
+
require 'http_eventstore/errors'
|
7
|
+
require 'http_eventstore/endpoint'
|
8
|
+
require 'http_eventstore/helpers/parse_entries'
|
9
|
+
require 'http_eventstore/actions/append_event_to_stream'
|
10
|
+
require 'http_eventstore/actions/delete_stream'
|
11
|
+
require 'http_eventstore/actions/read_all_stream_events'
|
12
|
+
require 'http_eventstore/actions/read_all_stream_events_backward'
|
13
|
+
require 'http_eventstore/actions/read_all_stream_events_forward'
|
14
|
+
require 'http_eventstore/actions/read_stream_events_backward'
|
15
|
+
require 'http_eventstore/actions/read_stream_events_forward'
|
metadata
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: http_eventstore
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Arkency
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-03-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.8'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.8'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: faraday
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: faraday_middleware
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: json
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: hashie
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description: HttpEventstore is a HTTP connector to the Greg's Event Store.
|
126
|
+
email:
|
127
|
+
- andrzejkrzywda@gmail.com
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- ".gitignore"
|
133
|
+
- Gemfile
|
134
|
+
- README.md
|
135
|
+
- Rakefile
|
136
|
+
- http_eventstore.gemspec
|
137
|
+
- lib/http_eventstore.rb
|
138
|
+
- lib/http_eventstore/actions/append_event_to_stream.rb
|
139
|
+
- lib/http_eventstore/actions/delete_stream.rb
|
140
|
+
- lib/http_eventstore/actions/read_all_stream_events.rb
|
141
|
+
- lib/http_eventstore/actions/read_all_stream_events_backward.rb
|
142
|
+
- lib/http_eventstore/actions/read_all_stream_events_forward.rb
|
143
|
+
- lib/http_eventstore/actions/read_stream_events_backward.rb
|
144
|
+
- lib/http_eventstore/actions/read_stream_events_forward.rb
|
145
|
+
- lib/http_eventstore/api/client.rb
|
146
|
+
- lib/http_eventstore/api/connection.rb
|
147
|
+
- lib/http_eventstore/api/errors_handler.rb
|
148
|
+
- lib/http_eventstore/connection.rb
|
149
|
+
- lib/http_eventstore/endpoint.rb
|
150
|
+
- lib/http_eventstore/errors.rb
|
151
|
+
- lib/http_eventstore/event.rb
|
152
|
+
- lib/http_eventstore/helpers/parse_entries.rb
|
153
|
+
homepage: https://github.com/arkency/http_eventstore
|
154
|
+
licenses: []
|
155
|
+
metadata: {}
|
156
|
+
post_install_message:
|
157
|
+
rdoc_options: []
|
158
|
+
require_paths:
|
159
|
+
- lib
|
160
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - ">="
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '0'
|
165
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
166
|
+
requirements:
|
167
|
+
- - ">="
|
168
|
+
- !ruby/object:Gem::Version
|
169
|
+
version: '0'
|
170
|
+
requirements: []
|
171
|
+
rubyforge_project:
|
172
|
+
rubygems_version: 2.4.6
|
173
|
+
signing_key:
|
174
|
+
specification_version: 4
|
175
|
+
summary: HttpEventstore is a HTTP connector to the Greg's Event Store.
|
176
|
+
test_files: []
|