synapse-core 0.5.3 → 0.5.4

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.
Files changed (49) hide show
  1. data/lib/synapse/command.rb +2 -0
  2. data/lib/synapse/command/callbacks/future.rb +50 -0
  3. data/lib/synapse/command/command_callback.rb +0 -47
  4. data/lib/synapse/command/message.rb +1 -1
  5. data/lib/synapse/common.rb +1 -0
  6. data/lib/synapse/common/concurrency/executor.rb +13 -0
  7. data/lib/synapse/common/message.rb +9 -2
  8. data/lib/synapse/common/message_builder.rb +5 -1
  9. data/lib/synapse/configuration.rb +1 -0
  10. data/lib/synapse/configuration/component/command_bus/async_command_bus.rb +2 -8
  11. data/lib/synapse/configuration/component/event_sourcing.rb +3 -3
  12. data/lib/synapse/configuration/component/event_sourcing/repository.rb +19 -2
  13. data/lib/synapse/configuration/component/event_sourcing/{aggregate_snapshot_taker.rb → snapshot/aggregate_taker.rb} +4 -4
  14. data/lib/synapse/configuration/component/event_sourcing/{interval_snapshot_policy.rb → snapshot/interval_policy.rb} +0 -0
  15. data/lib/synapse/configuration/component/mixin/thread_pool.rb +26 -0
  16. data/lib/synapse/domain/message.rb +0 -24
  17. data/lib/synapse/domain/message_builder.rb +0 -9
  18. data/lib/synapse/event_sourcing.rb +1 -1
  19. data/lib/synapse/event_sourcing/aggregate_root.rb +2 -1
  20. data/lib/synapse/event_sourcing/caching.rb +66 -0
  21. data/lib/synapse/event_sourcing/repository.rb +22 -15
  22. data/lib/synapse/event_sourcing/snapshot/aggregate_taker.rb +8 -9
  23. data/lib/synapse/event_sourcing/snapshot/policy.rb +1 -0
  24. data/lib/synapse/event_sourcing/snapshot/taker.rb +31 -2
  25. data/lib/synapse/repository/repository.rb +18 -4
  26. data/lib/synapse/repository/simple_repository.rb +8 -17
  27. data/lib/synapse/serialization/converter.rb +2 -2
  28. data/lib/synapse/serialization/converter/identity.rb +2 -2
  29. data/lib/synapse/serialization/converter/json.rb +3 -3
  30. data/lib/synapse/serialization/converter/ox.rb +3 -3
  31. data/lib/synapse/serialization/message/metadata.rb +2 -2
  32. data/lib/synapse/serialization/message/serialization_aware.rb +2 -2
  33. data/lib/synapse/serialization/message/serialized_message.rb +7 -24
  34. data/lib/synapse/serialization/message/serialized_message_builder.rb +4 -4
  35. data/lib/synapse/uow.rb +0 -1
  36. data/lib/synapse/uow/nesting.rb +2 -2
  37. data/lib/synapse/uow/uow.rb +12 -13
  38. data/lib/synapse/version.rb +1 -1
  39. data/test/configuration/component/event_sourcing/repository_test.rb +24 -1
  40. data/test/event_sourcing/caching_test.rb +118 -0
  41. data/test/event_sourcing/repository_test.rb +2 -1
  42. data/test/event_sourcing/snapshot/aggregate_taker_test.rb +46 -16
  43. data/test/repository/locking_test.rb +1 -10
  44. data/test/serialization/serializer/attribute_test.rb +51 -0
  45. data/test/uow/uow_test.rb +9 -12
  46. metadata +12 -9
  47. data/lib/synapse/event_sourcing/storage_listener.rb +0 -34
  48. data/lib/synapse/uow/storage_listener.rb +0 -14
  49. data/test/event_sourcing/storage_listener_test.rb +0 -81
@@ -1,3 +1,3 @@
1
1
  module Synapse
2
- VERSION = '0.5.3'
2
+ VERSION = '0.5.4'
3
3
  end
@@ -44,7 +44,7 @@ module Synapse
44
44
  Object.new
45
45
  end
46
46
 
47
- @builder.aggregate_snapshot_taker
47
+ @builder.snapshot_taker
48
48
  @builder.interval_snapshot_policy
