diff --git a/lib/http_event_store/actions/append_event_to_stream.rb b/lib/http_event_store/actions/append_event_to_stream.rb index 22bc1ff..6e34c2f 100644 --- a/lib/http_event_store/actions/append_event_to_stream.rb +++ b/lib/http_event_store/actions/append_event_to_stream.rb @@ -28,8 +28,9 @@ def call(stream_name, event_data, expected_version = nil) def create_event(event_data) type = event_data.event_type data = event_data.data + metadata = event_data.metadata if event_data.respond_to?(:metadata) event_id = event_data.event_id if event_data.respond_to?(:event_id) - Event.new(type, data, event_id) + Event.new(type, data, metadata, event_id) end def create_event_in_es(stream_name, event, expected_version) diff --git a/lib/http_event_store/api/client.rb b/lib/http_event_store/api/client.rb index 96465df..2fdc0f9 100644 --- a/lib/http_event_store/api/client.rb +++ b/lib/http_event_store/api/client.rb @@ -20,7 +20,8 @@ def append_to_stream(stream_name, event_data, expected_version = nil) { eventId: event.event_id, eventType: event.type, - data: event.data + data: event.data, + metadata: event.metadata } end diff --git a/lib/http_event_store/event.rb b/lib/http_event_store/event.rb index c0ab3b4..3986c47 100644 --- a/lib/http_event_store/event.rb +++ b/lib/http_event_store/event.rb @@ -1,7 +1,7 @@ require 'securerandom' -class Event < Struct.new(:type, :data, :source_event_uri, :event_id, :id, :position, :stream_name, :created_time) - def initialize(type, data, source_event_uri=nil, event_id=nil, id=nil, position=nil, stream_name=nil, created_time=nil) +class Event < Struct.new(:type, :data, :metadata, :source_event_uri, :event_id, :id, :position, :stream_name, :created_time) + def initialize(type, data, metadata=nil, source_event_uri=nil, event_id=nil, id=nil, position=nil, stream_name=nil, created_time=nil) event_id = SecureRandom.uuid if event_id.nil? super end diff --git a/lib/http_event_store/helpers/parse_entries.rb b/lib/http_event_store/helpers/parse_entries.rb index aa6d80e..fb035d4 100644 --- a/lib/http_event_store/helpers/parse_entries.rb +++ b/lib/http_event_store/helpers/parse_entries.rb @@ -19,12 +19,13 @@ def create_event(entry) event_id = entry['eventId'] type = entry['eventType'] source_event_uri = entry['id'] - data = JSON.parse(entry['data']) + data = !entry['data'].nil? && !entry['data'].empty? ? JSON.parse(entry['data']) : {} stream_name = entry['streamId'] position = entry['positionEventNumber'] created_time = entry['updated'] ? Time.parse(entry['updated']) : nil + metadata = !entry['metadata'].nil? && !entry['metadata'].empty? ? JSON.parse(entry['metadata']) : {} - Event.new(type, data, source_event_uri, event_id, id, position, stream_name, created_time) + Event.new(type, data, metadata, source_event_uri, event_id, id, position, stream_name, created_time) end end end diff --git a/spec/api_client_spec.rb b/spec/api_client_spec.rb index 7d6b612..fcd4ae7 100644 --- a/spec/api_client_spec.rb +++ b/spec/api_client_spec.rb @@ -10,10 +10,10 @@ module Api describe '#append_to_stream' do it "should handle one event" do - event = Event.new('event_type', { data: 1 }) - expect(client).to receive(:make_request).with(:post, '/streams/streamname', [{eventId: event.event_id, eventType: event.type, data: event.data}], {'accept' => 'application/vnd.eventstore.events+json', 'content-type' => 'application/vnd.eventstore.events+json'}) + event = Event.new('event_type', { data: 1}) + expect(client).to receive(:make_request).with(:post, '/streams/streamname', [{eventId: event.event_id, eventType: event.type, data: event.data, metadata: nil}], {'accept' => 'application/vnd.eventstore.events+json', 'content-type' => 'application/vnd.eventstore.events+json'}) client.append_to_stream(stream_name, event) - expect(client).to receive(:make_request).with(:post, '/streams/streamname', [{eventId: event.event_id, eventType: event.type, data: event.data}], {'ES-ExpectedVersion' => '1', 'accept' => 'application/vnd.eventstore.events+json', 'content-type' => 'application/vnd.eventstore.events+json'}) + expect(client).to receive(:make_request).with(:post, '/streams/streamname', [{eventId: event.event_id, eventType: event.type, data: event.data, metadata: nil}], {'ES-ExpectedVersion' => '1', 'accept' => 'application/vnd.eventstore.events+json', 'content-type' => 'application/vnd.eventstore.events+json'}) client.append_to_stream(stream_name, event, 1) end @@ -22,9 +22,18 @@ module Api event2 = Event.new('event-type2', {data: 2}) events = [event1, event2] - expect(client).to receive(:make_request).with(:post, '/streams/streamname', [{eventId: event1.event_id, eventType: event1.type, data: event1.data},{eventId: event2.event_id, eventType: event2.type, data: event2.data}], {'ES-ExpectedVersion' => '1', 'accept' => 'application/vnd.eventstore.events+json', 'content-type' => 'application/vnd.eventstore.events+json'}) + expect(client).to receive(:make_request).with(:post, '/streams/streamname', [{eventId: event1.event_id, eventType: event1.type, data: event1.data, metadata: nil},{eventId: event2.event_id, eventType: event2.type, data: event2.data, metadata: nil}], {'ES-ExpectedVersion' => '1', 'accept' => 'application/vnd.eventstore.events+json', 'content-type' => 'application/vnd.eventstore.events+json'}) client.append_to_stream(stream_name, events, 1) end + + + it "should handle one event with metadata" do + event = Event.new('event_type', { data: 1 }, { metadata: 2}) + expect(client).to receive(:make_request).with(:post, '/streams/streamname', [{eventId: event.event_id, eventType: event.type, data: event.data, metadata: { metadata: 2}}], {'accept' => 'application/vnd.eventstore.events+json', 'content-type' => 'application/vnd.eventstore.events+json'}) + client.append_to_stream(stream_name, event) + expect(client).to receive(:make_request).with(:post, '/streams/streamname', [{eventId: event.event_id, eventType: event.type, data: event.data, metadata: { metadata: 2}}], {'ES-ExpectedVersion' => '1', 'accept' => 'application/vnd.eventstore.events+json', 'content-type' => 'application/vnd.eventstore.events+json'}) + client.append_to_stream(stream_name, event, 1) + end end specify '#delete_stream' do diff --git a/spec/event_store_connection_spec.rb b/spec/event_store_connection_spec.rb index 47fceae..bea3ba7 100644 --- a/spec/event_store_connection_spec.rb +++ b/spec/event_store_connection_spec.rb @@ -33,6 +33,11 @@ module HttpEventStore expect(client.event_store[stream_name].length).to eq 1 end + specify 'can create new event with metadata in stream from hash' do + create_event_in_es({ event_type: 'event_type', data: 'event_data', metadata: "event_metadata" }) + expect(client.event_store[stream_name][0]["metadata"]).to eq "\"event_metadata\"" + end + specify 'can create new event in stream from array' do create_events_in_es([{ event_type: 'event_type', data: 'event_data' }]) expect(client.event_store[stream_name].length).to eq 1 diff --git a/spec/in_memory_es.rb b/spec/in_memory_es.rb index 3d58f8c..589eee4 100644 --- a/spec/in_memory_es.rb +++ b/spec/in_memory_es.rb @@ -18,7 +18,7 @@ def append_to_stream(stream_name, event_data, expected_version = nil) event_data.each do |event| id = event_store[stream_name].length - event_store[stream_name].unshift({'eventId' => event.event_id, 'data' => event.data.to_json, 'eventType' => event.type, 'positionEventNumber' => id}) + event_store[stream_name].unshift({'eventId' => event.event_id, 'data' => event.data.to_json, 'eventType' => event.type, 'positionEventNumber' => id, 'metadata' => event.metadata.to_json}) end end diff --git a/spec/parse_entries_spec.rb b/spec/parse_entries_spec.rb index c4b059b..75a7513 100644 --- a/spec/parse_entries_spec.rb +++ b/spec/parse_entries_spec.rb @@ -11,6 +11,7 @@ module Helpers expect(events.length).to eq 1 expect(events[0].type).to eq "entryCreated" expect(events[0].data).to eq({"a" => "1"}) + expect(events[0].metadata).to eq({"a" => "1"}) expect(events[0].event_id).to eq "fbf4a1a1-b4a3-4dfe-a01f-6668634e16e4" expect(events[0].id).to eq 47 expect(events[0].position).to eq 51 @@ -48,6 +49,7 @@ def entry "eventId" => "fbf4a1a1-b4a3-4dfe-a01f-6668634e16e4", "eventType" => "entryCreated", "data" => "{\n \"a\": \"1\"\n}", + "metadata" => "{\n \"a\": \"1\"\n}", "eventNumber" => 47, "positionEventNumber" => 51, "streamId" => 'entries',