event_sourcery-postgres 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e45ae5ad105bd165a2fb4b59be6032488ec925df
4
- data.tar.gz: c36491b6e980803520d2b3a900207500f694b500
3
+ metadata.gz: 54611962fa99a62b63f2a97d432614e43aa2b10e
4
+ data.tar.gz: d4b6413ce323e94e950fb1d3276eaebacdb6dedd
5
5
  SHA512:
6
- metadata.gz: a86c88d7db9e0368d3ddbea1b6b7ce869d8f3465dd1bce3990f0038edffcb5712da10d4182fd0ce46427b2e3aa08b67b7da6712d7aec0abd16f766741a492556
7
- data.tar.gz: 3f286cd47b3eb36e3b3e65929d6df0d51a1bc8762f1256d1b21c6f8041861fc8087bde5978989c7abb58d6f274add9dca368ca992105a12e5e7af6069e390dc7
6
+ metadata.gz: 55e76d3c6300f678ddfefe9c4dc9be6cd1fa365ace92ebce6cc6be432e2d19553cc9313da54923307fc264bb6b4582fc23022349dfc3e70df56261756a021c6d
7
+ data.tar.gz: 12e02831936b8fe0203ba1f0c7908a00fbff4e74308d5a879f22f0a02e311f1a2aac1b3b068df80ad81f68a4029b0b31436362a9a815d10cba32b290dfeb9f01
data/CHANGELOG.md CHANGED
@@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+
10
+ ## [0.5.0] - 2017-7-27
11
+ - First Version of YARD documentation.
12
+ - Fix Sequel deprecation by globally loading pg extensions
13
+
9
14
  ## [0.4.0] - 2017-6-21
10
15
  ### Changed
11
16
  - Reactors store the UUID of the event being processed in the `causation_id`
@@ -26,14 +31,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
26
31
  added to the `events` table and the `write_events` function has been
27
32
  altered. Event Sourcery apps will need to ensure these DB changes have
28
33
  been applied to use this version of Event Sourcery.
34
+ - The emit_events method now accepts typed events instead of symbols
35
+ - Remove dynamic emit events methods from reactors (e.g. emit_item_added)
29
36
 
30
37
  ## [0.2.0] - 2017-6-1
31
38
  ### Changed
32
39
  - Make `EventSourcery::Postgres::OptimisedEventPollWaiter#shutdown` private
33
40
  - Updated `EventSourcery::Postgres::OptimisedEventPollWaiter#poll` to ensure that `#shutdown!` is run when an error is raised
34
41
  or when the loop stops
35
- - Remove dynamic emit events methods from reactors (e.g. emit_item_added)
36
- - The emit_events method now accepts typed events instead of symbols
37
42
 
38
43
  ### Added
39
44
  - Configure projector tracker table name via `EventSourcery::Postgres.configure`
data/README.md CHANGED
@@ -91,11 +91,8 @@ To release a new version:
91
91
 
92
92
  1. Update the version number in `lib/event_sourcery/postgres/version.rb`
93
93
  2. Get this change onto master via the normal PR process