49
49
 
50
50
  @builder.factory :conflict_resolver do
@@ -66,6 +66,29 @@ module Synapse
66
66
  assert_same snapshot_taker, repository.snapshot_taker
67
67
  end
68
68
 
69
+ should 'build caching repository if cache is set' do
70
+ @builder.simple_event_bus
71
+ @builder.factory :event_store do
72
+ Object.new
73
+ end
74
+
75
+ @builder.factory :cache do
76
+ Object.new
77
+ end
78
+
79
+ @builder.es_repository :account_repository do
80
+ use_aggregate_type Object
81
+ use_cache :cache
82
+ end
83
+
84
+ repository = @container.resolve :account_repository
85
+
86
+ cache = @container.resolve :cache
87
+
88
+ assert_instance_of EventSourcing::CachingEventSourcingRepository, repository
89
+ assert_same cache, repository.cache
90
+ end
91
+
69
92
  end
70
93
  end
71
94
  end
@@ -0,0 +1,118 @@
1
+ require 'test_helper'
2
+
3
+ module Synapse
4
+ module EventSourcing
5
+ class CachingEventSourcingRepositoryTest < Test::Unit::TestCase
6
+
7
+ def setup
8
+ @unit_provider = UnitOfWork::UnitOfWorkProvider.new
9
+ @unit = UnitOfWork::UnitOfWork.new @unit_provider
10
+ @unit.start
11
+ @factory = GenericAggregateFactory.new StubAggregate
12
+ @event_store = Object.new
13
+ @lock_manager = Repository::NullLockManager.new
14
+ @cache = Object.new
15
+
16
+ @repository = CachingEventSourcingRepository.new @factory, @event_store, @lock_manager
17
+ @repository.cache = @cache
18
+ @repository.event_bus = EventBus::SimpleEventBus.new
19
+ @repository.unit_provider = @unit_provider
20
+ end
21
+
22
+ should 'load from cache before hitting the event store' do
23
+ aggregate_id = SecureRandom.uuid
24
+ aggregate = StubAggregate.new aggregate_id
25
+
26
+ mock(@cache).fetch(aggregate_id) do
27
+ aggregate
28
+ end
29
+
30
+ assert_same aggregate, @repository.load(aggregate_id)
31
+ end
32
+
33
+ should 'raise an exception if the aggregate loaded from the cache is marked for deletion' do
34
+ aggregate_id = SecureRandom.uuid
35
+ aggregate = StubAggregate.new aggregate_id
36
+ aggregate.delete_me
37
+
38
+ mock(@cache).fetch(aggregate_id) do
39
+ aggregate
40
+ end
41
+
42
+ assert_raise AggregateDeletedError do
43
+ @repository.load aggregate_id
44
+ end
45
+ end
46
+
47
+ should 'load from the event store if cache miss' do
48
+ type_identifier = @factory.type_identifier
49
+ aggregate_id = SecureRandom.uuid
50
+
51
+ mock(@cache).fetch(aggregate_id)
52
+ mock(@event_store).read_events(type_identifier, aggregate_id) do
53
+ raise EventStore::StreamNotFoundError.new(type_identifier, aggregate_id)
54
+ end
55
+
56
+ assert_raise Repository::AggregateNotFoundError do
57
+ @repository.load aggregate_id
58
+ end
59
+ end
60
+
61
+ should 'clear the cache if the unit of work is rolled back' do
62
+ aggregate_id = SecureRandom.uuid
63
+ aggregate = StubAggregate.new aggregate_id
64
+
65
+ mock(@cache).fetch(aggregate_id) do
66
+ aggregate
67
+ end
68
+
69
+ mock(@cache).delete(aggregate_id)
70
+
71
+ @repository.load aggregate_id
72
+ @unit.rollback
73
+ end
74
+
75
+ should 'delete aggregate from cache when aggregate is deleted' do
76
+ type_identifier = @factory.type_identifier
77
+ aggregate_id = SecureRandom.uuid
78
+ aggregate = StubAggregate.new aggregate_id
79
+
80
+ mock(@cache).fetch(aggregate_id).ordered do
81
+ aggregate
82
+ end
83
+
84
+ mock(@event_store).append_events(type_identifier, anything).ordered
85
+
86
+ mock(@cache).write(aggregate_id, aggregate).ordered
87
+
88
+ loaded_aggregate = @repository.load aggregate_id
89
+ loaded_aggregate.delete_me
90
+
91
+ @unit.commit
92
+ end
93
+
94
+ should 'delete aggregate from cache when commit goes wrong' do
95
+ type_identifier = @factory.type_identifier
96
+ aggregate_id = SecureRandom.uuid
97
+ aggregate = StubAggregate.new aggregate_id
98
+
99
+ mock(@cache).fetch(aggregate_id).ordered do
100
+ aggregate
101
+ end
102
+
103
+ mock(@event_store).append_events(type_identifier, anything).ordered do
104
+ raise
105
+ end
106
+
107
+ mock(@cache).delete(aggregate_id).ordered
108
+
109
+ @repository.load aggregate_id
110
+
111
+ assert_raise RuntimeError do
112
+ @unit.commit
113
+ end
114
+ end
115
+
116
+ end
117
+ end
118
+ end
@@ -90,7 +90,8 @@ module Synapse
90
90
 
