metacosm 0.2.13 → 0.2.14

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: f78fea361e727ab756d606811ca59e1f52a5b1e5
4
- data.tar.gz: b6539a027a2cf2bac9270b3c60b8a3246b35c228
3
+ metadata.gz: 68f1b5dd4218a10775dfe6aae1afc0b4db1e295d
4
+ data.tar.gz: b6d7707b7b226b4d30a8f1d3a89e275aee2973b2
5
5
  SHA512:
6
- metadata.gz: c34e16473d596582f095fa4785cb01e0de4f7a3436eae237b582ed504a1c9555950892afe4a643fbc85716cbb473d40b5d149778d0acbc4e2d7cc1f22f1a6ee4
7
- data.tar.gz: 15c5c5734f37cd1a1c088822027127dedc861381a25d3934fc6d622905fdec38666c12c299eb3acdbf9e3cc23f7be77430ab6867502bf4cc1bf4c2e2269ec107
6
+ metadata.gz: f6aaa059326435c46219c6205a21892b999980d9fc40d1108e1ec7ed47052206698098f94b8e7ce40c5a009002f38ce15c081337b2eb4f08a95b67d119e05d42
7
+ data.tar.gz: 8653b0c85c98fa87b1e09036ecc01e7e5ede20696b56e57ba660843951bba77c63ad7ce48ed150c494185ffb3a339514f72b18ed4983cff08fd12675c072a1e6
data/README.md CHANGED
@@ -10,181 +10,24 @@
10
10
 
11
11
  Metacosm is an awesome microframework for building reactive systems.
12
12
 
13
- The idea is to enable quick prototyping of command-query separated or event-sourced systems.
13
+ ## Goals
14
14
 
15
- One core concept is that we use commands to update "write-only" models,
16
- which trigger events that update "read-only" view models that are used by queries.
15
+ Enable quick prototyping of command-query separated architectures, and empower development of event-sourced systems.
16
+
17
+ ## Background
18
+
19
+ One core concept is that we use commands to update "write-only" models, which trigger events that update "read-only" view models that are used by queries.
17
20
 
18
21
  Models only transform their state in response to commands, so their state can be reconstructed by replaying the stream of commands.
19
22
 
20
23
  ## Features
21
24
 
