event_sourcery-postgres 0.4.0 → 0.5.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 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