91
91
  should 'register a snapshot listener if a policy and taker are set' do
92
92
  @repository.snapshot_policy = IntervalSnapshotPolicy.new 30
93
- @repository.snapshot_taker = AggregateSnapshotTaker.new @event_store
93
+ @repository.snapshot_taker = AggregateSnapshotTaker.new
94
+ @repository.snapshot_taker.event_store = @event_store
94
95
 
95
96
  mock(@unit).register_listener(anything)
96
97
  mock(@unit).register_listener(is_a(SnapshotUnitOfWorkListener))
@@ -5,33 +5,63 @@ module Synapse
5
5
  module EventSourcing
6
6
 
7
7
  class AggregateSnapshotTakerTest < Test::Unit::TestCase
8
+ def setup
9
+ @event_store = Object.new
10
+ @aggregate_factory = GenericAggregateFactory.new StubAggregate
11
+
12
+ @snapshot_taker = AggregateSnapshotTaker.new
13
+ @snapshot_taker.event_store = @event_store
14
+ @snapshot_taker.register_factory @aggregate_factory
15
+ end
16
+
8
17
  should 'store a snapshot by serializing the aggregate itself' do
9
- event_store = Object.new
10
- aggregate_factory = GenericAggregateFactory.new StubAggregate
18
+ type_identifier = @aggregate_factory.type_identifier
19
+ id = SecureRandom.uuid
11
20
 
12
- type_identifier = aggregate_factory.type_identifier
13
- id = 123
21
+ events = Array.new
22
+ events.push create_domain_event StubCreatedEvent.new(id), 0, id
23
+ events.push create_domain_event StubChangedEvent.new, 1, id
24
+ events.push create_domain_event StubChangedEvent.new, 2, id
14
25
 
15
- event = Domain::DomainEventMessage.build do |builder|
16
- builder.payload = StubCreatedEvent.new id
17
- builder.sequence_number = 0
18
- builder.aggregate_id = id
19
- end
20
- stream = Domain::SimpleDomainEventStream.new event
26
+ stream = Domain::SimpleDomainEventStream.new events
21
27
 
22
- mock(event_store).read_events(type_identifier, id) do
28
+ mock(@event_store).read_events(type_identifier, id) do
23
29
  stream
24
30
  end
25
31
 
26
- mock(event_store).append_snapshot_event(type_identifier, anything) do |_, snapshot|
32
+ mock(@event_store).append_snapshot_event(type_identifier, anything) do |_, snapshot|
27
33
  assert_equal StubAggregate, snapshot.payload_type
28
- assert_equal 0, snapshot.sequence_number
34
+ assert_equal 2, snapshot.sequence_number
29
35
  assert_equal id, snapshot.aggregate_id
30
36
  end
31
37
 
