replay 0.1.1 → 0.2.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/lib/replay.rb +1 -0
 - data/lib/replay/backends.rb +4 -4
 - data/lib/replay/configuration.rb +7 -1
 - data/lib/replay/event_declarations.rb +1 -2
 - data/lib/replay/event_decorator.rb +5 -1
 - data/lib/replay/event_envelope.rb +19 -0
 - data/lib/replay/observer.rb +1 -1
 - data/lib/replay/publisher.rb +26 -18
 - data/lib/replay/repository.rb +9 -8
 - data/lib/replay/repository/configuration.rb +7 -1
 - data/lib/replay/rspec.rb +1 -1
 - data/lib/replay/subscription_manager.rb +12 -6
 - data/lib/replay/subscriptions.rb +6 -2
 - data/lib/replay/test.rb +3 -1
 - data/lib/replay/test/test_event_stream.rb +7 -4
 - data/lib/replay/version.rb +1 -1
 - data/proofs/replay/publisher_proof.rb +6 -3
 - data/proofs/replay/repository_configuration_proof.rb +3 -1
 - data/proofs/replay/subscriber_manager_proof.rb +3 -3
 - data/proofs/replay/test_proof.rb +5 -1
 - data/replay.gemspec +1 -1
 - metadata +4 -3
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: d2ba86d3b1d0e597548c8fb5a807f0a5e9f98313
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 940e276d8721b831afd454f55c2dd7d574d4ab5a
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 3a8d3363c8b40dc87669b5d99934a1321eaa789cce0b18520cf1f2bf9e8228368256a8842ff0f1dad0093b416dee0af2f067a80fb3c096e72373f5be81a4a2cf
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 854dd7ae22f150b007853c8b3d39e2c697dbece4d2c7a421a1c93767243e983ed4bf2591217a4b5662c7d987b7e1ca38141bdf19d20e20c2aa4e82cb5f8a1783
         
     | 
    
        data/lib/replay.rb
    CHANGED
    
    | 
         @@ -32,6 +32,7 @@ require 'replay/inflector' 
     | 
|
| 
       32 
32 
     | 
    
         
             
            require 'replay/events'
         
     | 
| 
       33 
33 
     | 
    
         
             
            require 'replay/event_decorator'
         
     | 
| 
       34 
34 
     | 
    
         
             
            require 'replay/event_declarations'
         
     | 
| 
      
 35 
     | 
    
         
            +
            require 'replay/event_envelope'
         
     | 
| 
       35 
36 
     | 
    
         
             
            require 'replay/publisher'
         
     | 
| 
       36 
37 
     | 
    
         
             
            require 'replay/subscription_manager'
         
     | 
| 
       37 
38 
     | 
    
         
             
            require 'replay/subscriptions'
         
     | 
    
        data/lib/replay/backends.rb
    CHANGED
    
    | 
         @@ -15,8 +15,8 @@ module Replay 
     | 
|
| 
       15 
15 
     | 
    
         
             
                  def initialize
         
     | 
| 
       16 
16 
     | 
    
         
             
                    @store = {}
         
     | 
| 
       17 
17 
     | 
    
         
             
                  end
         
     | 