22
- - One interesting feature here is a sort of mock in-memory AR component called `Registrable` that is used for internal tests (note: this has been extracted to [PassiveRecord](http://github.com/deepcerulean/passive_record))
25
+ - Distributed simulations using Redis
23
26
 
24
27
  ## Examples
25
28
 
26
-
27
- Below is a Fizzbuzz implementation contrived enough to show off many of the features of the framework.
28
-
29
- You may also want to [look at this repository](https://github.com/jweissman/gol) which implements Conway's game of life using metacosm and gosu.
30
-
31
- ````ruby
32
- require 'metacosm'
33
- include Metacosm
34
-
35
- class Counter < Model
36
- def initialize
37
- @counter = 0
38
- super
39
- end
40
-
41
- def fizz!
42
- emit fizz
43
- end
44
-
45
- def buzz!
46
- emit buzz
47
- end
48
-
49
- def increment!(inc)
50
- @counter += inc
51
- emit(counter_incremented)
52
- end
53
-
54
- protected
55
- def fizz
56
- FizzEvent.create
57
- end
58
-
59
- def buzz
60
- BuzzEvent.create
61
- end
62
-
63
- def counter_incremented
64
- CounterIncrementedEvent.create(
65
- value: @counter,
66
- counter_id: @id
67
- )
68
- end
69
- end
70
-
71
- class CounterView < View
72
- attr_accessor :value, :counter_id
73
- def update_value(new_value)
74
- @value = new_value
75
- self
76
- end
77
- end
78
-
79
- class IncrementCounterCommand < Command
80
- attr_accessor :increment, :counter_id
81
- end
82
-
83
- class IncrementCounterCommandHandler
84
- def handle(increment:,counter_id:)
85
- counter = Counter.find(counter_id)
86
- counter.increment!(increment)
87
- end
88
- end
89
-
90
- class CounterIncrementedEvent < Event
91
- attr_accessor :value, :counter_id
92
- end
93
-
94
- class CounterIncrementedEventListener < EventListener
95
- def receive(value:,counter_id:)
96
- update_counter_view(counter_id, value)
97
-
98
- fizz_buzz!(counter_id, value)
99
- puts(value) unless fizz?(value) || buzz?(value)
100
- end
101
-
102
- def update_counter_view(counter_id, value)
103
- counter_view = CounterView.where(counter_id: counter_id).first_or_create
104
- counter_view.update value: value
105
- end
106
-
107
- private
108
- def fizz_buzz!(counter_id, n)
109
- fire(FizzCommand.create(counter_id: counter_id)) if fizz?(n)
110
- fire(BuzzCommand.create(counter_id: counter_id)) if buzz?(n)
111
- end
112
-
113
- def fizz?(n); n % 3 == 0 end
114
- def buzz?(n); n % 5 == 0 end
115
- end
116
-
117
- class FizzCommand < Command
118
- attr_accessor :counter_id
119
- end
120
-
121
- class FizzCommandHandler
122
- def handle(counter_id:)
123
- counter = Counter.find(counter_id)
124
- counter.fizz!
125
- end
126
- end
127
-
128
- class BuzzCommand < Command
129
- attr_accessor :counter_id
130
- end
131
-
132
- class BuzzCommandHandler
133
- def handle(counter_id:)
134
- counter = Counter.find(counter_id)
135
- counter.buzz!
136
- end
137
- end
138
-
139
- class FizzEvent < Event
140
- end
141
-
142
- class FizzEventListener < EventListener
143
- def receive
144
- puts "fizz"
145
- end
146
- end
147
-
148
- class BuzzEvent < Event
149
- end
150
-
151
- class BuzzEventListener < EventListener
152
- def receive
153
- puts "buzz"
154
- end
155
- end
156
- ````
157
-
158
- Given all this prelude we can run a fizzbuzz "simulation":
159
-
160
- ````ruby
161
- sim = Simulation.current
162
- counter_model = Counter.create
163
- counter_view = CounterView.find_by(counter_id: counter_model.id)
164
-
165
- counter_view.value # => 0
166
-
167
- increment_counter_command = IncrementCounterCommand.create(
168
- increment: 1, counter_id: counter_model.id
169
- )
170
-
171
- sim.apply(increment_counter_command)
172
-
173
- counter_view.value # => 1
174
-
175
- 100.times { sim.apply(increment_counter_command) }
176
-
177
- sim.events.take(10)
178
- # => [CounterCreatedEvent (id: 1, counter_id: 1),
179
- # CounterIncrementedEvent (id: 1, value: 1, counter_id: 1),
180
- # CounterIncrementedEvent (id: 2, value: 2, counter_id: 1),
181
- # CounterIncrementedEvent (id: 3, value: 3, counter_id: 1),
182
- # FizzEvent (id: 1),
183
- # CounterIncrementedEvent (id: 4, value: 4, counter_id: 1),
184
- # CounterIncrementedEvent (id: 5, value: 5, counter_id: 1),
185
- # BuzzEvent (id: 1),
186
- # CounterIncrementedEvent (id: 6, value: 6, counter_id: 1)]
187
- ````
29
+ - [Game of Life](https://github.com/jweissman/gol), which implements Conway's game of life using metacosm and gosu
30
+ - [Socius](http://github.com/jweissman/socius), a civlike using the Redis integration to communicate with a game server running the sim
188
31
 
189
32
  ## Requirements
190
33
 
@@ -1,6 +1,8 @@
1
1
  module Metacosm
2
2
  class RemoteSimulation < Simulation
3
- def initialize
3
+ def initialize(command_queue, event_stream)
4
+ @command_queue_name = command_queue
5
+ @event_stream_name = event_stream
4
6
  setup_connection
5
7
  end
6
8
 
@@ -11,14 +13,14 @@ module Metacosm
11
13
  def fire(command)
12
14
  command_dto = command.attrs.merge(handler_module: command.handler_module_name, handler_class_name: command.handler_class_name)
13
15
  redis = redis_connection
14
- redis.publish(:socius_command_queue, Marshal.dump(command_dto))
16
+ redis.publish(@command_queue_name, Marshal.dump(command_dto))
15
17
  end
16
18
 
17
19
  def setup_connection
18
20
  @remote_listener_thread = Thread.new do
19
21
  begin
20
22
  redis = redis_connection
21
- redis.subscribe(:socius_event_stream) do |on|
23
+ redis.subscribe(@event_stream_name) do |on|
22
24
  on.subscribe do |channel, subscriptions|
23
25
  puts "Subscribed to remote simulation event stream ##{channel} (#{subscriptions} subscriptions)"
24
26
  end
@@ -1,4 +1,4 @@
1
1
  module Metacosm
2
2
  # metacosm version
3
- VERSION = "0.2.13"
3
+ VERSION = "0.2.14"
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metacosm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.13
4
+ version: 0.2.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joseph Weissman