32
- snapshot_taker = AggregateSnapshotTaker.new event_store
33
- snapshot_taker.register_factory aggregate_factory
34
- snapshot_taker.schedule_snapshot type_identifier, id
38
+ @snapshot_taker.schedule_snapshot type_identifier, id
39
+ end
40
+
41
+ should 'not store a snapshot if it replaces only one event' do
42
+ type_identifier = @aggregate_factory.type_identifier
43
+ id = SecureRandom.uuid
44
+
45
+ events = Array.new
46
+ events.push create_domain_event StubCreatedEvent.new(id), 0, id
47
+
48
+ stream = Domain::SimpleDomainEventStream.new events
49
+
50
+ mock(@event_store).read_events(type_identifier, id) do
51
+ stream
52
+ end
53
+
54
+ @snapshot_taker.schedule_snapshot type_identifier, id
55
+ end
56
+
57
+ private
58
+
59
+ def create_domain_event(payload, sequence_number, aggregate_id)
60
+ Domain::DomainEventMessage.build do |builder|
61
+ builder.payload = payload
62
+ builder.sequence_number = sequence_number
63
+ builder.aggregate_id = aggregate_id
64
+ end
35
65
  end
36
66
  end
37
67
 
@@ -6,16 +6,13 @@ module Synapse
6
6
  def setup
7
7
  @event_bus = Object.new
8
8
  @lock_manager = Object.new
9
- @storage_listener = Object.new
10
9
  @unit_provider = UnitOfWork::UnitOfWorkProvider.new
11
10
 
12
11
  @unit = UnitOfWork::UnitOfWork.new @unit_provider
13
12
  @unit.start
14
13
 
15
- # I herd you like dependencies
16
14
  @repository = TestRepository.new @lock_manager
17
15
  @repository.event_bus = @event_bus
18
- @repository.storage_listener = @storage_listener
19
16
  @repository.unit_provider = @unit_provider
20
17
  end
21
18
 
@@ -25,8 +22,6 @@ module Synapse
25
22
 
26
23
  aggregate = TestAggregateRoot.new 123, nil
27
24
 
28
- mock(@storage_listener).store(aggregate)
29
-
30
25
  @repository.add aggregate
31
26
  @unit.commit
32
27
  end
@@ -75,7 +70,7 @@ module Synapse
75
70
  end
76
71
 
77
72
  class TestRepository < LockingRepository
78
- attr_accessor :aggregate, :storage_listener
73
+ attr_accessor :aggregate
79
74
 
80
75
  protected
81
76
 
@@ -92,10 +87,6 @@ module Synapse
92
87
  def aggregate_type
93
88
  TestAggregateRoot
94
89
  end
95
-
96
- def storage_listener
97
- @storage_listener
98
- end
99
90
  end
100
91
  end
101
92
  end
@@ -0,0 +1,51 @@
1
+ require 'test_helper'
2
+
3
+ module Synapse
4
+ module Serialization
5
+ class AttributeSerializerTest < Test::Unit::TestCase
6
+
7
+ should 'support serialization and deserialization of a hash' do
8
+ converter_factory = ConverterFactory.new
9
+ serializer = AttributeSerializer.new converter_factory
10
+
11
+ content = {
12
+ foo: 0
13
+ }
14
+
15
+ serialized_object = serializer.serialize(content, Hash)
16
+ assert_same content, serialized_object.content
17
+ assert_same content, serializer.deserialize(serialized_object)
18
+
19
+ assert serializer.can_serialize_to? Hash
20
+ end
21
+
22
+ should 'support serialization and deserialization of a compatible object' do
23
+ converter_factory = ConverterFactory.new
24
+ serializer = AttributeSerializer.new converter_factory
25
+
26
+ content = SomeAttributeEvent.new 0
27
+
28
+ attributes = {
29
+ foo: 0
30
+ }
31
+
32
+ serialized_object = serializer.serialize(content, Hash)
33
+ assert_equal attributes, serialized_object.content
34
+
35
+ deserialized = serializer.deserialize serialized_object
36
+ assert_equal attributes, deserialized.attributes
37
+ end
38
+
39
+ end
40
+
41
+ class SomeAttributeEvent
42
+ attr_accessor :attributes
43
+
44
+ def initialize(some_value)
45
+ @attributes = {
46
+ foo: some_value
47
+ }
48
+ end
49
+ end
50
+ end
51
+ end
@@ -37,12 +37,12 @@ module Synapse
37
37
  aggregate_d = TestAggregateB.new 3