94
- 3. Run `gem_push=false be rake release`,
95
- this will create a git tag for the version,
96
- push tags up to GitHub, and package the code in a `.gem` file.
97
- 4. Manually upload the generated gem file (`pkg/event_sourcery-postgres-#{version}.gem`) to
98
- [rubygems.envato.com](https://rubygems.envato.com).
94
+ 3. Run `bundle exec rake release`, this will create a git tag for the
95
+ version, push tags up to GitHub, and upload the gem to rubygems.org.
99
96
 
100
97
  ## Contributing
101
98
 
@@ -1,6 +1,5 @@
1
1
  require 'sequel'
2
2
 
3
- Sequel.extension :pg_json
4
3
  Sequel.default_timezone = :utc
5
4
 
6
5
  require 'event_sourcery'
@@ -38,10 +38,26 @@ module EventSourcery
38
38
  @event_sink ||= ::EventSourcery::EventStore::EventSink.new(event_store)
39
39
  end
40
40
 
41
+ def event_store_database=(sequel_connection)
42
+ setup_connection(sequel_connection)
43
+
44
+ @event_store_database = sequel_connection
45
+ end
46
+
41
47
  def projections_database=(sequel_connection)
48
+ setup_connection(sequel_connection)
49
+
42
50
  @projections_database = sequel_connection
43
51
  @event_tracker = Postgres::Tracker.new(sequel_connection)
44
52
  end
53
+
54
+ private
55
+
56
+ def setup_connection(sequel_connection)
57
+ return unless sequel_connection
58
+
59
+ sequel_connection.extension :pg_json
60
+ end
45
61
  end
46
62
  end
47
63
  end
@@ -15,6 +15,17 @@ module EventSourcery
15
15
  @event_builder = event_builder
16
16
  end
17
17
 
18
+ # Like water flowing into a sink evenually it will go down the drain
19
+ # into the goodness of the plumbing system.
20
+ # So to will the given events you put in this 'sink'. Except the plumbing
21
+ # system is the data base events table.
22
+ # This can raise db connection errors.
23
+ #
24
+ # @param event_or_events the event or events to save
25
+ # @param expected_version the version to save with the event, default nil
26
+ #
27
+ # @raise [DatabaseError] if something goes wrong with the database
28
+ # @raise [ConcurrencyError] if there was a concurrency conflict
18
29
  def sink(event_or_events, expected_version: nil)
19
30
  events = Array(event_or_events)
20
31
  aggregate_ids = events.map(&:aggregate_id).uniq
@@ -31,6 +42,15 @@ module EventSourcery
31
42
  end
32
43
  end
33
44
 
45
+ # Get the next set of events from the given event id. You can
46
+ # specify event typs and a limit.
47
+ # Default limit is 1000 and the default event types will be all.
48
+ #
49
+ # @param id the event id to get next envents from
50
+ # @param event_types the event types to filter, default nil = all
51
+ # @param limit the limit to the results, default 1000
52
+ #
53
+ # @return [Array] array of found events
34
54
  def get_next_from(id, event_types: nil, limit: 1000)
35
55
  query = events_table.
36
56
  order(:id).
@@ -40,6 +60,11 @@ module EventSourcery
40
60
  query.map { |event_row| build_event(event_row) }
41
61
  end
42
62
 
63
+ # Get last event id for a given event types.
64
+ #
65
+ # @param event_types the type of event(s) to filter
66
+ #
67
+ # @return the latest event id
43
68
  def latest_event_id(event_types: nil)
44
69
  latest_event = events_table
45
70
  latest_event = latest_event.where(type: event_types) if event_types
@@ -51,12 +76,23 @@ module EventSourcery
51
76
  end
52
77
  end
53
78
 
79
+ # Get the events for a given aggregate id.
80
+ #
81
+ # @param aggregate_id the aggregate id to filter for
82
+ #
83
+ # @return [Array] of found events
54
84
  def get_events_for_aggregate_id(aggregate_id)
55
85
  events_table.where(aggregate_id: aggregate_id.to_str).order(:version).map do |event_hash|
56
86
  build_event(event_hash)
57
87
  end
58
88
  end
59
89
 
90
+ # Subscribe to events.
91
+ #
92
+ # @param from_id subscribe from a starting event id. default will be from the start.
93
+ # @param event_types the event_types to subscribe to, default all.
94
+ # @param after_listen the after listen call back block. default nil.
95
+ # @param subscription_master the subscription master block
60
96
  def subscribe(from_id:, event_types: nil, after_listen: nil, subscription_master:, &block)
61
97
  poll_waiter = OptimisedEventPollWaiter.new(pg_connection: @pg_connection, after_listen: after_listen)
62
98
  args = {
@@ -11,18 +11,29 @@ module EventSourcery
11
11
  end
12
12
 
13
13
  module ClassMethods
14
+ # Assign the types of events this reactor can emit.
15
+ #
16
+ # @param event_types the types of events this reactor can emit
14
17
  def emits_events(*event_types)
15
18
  @emits_event_types = event_types
16
19
  end
17
20
 
21
+ # @return [Array] an array of the types of events this reactor can emit
18
22
  def emit_events
19
23
  @emits_event_types ||= []
20
24
  end
21
25
 
26
+ # This will tell you if this reactor emits any type of event.
27
+ #
28
+ # @return [true, false] true if this emits events, false if not
22
29
  def emits_events?
23
30
  !emit_events.empty?
24
31
  end
25
32
 
33
+ # Will check if this reactor emits the given type of event.
34
+ #
35
+ # @param event_type the event type to check
36
+ # @return [true, false] true if it does emit the given event false if not
26
37
  def emits_event?(event_type)
27
38
  emit_events.include?(event_type)
28
39
  end
@@ -3,6 +3,12 @@ module EventSourcery
3
3
  module Schema
4
4
  module_function
5
5
 
6
+ # This will create the event store tables and functions
7
+ # (event, aggregates, tracker and create or update functions)
8
+ # for the given Postgres database.
9
+ # The default will be the one specified in the config.
10
+ #
11
+ # @param db the Postgres database to use
6
12
  def create_event_store(db: EventSourcery::Postgres.config.event_store_database,
7
13
  events_table_name: EventSourcery::Postgres.config.events_table_name,
8
14
  aggregates_table_name: EventSourcery::Postgres.config.aggregates_table_name,
@@ -12,6 +18,11 @@ module EventSourcery
12
18
  create_or_update_functions(db: db, events_table_name: events_table_name, function_name: write_events_function_name, aggregates_table_name: aggregates_table_name)
13
19
  end
14
20
 
21
+ # Create the events table. Needs the database and the table name.
22
+ # The defaults will be whats specified in config.
23
+ #
24
+ # @param db the Postgres database to use
25
+ # @param table_name the name of the events table
15
26
  def create_events(db: EventSourcery::Postgres.config.event_store_database,
16
27
  table_name: EventSourcery::Postgres.config.events_table_name)
17
28
  db.run 'CREATE EXTENSION IF NOT EXISTS "uuid-ossp"'
@@ -34,6 +45,11 @@ module EventSourcery
34
45
  end
35
46
  end
36
47
 
48
+ # Create the aggregates table. Needs the database and the table name.
49
+ # The defaults will be whats specified in config.
50
+ #
51
+ # @param db the Postgres database to use
52
+ # @param table_name the name of the aggregates table
37
53
  def create_aggregates(db: EventSourcery::Postgres.config.event_store_database,
38
54
  table_name: EventSourcery::Postgres.config.aggregates_table_name)
39
55
  db.create_table(table_name) do
@@ -42,6 +58,14 @@ module EventSourcery
42
58
  end
43
59
  end
44
60
 
61
+ # Create the 'create or update' fucntions.
62
+ # Needs the database, table name, function name and aggregates table name.
63
+ # The defaults will be whats specified in config.
64
+ #
65
+ # @param db the Postgres database to use
66
+ # @param function_name the name of the write events function
67
+ # @param events_table_name the name of the events table
68
+ # @param aggregates_table_name the name of the aggregates table
45
69
  def create_or_update_functions(db: EventSourcery::Postgres.config.event_store_database,
46
70
  function_name: EventSourcery::Postgres.config.write_events_function_name,
47
71
  events_table_name: EventSourcery::Postgres.config.events_table_name,
@@ -138,6 +162,11 @@ $$ language plpgsql;
138
162
  SQL
139
163
  end
140
164
 
165
+ # Create the projector tracker table. Needs the database and the table name.
166
+ # The defaults will be whats specified in config.
167
+ #
168
+ # @param db the Postgres database to use
169
+ # @param table_name the name of the aggregates table
141
170
  def create_projector_tracker(db: EventSourcery::Postgres.config.projections_database,
142
171
  table_name: EventSourcery::Postgres.config.tracker_table_name)
143
172
  db.create_table(table_name) do
@@ -9,15 +9,23 @@ module EventSourcery
9
9
  end
10
10
 
11
11
  module ClassMethods
12
+ # Hash of the tables and thier corresponding blocks.
13
+ #
14
+ # @return [Hash] hash keyed by table names and block values
12
15
  def tables
13
16
  @tables ||= {}
14
17
  end
15
18
 
19
+ # For the givent table name assign to give block as the value.
20
+ #
21
+ # @param name the name of the table
22
+ # @param block the block of code to assign for the table
16
23
  def table(name, &block)
17
24
  tables[name] = block
18
25
  end
19
26
  end
20
27
 
28
+ # Create each table.
21
29
  def setup
22
30
  self.class.tables.each do |table_name, schema_block|
23
31
  prefixed_name = table_name_prefixed(table_name)
@@ -26,6 +34,7 @@ module EventSourcery
26
34
  super if defined?(super)
27
35
  end
28
36
 
37
+ # Reset by dropping each table.
29
38
  def reset
30
39
  self.class.tables.keys.each do |table_name|
31
40
  prefixed_name = table_name_prefixed(table_name)
@@ -37,6 +46,8 @@ module EventSourcery
37
46
  setup
38
47
  end
39
48
 
49
+ # This will truncate all the tables and reset the tracker back to 0,
50
+ # done as a transaction.
40
51
  def truncate
41
52
  self.class.tables.each do |table_name, _|
42
53
  @db_connection.transaction do
@@ -1,6 +1,8 @@
1
1
  module EventSourcery
2
2
  module Postgres
3
+ # This will set up a persisted event id tracker for processors.
3
4
  class Tracker
5
+
4
6
  def initialize(connection = EventSourcery::Postgres.config.projections_database,
5
7
  table_name: EventSourcery::Postgres.config.tracker_table_name,
6
8
  obtain_processor_lock: true)
@@ -9,6 +11,11 @@ module EventSourcery
9
11
  @obtain_processor_lock = obtain_processor_lock
10
12
  end
11
13
 
14
+ # Set up the given processor.
15
+ # This will create the projector tracker table if it does not exits.
16
+ # If given a processor_name it will then attempt to get a lock on the db.
17
+ #
18
+ # @param processor_name the name of the procerror
12
19
  def setup(processor_name = nil)
13
20
  create_table_if_not_exists if EventSourcery::Postgres.config.auto_create_projector_tracker
14
21
 
@@ -24,6 +31,11 @@ module EventSourcery
24
31
  end
25
32
  end
26
33
 
34
+ # This will updated the tracker table to the given event id value
35
+ # for the given processor name.
36
+ #
37
+ # @param processor_name the name of the processor to udpate
38
+ # @param event_id the event id number to update to
27
39
  def processed_event(processor_name, event_id)
28
40
  table.
29
41
  where(name: processor_name.to_s).
@@ -31,6 +43,12 @@ module EventSourcery
31
43
  true
32
44
  end
33
45
 
46
+ # This allows you to process an event and update the tracker table in
47
+ # a single transaction. Will yeild the given block first then update the
48
+ # the tracker table to the give event id for the given processor name.
49
+ #
50
+ # @param processor_name the name of the processor to update
51
+ # @param event_id the event id number to update to
34
52
  def processing_event(processor_name, event_id)
35
53
  @connection.transaction do
36
54
  yield
@@ -38,15 +56,25 @@ module EventSourcery
38
56
  end
39
57
  end
40
58
 
59
+ # This will reset the tracker to the start (0) for the given processor name.
60
+ #
61
+ # @param processor_name the name of the processor to reset to 0
41
62
  def reset_last_processed_event_id(processor_name)
42
63
  table.where(name: processor_name.to_s).update(last_processed_event_id: 0)
43
64
  end
44
65
 
66
+ # This will return the last processed event id for the given processor name.
67
+ #
68
+ # @param processor_name the name of the processor you want to look up
69
+ # @return [Int, nil] the value of the last event_id processed
45
70
  def last_processed_event_id(processor_name)
46
71
  track_entry = table.where(name: processor_name.to_s).first
47
72
  track_entry[:last_processed_event_id] if track_entry
48
73
  end
49
74
 
75
+ # Will return an array of all known tracked processors.
76
+ #
77
+ # @return [Array] array of all known tracked processors
50
78
  def tracked_processors
51
79
  table.select_map(:name)
52
80
  end
@@ -1,5 +1,5 @@
1
1
  module EventSourcery
2
2
  module Postgres
3
- VERSION = '0.4.0'.freeze
3
+ VERSION = '0.5.0'.freeze
4
4
  end
5
5
  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.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Envato
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-06-21 00:00:00.000000000 Z
11
+ date: 2017-07-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel
@@ -164,7 +164,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
164
  version: '0'
165
165
  requirements: []
166
166
  rubyforge_project:
167
- rubygems_version: 2.6.11
167
+ rubygems_version: 2.5.2
168
168
  signing_key:
169
169
  specification_version: 4
170
170
  summary: Postgres event store for use with EventSourcery