| 
       18 
     | 
    
         
            -
                  def self.published( 
     | 
| 
       19 
     | 
    
         
            -
                    instance.published( 
     | 
| 
      
 18 
     | 
    
         
            +
                  def self.published(envelope)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    instance.published(envelope)
         
     | 
| 
       20 
20 
     | 
    
         
             
                  end
         
     | 
| 
       21 
21 
     | 
    
         | 
| 
       22 
22 
     | 
    
         
             
                  def self.clear
         
     | 
| 
         @@ -27,9 +27,9 @@ module Replay 
     | 
|
| 
       27 
27 
     | 
    
         
             
                    @store = {}
         
     | 
| 
       28 
28 
     | 
    
         
             
                  end
         
     | 
| 
       29 
29 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
                  def published( 
     | 
| 
      
 30 
     | 
    
         
            +
                  def published(envelope)
         
     | 
| 
       31 
31 
     | 
    
         
             
                    @store[stream_id] ||= []
         
     | 
| 
       32 
     | 
    
         
            -
                    @store[stream_id] <<  
     | 
| 
      
 32 
     | 
    
         
            +
                    @store[stream_id] << envelope
         
     | 
| 
       33 
33 
     | 
    
         
             
                  end
         
     | 
| 
       34 
34 
     | 
    
         | 
| 
       35 
35 
     | 
    
         
             
                  def event_stream(stream_id)
         
     | 
    
        data/lib/replay/configuration.rb
    CHANGED
    
    | 
         @@ -1,10 +1,16 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Replay
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Configuration
         
     | 
| 
       3 
3 
     | 
    
         
             
                attr_accessor :storage
         
     | 
| 
      
 4 
     | 
    
         
            +
                attr_writer :reject_load_on_empty_stream
         
     | 
| 
       4 
5 
     | 
    
         | 
| 
       5 
6 
     | 
    
         
             
                def storage=(stores)
         
     | 
| 
       6 
7 
     | 
    
         
             
                  stores = [stores] unless stores.is_a?(Array)
         
     | 
| 
       7 
8 
     | 
    
         
             
                  @storage = stores
         
     | 
| 
       8 
9 
     | 
    
         
             
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                def reject_load_on_empty_stream?
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @reject_load_on_empty_stream ||= true
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @reject_load_on_empty_stream
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
       9 
15 
     | 
    
         
             
              end
         
     | 
| 
       10 
     | 
    
         
            -
            end
         
     | 
| 
      
 16 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -15,6 +15,7 @@ module Replay 
     | 
|
| 
       15 
15 
     | 
    
         
             
                    end
         
     | 
| 
       16 
16 
     | 
    
         
             
                  end
         
     | 
| 
       17 
17 
     | 
    
         
             
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
       18 
19 
     | 
    
         
             
                def method_missing(name, *args)
         
     | 
| 
       19 
20 
     | 
    
         
             
                  declare_event(self, name, args.first)
         
     | 
| 
       20 
21 
     | 
    
         
             
                end
         
     | 
| 
         @@ -22,13 +23,11 @@ module Replay 
     | 
|
| 
       22 
23 
     | 
    
         
             
                def declare_event(base, name, props)
         
     | 
| 
       23 
24 
     | 
    
         
             
                  klass = Class.new do
         
     | 
| 
       24 
25 
     | 
    
         
             
                    include Replay::EventDecorator
         
     | 
| 
       25 
     | 
    
         
            -
                    attribute :published_at, Time, default: lambda{|p,a| Time.now}
         
     | 
| 
       26 
26 
     | 
    
         
             
                    values do
         
     | 
| 
       27 
27 
     | 
    
         
             
                      props.keys.each do |prop|
         
     | 
| 
       28 
28 
     | 
    
         
             
                        attribute prop, props[prop]
         
     | 
| 
       29 
29 
     | 
    
         
             
                      end
         
     | 
| 
       30 
30 
     | 
    
         
             
                    end
         
     | 
| 
       31 
     | 
    
         
            -
                    include Virtus::Equalizer.new("#{name.to_s} equalizer", (self.attribute_set.map(&:name) - [:published_at]).map(&:to_s))
         
     | 
| 
       32 
31 
     | 
    
         
             
                  end
         
     | 
| 
       33 
32 
     | 
    
         
             
                  base.const_set name, klass
         
     | 
| 
       34 
33 
     | 
    
         
             
                end
         
     | 
| 
         @@ -4,8 +4,12 @@ module Replay 
     | 
|
| 
       4 
4 
     | 
    
         
             
                def self.included(base)
         
     | 
| 
       5 
5 
     | 
    
         
             
                  base.class_eval do 
         
     | 
| 
       6 
6 
     | 
    
         
             
                    include Virtus.value_object
         
     | 
| 
      
 7 
     | 
    
         
            +
                    attr_accessor :metadata
         
     | 
| 
       7 
8 
     | 
    
         
             
                    def inspect
         
     | 
| 
       8 
     | 
    
         
            -
                      "#{self. 
     | 
| 
      
 9 
     | 
    
         
            +
                      "#{self.type}: #{self.attributes.map{|k, v| "#{k.to_s} = #{v.to_s}"}.join(", ")}"
         
     | 
| 
      
 10 
     | 
    
         
            +
                    end
         
     | 
| 
      
 11 
     | 
    
         
            +
                    def type
         
     | 
| 
      
 12 
     | 
    
         
            +
                      self.class.to_s
         
     | 
| 
       9 
13 
     | 
    
         
             
                    end
         
     | 
| 
       10 
14 
     | 
    
         
             
                  end
         
     | 
| 
       11 
15 
     | 
    
         
             
                end
         
     | 
| 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Replay
         
     | 
| 
      
 2 
     | 
    
         
            +
              class EventEnvelope
         
     | 
| 
      
 3 
     | 
    
         
            +
                attr_reader :stream_id, :event, :metadata
         
     | 
| 
      
 4 
     | 
    
         
            +
                def initialize(stream_id, event, metadata = {})
         
     | 
| 
      
 5 
     | 
    
         
            +
                  @metadata = metadata
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @event = event
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @stream_id = stream_id
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                def type
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @event.type
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def method_missing(method, *args)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  return @event.send(method, args) if @event.respond_to?(method)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  super
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/replay/observer.rb
    CHANGED
    
    | 
         @@ -21,7 +21,7 @@ module Replay 
     | 
|
| 
       21 
21 
     | 
    
         
             
                  end
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
       23 
23 
     | 
    
         
             
                  def published(stream_id, event)
         
     | 
| 
       24 
     | 
    
         
            -
                    blk = @observer_blocks[Replay::Inflector.underscore(event. 
     | 
| 
      
 24 
     | 
    
         
            +
                    blk = @observer_blocks[Replay::Inflector.underscore(event.type)]
         
     | 
| 
       25 
25 
     | 
    
         
             
                    blk.call(stream_id, event, binding) if blk
         
     | 
| 
       26 
26 
     | 
    
         
             
                  end
         
     | 
| 
       27 
27 
     | 
    
         
             
                end
         
     | 
    
        data/lib/replay/publisher.rb
    CHANGED
    
    | 
         @@ -13,28 +13,36 @@ module Replay 
     | 
|
| 
       13 
13 
     | 
    
         
             
                  return apply([events], raise_unhandled) unless events.is_a?(Array)
         
     | 
| 
       14 
14 
     | 
    
         | 
| 
       15 
15 
     | 
    
         
             
                  events.each do |event|
         
     | 
| 
       16 
     | 
    
         
            -
                     
     | 
| 
       17 
     | 
    
         
            -
                    raise UnhandledEventError.new "event #{event. 
     | 
| 
       18 
     | 
    
         
            -
                    self. 
     | 
| 
      
 16 
     | 
    
         
            +
                    apply_method = apply_method_for(event.class)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    raise UnhandledEventError.new "event #{event.type} is not handled by #{self.class.name}" if (!respond_to?(apply_method) && raise_unhandled)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    self.send(apply_method, event)
         
     | 
| 
       19 
19 
     | 
    
         
             
                  end
         
     | 
| 
       20 
20 
     | 
    
         
             
                  return self
         
     | 
| 
       21 
21 
     | 
    
         
             
                end
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
       23 
     | 
    
         
            -
                def  
     | 
| 
       24 
     | 
    
         
            -
                  self.class. 
     | 
| 
      
 23 
     | 
    
         
            +
                def apply_method_for(klass)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  self.class.apply_method_for(klass)
         
     | 
| 
       25 
25 
     | 
    
         
             
                end
         
     | 
| 
       26 
     | 
    
         
            -
                protected :block_for
         
     | 
| 
       27 
26 
     | 
    
         | 
| 
       28 
     | 
    
         
            -
                 
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
      
 27 
     | 
    
         
            +
                private :apply_method_for
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                def publish(event, metadata={})
         
     | 
| 
      
 30 
     | 
    
         
            +
                  return publish([event]) unless event.is_a?(Array)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  event.each do |evt|
         
     | 
| 
      
 32 
     | 
    
         
            +
                    metadata = ({:published_at => Time.now}.merge!(metadata))
         
     | 
| 
      
 33 
     | 
    
         
            +
                    apply(evt)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    subscription_manager.notify_subscribers(to_stream_id, evt, metadata)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
       31 
36 
     | 
    
         
             
                  return self
         
     | 
| 
       32 
37 
     | 
    
         
             
                end
         
     | 
| 
       33 
38 
     | 
    
         | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
39 
     | 
    
         
             
                def to_stream_id
         
     | 
| 
       36 
     | 
    
         
            -
                  raise Replay::UndefinedKeyError.new("No key attribute defined for #{self. 
     | 
| 
       37 
     | 
    
         
            -
                  self.send(self. 
     | 
| 
      
 40 
     | 
    
         
            +
                  raise Replay::UndefinedKeyError.new("No key attribute defined for #{self.type}") unless self.key_attr
         
     | 
| 
      
 41 
     | 
    
         
            +
                  self.send(self.key_attr).to_s
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                def key_attr
         
     | 
| 
      
 45 
     | 
    
         
            +
                  self.class.key_attr
         
     | 
| 
       38 
46 
     | 
    
         
             
                end
         
     | 
| 
       39 
47 
     | 
    
         | 
| 
       40 
48 
     | 
    
         
             
                module ClassMethods
         
     | 
| 
         @@ -47,17 +55,17 @@ module Replay 
     | 
|
| 
       47 
55 
     | 
    
         
             
                  end
         
     | 
| 
       48 
56 
     | 
    
         | 
| 
       49 
57 
     | 
    
         
             
                  def apply(event_type, &block)
         
     | 
| 
       50 
     | 
    
         
            -
                     
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
                  def block_for(event_type)
         
     | 
| 
       54 
     | 
    
         
            -
                    blk = @application_blocks[stringify_class(event_type)]
         
     | 
| 
       55 
     | 
    
         
            -
                    return blk
         
     | 
| 
      
 58 
     | 
    
         
            +
                    method_name = apply_method_for(event_type)
         
     | 
| 
      
 59 
     | 
    
         
            +
                    define_method method_name, block
         
     | 
| 
       56 
60 
     | 
    
         
             
                  end
         
     | 
| 
       57 
61 
     | 
    
         | 
| 
       58 
62 
     | 
    
         
             
                  def stringify_class(klass)
         
     | 
| 
       59 
63 
     | 
    
         
             
                    Replay::Inflector.underscore(klass.to_s.dup)
         
     | 
| 
       60 
64 
     | 
    
         
             
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                  def apply_method_for(klass)
         
     | 
| 
      
 67 
     | 
    
         
            +
                    "handle_#{stringify_class(klass).gsub(".", "_")}"
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
       61 
69 
     | 
    
         
             
                end
         
     | 
| 
       62 
70 
     | 
    
         
             
              end
         
     | 
| 
       63 
71 
     | 
    
         
             
            end
         
     | 
    
        data/lib/replay/repository.rb
    CHANGED
    
    | 
         @@ -19,15 +19,15 @@ module Replay 
     | 
|
| 
       19 
19 
     | 
    
         
             
                    repository_load(klass, stream_id, options)
         
     | 
| 
       20 
20 
     | 
    
         
             
                  end
         
     | 
| 
       21 
21 
     | 
    
         | 
| 
       22 
     | 
    
         
            -
                  def repository_load( 
     | 
| 
       23 
     | 
    
         
            -
                     
     | 
| 
       24 
     | 
    
         
            -
                    if  
     | 
| 
      
 22 
     | 
    
         
            +
                  def repository_load(klass_or_instance, stream_id, options={})
         
     | 
| 
      
 23 
     | 
    
         
            +
                    stream = store.event_stream(stream_id)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    if stream.empty? && configuration.reject_load_on_empty_stream?
         
     | 
| 
       25 
25 
     | 
    
         
             
                      raise Errors::EventStreamNotFoundError.new("Could not find any events for stream identifier #{stream_id}") if options[:create].nil?
         
     | 
| 
       26 
26 
     | 
    
         
             
                    end
         
     | 
| 
       27 
27 
     | 
    
         | 
| 
       28 
     | 
    
         
            -
                    obj = prepare(klass.new)
         
     | 
| 
       29 
     | 
    
         
            -
                    obj.create(stream_id) if options[:create] &&  
     | 
| 
       30 
     | 
    
         
            -
                    obj.apply( 
     | 
| 
      
 28 
     | 
    
         
            +
                    obj = klass_or_instance.is_a?(Class) ? prepare(klass.new, options[:metadata]) : klass_or_instance
         
     | 
| 
      
 29 
     | 
    
         
            +
                    obj.create(stream_id) if options[:create] && stream.empty?
         
     | 
| 
      
 30 
     | 
    
         
            +
                    obj.apply(stream.map(&:event))
         
     | 
| 
       31 
31 
     | 
    
         | 
| 
       32 
32 
     | 
    
         
             
                    obj
         
     | 
| 
       33 
33 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -40,7 +40,8 @@ module Replay 
     | 
|
| 
       40 
40 
     | 
    
         
             
                    new_obj
         
     | 
| 
       41 
41 
     | 
    
         
             
                  end
         
     | 
| 
       42 
42 
     | 
    
         | 
| 
       43 
     | 
    
         
            -
                  def prepare(obj)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  def prepare(obj, metadata={})
         
     | 
| 
      
 44 
     | 
    
         
            +
                    obj.subscription_manager = SubscriptionManager.new(configuration.logger, metadata)
         
     | 
| 
       44 
45 
     | 
    
         
             
                    @configuration.subscribers.each do |subscriber|
         
     | 
| 
       45 
46 
     | 
    
         
             
                      obj.add_subscriber(subscriber)
         
     | 
| 
       46 
47 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -48,7 +49,7 @@ module Replay 
     | 
|
| 
       48 
49 
     | 
    
         
             
                  end
         
     | 
| 
       49 
50 
     | 
    
         | 
| 
       50 
51 
     | 
    
         
             
                  def configure 
         
     | 
| 
       51 
     | 
    
         
            -
                    @configuration ||= Configuration. 
     | 
| 
      
 52 
     | 
    
         
            +
                    @configuration ||= Configuration.default
         
     | 
| 
       52 
53 
     | 
    
         
             
                    yield @configuration
         
     | 
| 
       53 
54 
     | 
    
         
             
                    @configuration
         
     | 
| 
       54 
55 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -1,8 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Replay
         
     | 
| 
       2 
2 
     | 
    
         
             
              module Repository
         
     | 
| 
       3 
3 
     | 
    
         
             
                class Configuration
         
     | 
| 
       4 
     | 
    
         
            -
                   
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_accessor :logger
         
     | 
| 
      
 5 
     | 
    
         
            +
                  def initialize(logger = nil)
         
     | 
| 
       5 
6 
     | 
    
         
             
                    @default_subscribers =[]
         
     | 
| 
      
 7 
     | 
    
         
            +
                    @logger = logger
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def self.default
         
     | 
| 
      
 11 
     | 
    
         
            +
                    self.new(Replay.logger)
         
     | 
| 
       6 
12 
     | 
    
         
             
                  end
         
     | 
| 
       7 
13 
     | 
    
         | 
| 
       8 
14 
     | 
    
         
             
                  def add_default_subscriber(subscriber)
         
     | 
    
        data/lib/replay/rspec.rb
    CHANGED
    
    | 
         @@ -43,7 +43,7 @@ RSpec::Matchers.define :publish do |expected_event| 
     | 
|
| 
       43 
43 
     | 
    
         
             
              end
         
     | 
| 
       44 
44 
     | 
    
         | 
| 
       45 
45 
     | 
    
         
             
              def event_interpretation(event)
         
     | 
| 
       46 
     | 
    
         
            -
                "#{event. 
     | 
| 
      
 46 
     | 
    
         
            +
                "#{event.type} [#{event.attributes.reject{|k,v| v.nil?}.keys.map{|k| "#{k.to_s} = #{event.attributes[k]}"}.join(", ")}]"
         
     | 
| 
       47 
47 
     | 
    
         
             
              end
         
     | 
| 
       48 
48 
     | 
    
         | 
| 
       49 
49 
     | 
    
         
             
            end
         
     | 
| 
         @@ -1,26 +1,32 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Replay
         
     | 
| 
       2 
2 
     | 
    
         
             
              class SubscriptionManager
         
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
                def initialize(logger = nil)
         
     | 
| 
      
 3 
     | 
    
         
            +
                def initialize(logger = nil, session_metadata = {})
         
     | 
| 
       5 
4 
     | 
    
         
             
                  @subscribers = []
         
     | 
| 
       6 
5 
     | 
    
         
             
                  @logger = logger
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @session_metadata = session_metadata
         
     | 
| 
       7 
7 
     | 
    
         
             
                end
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
                def add_subscriber(subscriber)
         
     | 
| 
       10 
10 
     | 
    
         
             
                  if subscriber.respond_to?(:published)
         
     | 
| 
       11 
     | 
    
         
            -
                    @subscribers << subscriber 
     | 
| 
      
 11 
     | 
    
         
            +
                    @subscribers << subscriber
         
     | 
| 
       12 
12 
     | 
    
         
             
                  else
         
     | 
| 
       13 
13 
     | 
    
         
             
                    raise Replay::InvalidSubscriberError.new(subscriber)
         
     | 
| 
       14 
14 
     | 
    
         
             
                  end
         
     | 
| 
       15 
15 
     | 
    
         
             
                end
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
                def notify_subscribers(stream_id, event)
         
     | 
| 
      
 17 
     | 
    
         
            +
                def notify_subscribers(stream_id, event, metadata = {})
         
     | 
| 
       18 
18 
     | 
    
         
             
                  @subscribers.each do |sub|
         
     | 
| 
       19 
19 
     | 
    
         
             
                    begin
         
     | 
| 
       20 
     | 
    
         
            -
                       
     | 
| 
      
 20 
     | 
    
         
            +
                      meta = metadata.merge(@session_metadata)
         
     | 
| 
      
 21 
     | 
    
         
            +
                      sub.published(EventEnvelope.new(stream_id, event, meta))
         
     | 
| 
      
 22 
     | 
    
         
            +
                      #sub.published(stream_id, event, metadata)
         
     | 
| 
       21 
23 
     | 
    
         
             
                    rescue Exception => e
         
     | 
| 
       22 
24 
     | 
    
         
             
                      #hmmmm
         
     | 
| 
       23 
     | 
    
         
            -
                       
     | 
| 
      
 25 
     | 
    
         
            +
                      if @logger
         
     | 
| 
      
 26 
     | 
    
         
            +
                        @logger.error "exception in event subscriber #{sub.class.to_s} while handling event stream #{stream_id} #{event.inspect}: #{e.message}\n#{e.backtrace.join("\n")}" 
         
     | 
| 
      
 27 
     | 
    
         
            +
                      else
         
     | 
| 
      
 28 
     | 
    
         
            +
                        raise e
         
     | 
| 
      
 29 
     | 
    
         
            +
                      end
         
     | 
| 
       24 
30 
     | 
    
         
             
                    end
         
     | 
| 
       25 
31 
     | 
    
         
             
                  end
         
     | 
| 
       26 
32 
     | 
    
         
             
                end
         
     | 
    
        data/lib/replay/subscriptions.rb
    CHANGED
    
    | 
         @@ -4,12 +4,16 @@ module Replay 
     | 
|
| 
       4 
4 
     | 
    
         
             
                  @subscription_manager ||= Replay::SubscriptionManager.new(Replay.logger)
         
     | 
| 
       5 
5 
     | 
    
         
             
                end
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
      
 7 
     | 
    
         
            +
                def subscription_manager=(sm)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @subscription_manager = sm
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
       7 
11 
     | 
    
         
             
                def add_subscriber(subscriber)
         
     | 
| 
       8 
12 
     | 
    
         
             
                  subscription_manager.add_subscriber(subscriber)
         
     | 
| 
       9 
13 
     | 
    
         
             
                end
         
     | 
| 
       10 
14 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
                def published(stream_id, event)
         
     | 
| 
       12 
     | 
    
         
            -
                  @subscription_manager.notify_subscribers(stream_id, event)
         
     | 
| 
      
 15 
     | 
    
         
            +
                def published(stream_id, event, metadata)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @subscription_manager.notify_subscribers(stream_id, event, metadata)
         
     | 
| 
       13 
17 
     | 
    
         
             
                end
         
     | 
| 
       14 
18 
     | 
    
         
             
              end
         
     | 
| 
       15 
19 
     | 
    
         
             
            end
         
     | 
    
        data/lib/replay/test.rb
    CHANGED
    
    | 
         @@ -61,8 +61,10 @@ Replay::EventDecorator.module_exec do 
     | 
|
| 
       61 
61 
     | 
    
         
             
                relevant_attrs_match = event.attributes.reject{|k,v| v.nil?}
         
     | 
| 
       62 
62 
     | 
    
         
             
                relevant_attrs_self = self.attributes.reject{|k,v| v.nil?}
         
     | 
| 
       63 
63 
     | 
    
         | 
| 
      
 64 
     | 
    
         
            +
                keys_self = relevant_attrs_self.keys
         
     | 
| 
       64 
65 
     | 
    
         
             
                if (relevant_attrs_self.keys - relevant_attrs_match.keys).empty?
         
     | 
| 
       65 
     | 
    
         
            -
                   
     | 
| 
      
 66 
     | 
    
         
            +
                  #publication time is not considered part of the event data
         
     | 
| 
      
 67 
     | 
    
         
            +
                  if keys_self.reject{|k| event[k] == self[k]}.any?
         
     | 
| 
       66 
68 
     | 
    
         
             
                    return false
         
     | 
| 
       67 
69 
     | 
    
         
             
                  else
         
     | 
| 
       68 
70 
     | 
    
         
             
                    return true
         
     | 
| 
         @@ -1,19 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'replay/test'
         
     | 
| 
       1 
2 
     | 
    
         
             
            module Replay
         
     | 
| 
       2 
3 
     | 
    
         
             
              class TestEventStream
         
     | 
| 
      
 4 
     | 
    
         
            +
                include EventExaminer
         
     | 
| 
      
 5 
     | 
    
         
            +
                attr_accessor :events
         
     | 
| 
       3 
6 
     | 
    
         | 
| 
       4 
7 
     | 
    
         
             
                def initialize
         
     | 
| 
       5 
8 
     | 
    
         
             
                  @events = []
         
     | 
| 
       6 
9 
     | 
    
         
             
                end
         
     | 
| 
       7 
     | 
    
         
            -
                def  
     | 
| 
       8 
     | 
    
         
            -
                  @events <<  
     | 
| 
      
 10 
     | 
    
         
            +
                def published(event_envelope)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @events << event_envelope
         
     | 
| 
       9 
12 
     | 
    
         
             
                end
         
     | 
| 
       10 
13 
     | 
    
         | 
| 
       11 
14 
     | 
    
         
             
                def published_event?(event)
         
     | 
| 
       12 
     | 
    
         
            -
                  @events.detect{|e| e 
     | 
| 
      
 15 
     | 
    
         
            +
                  @events.detect{|e| e.event==event}
         
     | 
| 
       13 
16 
     | 
    
         
             
                end
         
     | 
| 
       14 
17 
     | 
    
         | 
| 
       15 
18 
     | 
    
         
             
                def published?(stream_id, event)
         
     | 
| 
       16 
     | 
    
         
            -
                  @events.detect{|e| e ==  
     | 
| 
      
 19 
     | 
    
         
            +
                  @events.detect{|e| e.stream_id == stream_id &&  e.event == event}
         
     | 
| 
       17 
20 
     | 
    
         
             
                end
         
     | 
| 
       18 
21 
     | 
    
         
             
              end
         
     | 
| 
       19 
22 
     | 
    
         
             
            end
         
     | 
    
        data/lib/replay/version.rb
    CHANGED
    
    
| 
         @@ -1,5 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require_relative "../proofs_init.rb"
         
     | 
| 
       2 
2 
     | 
    
         
             
            require 'replay/test'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'replay/test/test_event_stream'
         
     | 
| 
       3 
4 
     | 
    
         | 
| 
       4 
5 
     | 
    
         
             
            class ReplayTest
         
     | 
| 
       5 
6 
     | 
    
         
             
              include Replay::Publisher
         
     | 
| 
         @@ -29,8 +30,10 @@ end 
     | 
|
| 
       29 
30 
     | 
    
         | 
| 
       30 
31 
     | 
    
         
             
            module ReplayTest::Proof
         
     | 
| 
       31 
32 
     | 
    
         
             
              def sets_publish_time
         
     | 
| 
      
 33 
     | 
    
         
            +
                ts=Replay::TestEventStream.new
         
     | 
| 
      
 34 
     | 
    
         
            +
                add_subscriber(ts)
         
     | 
| 
       32 
35 
     | 
    
         
             
                publish SomeEvent(pid: 123)
         
     | 
| 
       33 
     | 
    
         
            -
                events.last.published_at != nil && (Time.now - events.last.published_at) <  
     | 
| 
      
 36 
     | 
    
         
            +
                ts.events.last.metadata[:published_at] != nil && (Time.now - ts.events.last.metadata[:published_at]) < 1
         
     | 
| 
       34 
37 
     | 
    
         
             
              end
         
     | 
| 
       35 
38 
     | 
    
         | 
| 
       36 
39 
     | 
    
         
             
              def published_at_not_considered_in_equality
         
     | 
| 
         @@ -72,7 +75,7 @@ module ReplayTest::Proof 
     | 
|
| 
       72 
75 
     | 
    
         | 
| 
       73 
76 
     | 
    
         
             
              def subscribers_receive_events
         
     | 
| 
       74 
77 
     | 
    
         
             
                sub = Class.new do
         
     | 
| 
       75 
     | 
    
         
            -
                  def published( 
     | 
| 
      
 78 
     | 
    
         
            +
                  def published(envelope)
         
     | 
| 
       76 
79 
     | 
    
         
             
                    @published = true
         
     | 
| 
       77 
80 
     | 
    
         
             
                  end
         
     | 
| 
       78 
81 
     | 
    
         
             
                  def published?; @published; end
         
     | 
| 
         @@ -154,7 +157,7 @@ proof "Returns self from publish" do 
     | 
|
| 
       154 
157 
     | 
    
         
             
              r.prove{ publish([]) == self}
         
     | 
| 
       155 
158 
     | 
    
         
             
            end
         
     | 
| 
       156 
159 
     | 
    
         | 
| 
       157 
     | 
    
         
            -
            proof " 
     | 
| 
      
 160 
     | 
    
         
            +
            proof "adds the publish time to event metadata" do
         
     | 
| 
       158 
161 
     | 
    
         
             
              r = ReplayTest.new
         
     | 
| 
       159 
162 
     | 
    
         
             
              r.prove{ sets_publish_time }
         
     | 
| 
       160 
163 
     | 
    
         
             
            end
         
     | 
| 
         @@ -2,9 +2,11 @@ require_relative "../proofs_init.rb" 
     | 
|
| 
       2 
2 
     | 
    
         
             
            require 'replay/test'
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            class Subscriber
         
     | 
| 
       5 
     | 
    
         
            -
              def published( 
     | 
| 
      
 5 
     | 
    
         
            +
              def published(envelope); end
         
     | 
| 
       6 
6 
     | 
    
         
             
            end
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
      
 8 
     | 
    
         
            +
            title "Repository configuration"
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
       8 
10 
     | 
    
         
             
            module Replay::Repository::Configuration::Proof
         
     | 
| 
       9 
11 
     | 
    
         
             
              def can_configure_store?
         
     | 
| 
       10 
12 
     | 
    
         
             
                self.store = :memory
         
     | 
| 
         @@ -14,9 +14,9 @@ module Replay::SubscriptionManager::Proof 
     | 
|
| 
       14 
14 
     | 
    
         
             
              def sub_gets_notified
         
     | 
| 
       15 
15 
     | 
    
         
             
                sub = Class.new do
         
     | 
| 
       16 
16 
     | 
    
         
             
                  attr_accessor :stream, :event
         
     | 
| 
       17 
     | 
    
         
            -
                  def published( 
     | 
| 
       18 
     | 
    
         
            -
                    self.stream =  
     | 
| 
       19 
     | 
    
         
            -
                    self.event = event
         
     | 
| 
      
 17 
     | 
    
         
            +
                  def published(envelope)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    self.stream = envelope.stream_id
         
     | 
| 
      
 19 
     | 
    
         
            +
                    self.event = envelope.event
         
     | 
| 
       20 
20 
     | 
    
         
             
                  end
         
     | 
| 
       21 
21 
     | 
    
         
             
                end.new
         
     | 
| 
       22 
22 
     | 
    
         
             
                add_subscriber(sub)
         
     | 
    
        data/proofs/replay/test_proof.rb
    CHANGED
    
    | 
         @@ -21,8 +21,12 @@ proof "fuzzy matching of events" do 
     | 
|
| 
       21 
21 
     | 
    
         | 
| 
       22 
22 
     | 
    
         
             
              e1 = TestEvent.new(one: '1')
         
     | 
| 
       23 
23 
     | 
    
         
             
              e2 = TestEvent.new(one: '1', two: '2')
         
     | 
| 
      
 24 
     | 
    
         
            +
              e3 = TestEvent.new(one: '1', two: '2')
         
     | 
| 
      
 25 
     | 
    
         
            +
              e4 = TestEvent.new(one: '1', two: '4')
         
     | 
| 
       24 
26 
     | 
    
         | 
| 
       25 
27 
     | 
    
         
             
              e1.prove{ matches_fuzzy(e2)}
         
     | 
| 
       26 
28 
     | 
    
         
             
              e2.prove{ !matches_fuzzy(e1)}
         
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
      
 29 
     | 
    
         
            +
              e2.prove{ matches_fuzzy(e2)}
         
     | 
| 
      
 30 
     | 
    
         
            +
              e2.prove{ matches_fuzzy(e3)}
         
     | 
| 
      
 31 
     | 
    
         
            +
              e2.prove{ !matches_fuzzy(e4)}
         
     | 
| 
       28 
32 
     | 
    
         
             
            end
         
     | 
    
        data/replay.gemspec
    CHANGED
    
    | 
         @@ -7,7 +7,7 @@ Gem::Specification.new do |s| 
     | 
|
| 
       7 
7 
     | 
    
         
             
              s.version     = Replay::VERSION
         
     | 
| 
       8 
8 
     | 
    
         
             
              s.authors     = ["karmajunkie"]
         
     | 
| 
       9 
9 
     | 
    
         
             
              s.email       = ["keith.gaddis@gmail.com"]
         
     | 
| 
       10 
     | 
    
         
            -
              s.homepage    = ""
         
     | 
| 
      
 10 
     | 
    
         
            +
              s.homepage    = "https://github.com/karmajunkie/replay"
         
     | 
| 
       11 
11 
     | 
    
         
             
              s.summary     = %q{Replay supports event-sourced data models.}
         
     | 
| 
       12 
12 
     | 
    
         
             
              s.description = %q{Replay supports event-sourced data models.}
         
     | 
| 
       13 
13 
     | 
    
         | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: replay
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.2.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - karmajunkie
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2014- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2014-05-26 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: bundler
         
     | 
| 
         @@ -85,6 +85,7 @@ files: 
     | 
|
| 
       85 
85 
     | 
    
         
             
            - lib/replay/configuration.rb
         
     | 
| 
       86 
86 
     | 
    
         
             
            - lib/replay/event_declarations.rb
         
     | 
| 
       87 
87 
     | 
    
         
             
            - lib/replay/event_decorator.rb
         
     | 
| 
      
 88 
     | 
    
         
            +
            - lib/replay/event_envelope.rb
         
     | 
| 
       88 
89 
     | 
    
         
             
            - lib/replay/events.rb
         
     | 
| 
       89 
90 
     | 
    
         
             
            - lib/replay/inflector.rb
         
     | 
| 
       90 
91 
     | 
    
         
             
            - lib/replay/observer.rb
         
     | 
| 
         @@ -112,7 +113,7 @@ files: 
     | 
|
| 
       112 
113 
     | 
    
         
             
            - test/replay/observer_spec.rb
         
     | 
| 
       113 
114 
     | 
    
         
             
            - test/replay/router/default_router_spec.rb
         
     | 
| 
       114 
115 
     | 
    
         
             
            - test/test_helper.rb
         
     | 
| 
       115 
     | 
    
         
            -
            homepage:  
     | 
| 
      
 116 
     | 
    
         
            +
            homepage: https://github.com/karmajunkie/replay
         
     | 
| 
       116 
117 
     | 
    
         
             
            licenses: []
         
     | 
| 
       117 
118 
     | 
    
         
             
            metadata: {}
         
     | 
| 
       118 
119 
     | 
    
         
             
            post_install_message: 
         
     |