38
38
 
39
39
  event_bus = Object.new
40
- storage_listener = Object.new
40
+ storage_callback = lambda {}
41
41
 
42
- assert_same aggregate_a, @uow.register_aggregate(aggregate_a, event_bus, storage_listener)
43
- assert_same aggregate_b, @uow.register_aggregate(aggregate_b, event_bus, storage_listener)
44
- assert_same aggregate_c, @uow.register_aggregate(aggregate_c, event_bus, storage_listener)
45
- assert_same aggregate_c, @uow.register_aggregate(aggregate_d, event_bus, storage_listener)
42
+ assert_same aggregate_a, @uow.register_aggregate(aggregate_a, event_bus, &storage_callback)
43
+ assert_same aggregate_b, @uow.register_aggregate(aggregate_b, event_bus, &storage_callback)
44
+ assert_same aggregate_c, @uow.register_aggregate(aggregate_c, event_bus, &storage_callback)
45
+ assert_same aggregate_c, @uow.register_aggregate(aggregate_d, event_bus, &storage_callback)
46
46
  end
47
47
 
48
48
  should 'interact with a transaction manager on commit' do
@@ -157,7 +157,7 @@ module Synapse
157
157
  end
158
158
  end
159
159
 
160
- should 'rollback if an aggregate storage listener raises an exception' do
160
+ should 'rollback if an aggregate storage callback raises an exception' do
161
161
  aggregate_root = Object.new
162
162
  mock(aggregate_root).add_registration_listener
163
163
  mock(aggregate_root).id
@@ -165,11 +165,6 @@ module Synapse
165
165
  event_bus = Object.new
166
166
  cause = TestError.new
167
167
 
168
- storage_listener = Object.new
169
- mock(storage_listener).store(aggregate_root) {
170
- raise cause
171
- }
172
-
173
168
  listener = UnitOfWorkListener.new
174
169
  mock(listener).on_prepare_commit(@uow, anything, anything)
175
170
  mock(listener).on_rollback(@uow, cause)
@@ -178,7 +173,9 @@ module Synapse
178
173
 
179
174
  @uow.start
180
175
  @uow.register_listener listener
181
- @uow.register_aggregate aggregate_root, event_bus, storage_listener
176
+ @uow.register_aggregate aggregate_root, event_bus do |aggregate|
177
+ raise cause
178
+ end
182
179
 
183
180
  assert_raises TestError do
184
181
  @uow.commit
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: synapse-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 0.5.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-03 00:00:00.000000000 Z
12
+ date: 2013-06-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -86,12 +86,12 @@ files:
86
86
  - lib/synapse/uow/transaction_manager.rb
87
87
  - lib/synapse/uow/factory.rb
88
88
  - lib/synapse/uow/uow.rb
89
- - lib/synapse/uow/storage_listener.rb
90
89
  - lib/synapse/uow/listener_collection.rb
91
90
  - lib/synapse/uow/listener.rb
92
91
  - lib/synapse/uow/nesting.rb
93
92
  - lib/synapse/command/rollback_policy.rb
94
93
  - lib/synapse/command/interceptors/serialization.rb
94
+ - lib/synapse/command/callbacks/future.rb
95
95
  - lib/synapse/command/gateway/interval_retry_scheduler.rb
96
96
  - lib/synapse/command/gateway/retrying_callback.rb
97
97
  - lib/synapse/command/gateway/retry_scheduler.rb
@@ -119,13 +119,13 @@ files:
119
119
  - lib/synapse/repository/repository.rb
120
120
  - lib/synapse/auditing.rb
121
121
  - lib/synapse/event_sourcing/aggregate_factory.rb
122
+ - lib/synapse/event_sourcing/caching.rb
122
123
  - lib/synapse/event_sourcing/stream_decorator.rb
123
124
  - lib/synapse/event_sourcing/entity.rb
124
125
  - lib/synapse/event_sourcing/snapshot/aggregate_taker.rb
125
126
  - lib/synapse/event_sourcing/snapshot/policy.rb
126
127
  - lib/synapse/event_sourcing/snapshot/unit_listener.rb
