event_sourcery-postgres 0.5.0 → 0.6.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 +4 -4
- data/CHANGELOG.md +7 -1
- data/README.md +0 -1
- data/lib/event_sourcery/postgres/config.rb +19 -17
- data/lib/event_sourcery/postgres/event_store.rb +9 -9
- data/lib/event_sourcery/postgres/optimised_event_poll_waiter.rb +3 -3
- data/lib/event_sourcery/postgres/projector.rb +1 -2
- data/lib/event_sourcery/postgres/schema.rb +1 -1
- data/lib/event_sourcery/postgres/table_owner.rb +2 -2
- data/lib/event_sourcery/postgres/tracker.rb +11 -11
- data/lib/event_sourcery/postgres/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c2860efca21f5ae2a7a8ae316ea70db1fcb1aa1e
|
4
|
+
data.tar.gz: 56fe6bc5b9233ffc8795ba6b37cff8763bf1b166
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b1ef120a33fa76da1698f68a063c07293d82ff1a8310682dbf7be812156216c18061ad7fb5706d412d03f60a67dc1dbd33d05637c12891018fb2cdd7cfbbd42
|
7
|
+
data.tar.gz: 9310dbd856abac2ffe24f9a6b78f1fc3b6baf23ecfdf087fa5e2349210c343a1f4533c876df9fb5e21107cd5e7bf5fd197fe8cc8fbe4a5eea56ce96aa67c7f37
|
data/CHANGELOG.md
CHANGED
@@ -4,8 +4,14 @@ All notable changes to this project will be documented in this file.
|
|
4
4
|
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
5
5
|
and this project adheres to [Semantic Versioning](http://semver.org/).
|
6
6
|
|
7
|
-
## [
|
7
|
+
## [0.6.0] - 2018-1-2
|
8
|
+
### Changed
|
9
|
+
|
10
|
+
- Only send info log after processing a group of events
|
8
11
|
|
12
|
+
### Removed
|
13
|
+
- Remove `processes_events` and `projects_events` as these have been [removed
|
14
|
+
in event_sourcery](https://github.com/envato/event_sourcery/pull/161).
|
9
15
|
|
10
16
|
## [0.5.0] - 2017-7-27
|
11
17
|
- First Version of YARD documentation.
|
data/README.md
CHANGED
@@ -22,7 +22,6 @@ gem 'event_sourcery-postgres'
|
|
22
22
|
EventSourcery::Postgres.configure do |config|
|
23
23
|
config.event_store_database = Sequel.connect(...)
|
24
24
|
config.projections_database = Sequel.connect(...)
|
25
|
-
config.use_optimistic_concurrency = true
|
26
25
|
config.write_events_function_name = 'writeEvents'
|
27
26
|
config.events_table_name = :events
|
28
27
|
config.aggregates_table_name = :aggregates
|
@@ -1,19 +1,21 @@
|
|
1
1
|
module EventSourcery
|
2
2
|
module Postgres
|
3
3
|
class Config
|
4
|
-
attr_accessor :
|
5
|
-
:lock_table_to_guarantee_linear_sequence_id_growth,
|
4
|
+
attr_accessor :lock_table_to_guarantee_linear_sequence_id_growth,
|
6
5
|
:write_events_function_name,
|
7
6
|
:events_table_name,
|
8
7
|
:aggregates_table_name,
|
9
8
|
:tracker_table_name,
|
10
9
|
:callback_interval_if_no_new_events,
|
11
10
|
:auto_create_projector_tracker,
|
12
|
-
:event_tracker
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
:event_tracker
|
12
|
+
|
13
|
+
attr_writer :event_store,
|
14
|
+
:event_source,
|
15
|
+
:event_sink
|
16
|
+
|
17
|
+
attr_reader :event_store_database,
|
18
|
+
:projections_database
|
17
19
|
|
18
20
|
def initialize
|
19
21
|
@lock_table_to_guarantee_linear_sequence_id_growth = true
|
@@ -38,25 +40,25 @@ module EventSourcery
|
|
38
40
|
@event_sink ||= ::EventSourcery::EventStore::EventSink.new(event_store)
|
39
41
|
end
|
40
42
|
|
41
|
-
def event_store_database=(
|
42
|
-
setup_connection(
|
43
|
+
def event_store_database=(db_connection)
|
44
|
+
setup_connection(db_connection)
|
43
45
|
|
44
|
-
@event_store_database =
|
46
|
+
@event_store_database = db_connection
|
45
47
|
end
|
46
48
|
|
47
|
-
def projections_database=(
|
48
|
-
setup_connection(
|
49
|
+
def projections_database=(db_connection)
|
50
|
+
setup_connection(db_connection)
|
49
51
|
|
50
|
-
@projections_database =
|
51
|
-
@event_tracker = Postgres::Tracker.new(
|
52
|
+
@projections_database = db_connection
|
53
|
+
@event_tracker = Postgres::Tracker.new(db_connection)
|
52
54
|
end
|
53
55
|
|
54
56
|
private
|
55
57
|
|
56
|
-
def setup_connection(
|
57
|
-
return unless
|
58
|
+
def setup_connection(db_connection)
|
59
|
+
return unless db_connection
|
58
60
|
|
59
|
-
|
61
|
+
db_connection.extension :pg_json
|
60
62
|
end
|
61
63
|
end
|
62
64
|
end
|
@@ -3,19 +3,19 @@ module EventSourcery
|
|
3
3
|
class EventStore
|
4
4
|
include EventSourcery::EventStore::EachByRange
|
5
5
|
|
6
|
-
def initialize(
|
6
|
+
def initialize(db_connection,
|
7
7
|
events_table_name: EventSourcery::Postgres.config.events_table_name,
|
8
8
|
lock_table: EventSourcery::Postgres.config.lock_table_to_guarantee_linear_sequence_id_growth,
|
9
9
|
write_events_function_name: EventSourcery::Postgres.config.write_events_function_name,
|
10
10
|
event_builder: EventSourcery.config.event_builder)
|
11
|
-
@
|
11
|
+
@db_connection = db_connection
|
12
12
|
@events_table_name = events_table_name
|
13
13
|
@write_events_function_name = write_events_function_name
|
14
14
|
@lock_table = lock_table
|
15
15
|
@event_builder = event_builder
|
16
16
|
end
|
17
17
|
|
18
|
-
# Like water flowing into a sink
|
18
|
+
# Like water flowing into a sink eventually it will go down the drain
|
19
19
|
# into the goodness of the plumbing system.
|
20
20
|
# So to will the given events you put in this 'sink'. Except the plumbing
|
21
21
|
# system is the data base events table.
|
@@ -31,7 +31,7 @@ module EventSourcery
|
|
31
31
|
aggregate_ids = events.map(&:aggregate_id).uniq
|
32
32
|
raise AtomicWriteToMultipleAggregatesNotSupported unless aggregate_ids.count == 1
|
33
33
|
sql = write_events_sql(aggregate_ids.first, events, expected_version)
|
34
|
-
@
|
34
|
+
@db_connection.run(sql)
|
35
35
|
log_events_saved(events)
|
36
36
|
true
|
37
37
|
rescue Sequel::DatabaseError => e
|
@@ -43,10 +43,10 @@ module EventSourcery
|
|
43
43
|
end
|
44
44
|
|
45
45
|
# Get the next set of events from the given event id. You can
|
46
|
-
# specify event
|
46
|
+
# specify event types and a limit.
|
47
47
|
# Default limit is 1000 and the default event types will be all.
|
48
48
|
#
|
49
|
-
# @param id the event id to get next
|
49
|
+
# @param id the event id to get next events from
|
50
50
|
# @param event_types the event types to filter, default nil = all
|
51
51
|
# @param limit the limit to the results, default 1000
|
52
52
|
#
|
@@ -94,7 +94,7 @@ module EventSourcery
|
|
94
94
|
# @param after_listen the after listen call back block. default nil.
|
95
95
|
# @param subscription_master the subscription master block
|
96
96
|
def subscribe(from_id:, event_types: nil, after_listen: nil, subscription_master:, &block)
|
97
|
-
poll_waiter = OptimisedEventPollWaiter.new(
|
97
|
+
poll_waiter = OptimisedEventPollWaiter.new(db_connection: @db_connection, after_listen: after_listen)
|
98
98
|
args = {
|
99
99
|
poll_waiter: poll_waiter,
|
100
100
|
event_store: self,
|
@@ -110,7 +110,7 @@ module EventSourcery
|
|
110
110
|
private
|
111
111
|
|
112
112
|
def events_table
|
113
|
-
@
|
113
|
+
@db_connection[@events_table_name]
|
114
114
|
end
|
115
115
|
|
116
116
|
def build_event(data)
|
@@ -159,7 +159,7 @@ module EventSourcery
|
|
159
159
|
else
|
160
160
|
value
|
161
161
|
end
|
162
|
-
@
|
162
|
+
@db_connection.literal(wrapped_value)
|
163
163
|
end
|
164
164
|
|
165
165
|
def log_events_saved(events)
|
@@ -4,8 +4,8 @@ module EventSourcery
|
|
4
4
|
class OptimisedEventPollWaiter
|
5
5
|
ListenThreadDied = Class.new(StandardError)
|
6
6
|
|
7
|
-
def initialize(
|
8
|
-
@
|
7
|
+
def initialize(db_connection:, timeout: 30, after_listen: proc {})
|
8
|
+
@db_connection = db_connection
|
9
9
|
@timeout = timeout
|
10
10
|
@events_queue = QueueWithIntervalCallback.new
|
11
11
|
@after_listen = after_listen
|
@@ -65,7 +65,7 @@ module EventSourcery
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def listen_for_new_events(loop: true, after_listen: nil, timeout: 30)
|
68
|
-
@
|
68
|
+
@db_connection.listen('new_event',
|
69
69
|
loop: loop,
|
70
70
|
after_listen: after_listen,
|
71
71
|
timeout: timeout) do |_channel, _pid, _payload|
|
@@ -10,7 +10,6 @@ module EventSourcery
|
|
10
10
|
|
11
11
|
class << self
|
12
12
|
alias_method :project, :process
|
13
|
-
alias_method :projects_events, :processes_events
|
14
13
|
alias_method :projector_name, :processor_name
|
15
14
|
end
|
16
15
|
end
|
@@ -33,8 +32,8 @@ module EventSourcery
|
|
33
32
|
tracker.processed_event(processor_name, event.id)
|
34
33
|
end
|
35
34
|
EventSourcery.logger.debug { "[#{processor_name}] Processed event: #{event.inspect}" }
|
36
|
-
EventSourcery.logger.info { "[#{processor_name}] Processed up to event id: #{events.last.id}" }
|
37
35
|
end
|
36
|
+
EventSourcery.logger.info { "[#{processor_name}] Processed up to event id: #{events.last.id}" }
|
38
37
|
end
|
39
38
|
end
|
40
39
|
end
|
@@ -58,7 +58,7 @@ module EventSourcery
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
# Create the 'create or update'
|
61
|
+
# Create the 'create or update' functions.
|
62
62
|
# Needs the database, table name, function name and aggregates table name.
|
63
63
|
# The defaults will be whats specified in config.
|
64
64
|
#
|
@@ -9,14 +9,14 @@ module EventSourcery
|
|
9
9
|
end
|
10
10
|
|
11
11
|
module ClassMethods
|
12
|
-
# Hash of the tables and
|
12
|
+
# Hash of the tables and their corresponding blocks.
|
13
13
|
#
|
14
14
|
# @return [Hash] hash keyed by table names and block values
|
15
15
|
def tables
|
16
16
|
@tables ||= {}
|
17
17
|
end
|
18
18
|
|
19
|
-
# For the
|
19
|
+
# For the given table name assign to give block as the value.
|
20
20
|
#
|
21
21
|
# @param name the name of the table
|
22
22
|
# @param block the block of code to assign for the table
|
@@ -3,19 +3,19 @@ module EventSourcery
|
|
3
3
|
# This will set up a persisted event id tracker for processors.
|
4
4
|
class Tracker
|
5
5
|
|
6
|
-
def initialize(
|
6
|
+
def initialize(db_connection = EventSourcery::Postgres.config.projections_database,
|
7
7
|
table_name: EventSourcery::Postgres.config.tracker_table_name,
|
8
8
|
obtain_processor_lock: true)
|
9
|
-
@
|
9
|
+
@db_connection = db_connection
|
10
10
|
@table_name = table_name.to_sym
|
11
11
|
@obtain_processor_lock = obtain_processor_lock
|
12
12
|
end
|
13
13
|
|
14
14
|
# Set up the given processor.
|
15
|
-
# This will create the projector tracker table if it does not
|
15
|
+
# This will create the projector tracker table if it does not exist.
|
16
16
|
# If given a processor_name it will then attempt to get a lock on the db.
|
17
17
|
#
|
18
|
-
# @param processor_name the name of the
|
18
|
+
# @param processor_name the name of the processor
|
19
19
|
def setup(processor_name = nil)
|
20
20
|
create_table_if_not_exists if EventSourcery::Postgres.config.auto_create_projector_tracker
|
21
21
|
|
@@ -34,7 +34,7 @@ module EventSourcery
|
|
34
34
|
# This will updated the tracker table to the given event id value
|
35
35
|
# for the given processor name.
|
36
36
|
#
|
37
|
-
# @param processor_name the name of the processor to
|
37
|
+
# @param processor_name the name of the processor to update
|
38
38
|
# @param event_id the event id number to update to
|
39
39
|
def processed_event(processor_name, event_id)
|
40
40
|
table.
|
@@ -44,13 +44,13 @@ module EventSourcery
|
|
44
44
|
end
|
45
45
|
|
46
46
|
# This allows you to process an event and update the tracker table in
|
47
|
-
# a single transaction. Will
|
47
|
+
# a single transaction. Will yield the given block first then update the
|
48
48
|
# the tracker table to the give event id for the given processor name.
|
49
49
|
#
|
50
50
|
# @param processor_name the name of the processor to update
|
51
51
|
# @param event_id the event id number to update to
|
52
52
|
def processing_event(processor_name, event_id)
|
53
|
-
@
|
53
|
+
@db_connection.transaction do
|
54
54
|
yield
|
55
55
|
processed_event(processor_name, event_id)
|
56
56
|
end
|
@@ -82,7 +82,7 @@ module EventSourcery
|
|
82
82
|
private
|
83
83
|
|
84
84
|
def obtain_global_lock_on_processor(processor_name)
|
85
|
-
lock_obtained = @
|
85
|
+
lock_obtained = @db_connection.fetch("select pg_try_advisory_lock(#{@track_entry_id})").to_a.first[:pg_try_advisory_lock]
|
86
86
|
if lock_obtained == false
|
87
87
|
raise UnableToLockProcessorError, "Unable to get a lock on #{processor_name} #{@track_entry_id}"
|
88
88
|
end
|
@@ -91,7 +91,7 @@ module EventSourcery
|
|
91
91
|
def create_table_if_not_exists
|
92
92
|
unless tracker_table_exists?
|
93
93
|
EventSourcery.logger.info { "Projector tracker missing - attempting to create 'projector_tracker' table" }
|
94
|
-
EventSourcery::Postgres::Schema.create_projector_tracker(db: @
|
94
|
+
EventSourcery::Postgres::Schema.create_projector_tracker(db: @db_connection, table_name: @table_name)
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
@@ -105,11 +105,11 @@ module EventSourcery
|
|
105
105
|
end
|
106
106
|
|
107
107
|
def table
|
108
|
-
@
|
108
|
+
@db_connection[@table_name]
|
109
109
|
end
|
110
110
|
|
111
111
|
def tracker_table_exists?
|
112
|
-
@
|
112
|
+
@db_connection.table_exists?(@table_name)
|
113
113
|
end
|
114
114
|
end
|
115
115
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: event_sourcery-postgres
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Envato
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|