127
128
  - lib/synapse/event_sourcing/snapshot/taker.rb
128
- - lib/synapse/event_sourcing/storage_listener.rb
129
129
  - lib/synapse/event_sourcing/member.rb
130
130
  - lib/synapse/event_sourcing/repository.rb
131
131
  - lib/synapse/event_sourcing/aggregate_root.rb
@@ -148,9 +148,9 @@ files:
148
148
  - lib/synapse/configuration/component/command_bus/gateway.rb
149
149
  - lib/synapse/configuration/component/repository/simple_repository.rb
150
150
  - lib/synapse/configuration/component/repository/locking_repository.rb
151
- - lib/synapse/configuration/component/event_sourcing/aggregate_snapshot_taker.rb
151
+ - lib/synapse/configuration/component/event_sourcing/snapshot/aggregate_taker.rb
152
+ - lib/synapse/configuration/component/event_sourcing/snapshot/interval_policy.rb
152
153
  - lib/synapse/configuration/component/event_sourcing/repository.rb
153
- - lib/synapse/configuration/component/event_sourcing/interval_snapshot_policy.rb
154
154
  - lib/synapse/configuration/component/upcasting/upcaster_chain.rb
155
155
  - lib/synapse/configuration/component/process_manager.rb
156
156
  - lib/synapse/configuration/component/process_manager/mapping_process_manager.rb
@@ -159,6 +159,7 @@ files:
159
159
  - lib/synapse/configuration/component/upcasting.rb
160
160
  - lib/synapse/configuration/component/serialization.rb
161
161
  - lib/synapse/configuration/component/uow.rb
162
+ - lib/synapse/configuration/component/mixin/thread_pool.rb
162
163
  - lib/synapse/configuration/component/repository.rb
163
164
  - lib/synapse/configuration/component/event_bus/simple_event_bus.rb
164
165
  - lib/synapse/configuration/component/serialization/converter_factory.rb
@@ -203,6 +204,7 @@ files:
203
204
  - lib/synapse/common/identifier.rb
204
205
  - lib/synapse/common/duplication.rb
205
206
  - lib/synapse/common/concurrency/public_lock.rb
207
+ - lib/synapse/common/concurrency/executor.rb
206
208
  - lib/synapse/common/concurrency/identifier_lock.rb
207
209
  - lib/synapse/common/message.rb
208
210
  - lib/synapse/common/errors.rb
@@ -266,11 +268,11 @@ files:
266
268
  - test/repository/optimistic_test.rb
267
269
  - test/repository/locking_test.rb
268
270
  - test/test_helper.rb
269
- - test/event_sourcing/storage_listener_test.rb
270
271
  - test/event_sourcing/repository_test.rb
271
272
  - test/event_sourcing/aggregate_root_test.rb
272
273
  - test/event_sourcing/snapshot/interval_policy_test.rb
273
274
  - test/event_sourcing/snapshot/aggregate_taker_test.rb
275
+ - test/event_sourcing/caching_test.rb
274
276
  - test/event_sourcing/entity_test.rb
275
277
  - test/event_sourcing/fixtures.rb
276
278
  - test/event_sourcing/aggregate_factory_test.rb
@@ -333,6 +335,7 @@ files:
333
335
  - test/serialization/lazy_object_test.rb
334
336
  - test/serialization/serializer/oj_test.rb
335
337
  - test/serialization/serializer/ox_test.rb
338
+ - test/serialization/serializer/attribute_test.rb
336
339
  - test/serialization/serializer/marshal_test.rb
337
340
  - test/serialization/serialized_object_test.rb
338
341
  - test/serialization/revision_resolver_test.rb
@@ -353,7 +356,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
353
356
  version: '0'
354
357
  segments:
355
358
  - 0
356
- hash: -4187832660438552395
359
+ hash: 293343002242626074
357
360
  required_rubygems_version: !ruby/object:Gem::Requirement
358
361
  none: false
359
362
  requirements:
@@ -362,7 +365,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
362
365
  version: '0'
363
366
  segments:
364
367
  - 0
365
- hash: -4187832660438552395
368
+ hash: 293343002242626074
366
369
  requirements: []
367
370
  rubyforge_project:
368
371
  rubygems_version: 1.8.25