@@ -77,16 +77,16 @@ export default class Dispatcher extends Scuttlebutt {
77
77
78
78
this . _isGossipType = this . options . isGossipType
79
79
80
- // history of all current updates
81
- // timestamp-source-sorted for time travel and replay
82
- this . _updates = [ ]
83
80
84
81
// redux methods to wrap
85
82
this . _reduxDispatch = ( ) => {
86
83
throw new Error ( 'Are you sure you called wrapDispatch?' )
87
84
}
88
85
this . _reduxGetState = ( ) => {
89
- throw new Error ( 'Are you sure you called wrapGetState?' )
86
+ // throw new Error('Are you sure you called wrapGetState?')
87
+ // this must return a default state for the very first history call,
88
+ // before .wrapGetState has been applied in the store enhancer.
89
+ return [ ]
90
90
}
91
91
}
92
92
@@ -131,44 +131,50 @@ export default class Dispatcher extends Scuttlebutt {
131
131
// implemented for scuttlebutt class
132
132
applyUpdate ( update ) {
133
133
const [ action , timestamp , source ] = update ,
134
- // add our metadata to the action
135
- localAction = {
136
- ...action ,
137
- meta : {
138
- ...action . meta ,
139
- [ META_TIMESTAMP ] : timestamp ,
140
- [ META_SOURCE ] : source
134
+ // copy the object so we can modify its properties later
135
+ localAction = { meta : { } , ...action } ,
136
+ dispatch = ( shouldApply ) => {
137
+ if ( ! shouldApply ) {
138
+ return
139
+ } else if ( this . _customDispatch ) {
140
+ this . _customDispatch ( localAction )
141
+ } else {
142
+ this . _reduxDispatch ( localAction )
141
143
}
142
144
}
143
145
144
- // we log all updates to emit in the order we saw them.
145
- // not sure if it's better than replaying in order of timestamp (which might
146
- // cut down on the amount of time travelling done by all peers), but seems
147
- // like the de facto for scuttlebutt models
148
- this . _updates . push ( update )
149
-
150
- // this could be sped up by only sorting as far as the new update
151
- this . _updates . sort ( ( a , b ) => orderedHistory . sort (
152
- a [ UPDATE_TIMESTAMP ] , b [ UPDATE_TIMESTAMP ] ,
153
- a [ UPDATE_SOURCE ] , b [ UPDATE_SOURCE ]
154
- ) )
146
+ // add our metadata to the action as non-enumerable properties
147
+ Object . defineProperty ( localAction . meta , META_TIMESTAMP , {
148
+ enumerable : false ,
149
+ value : timestamp
150
+ } )
151
+ Object . defineProperty ( localAction . meta , META_SOURCE , {
152
+ enumerable : false ,
153
+ value : source
154
+ } )
155
155
156
- if ( this . _customDispatch ) {
157
- this . _customDispatch ( localAction )
158
- } else {
159
- this . _reduxDispatch ( localAction )
160
- }
156
+ dispatch ( true )
161
157
162
158
// recieved message succesfully. if false, peers may retry the message.
163
159
return true
164
160
}
165
161
166
- // gossip
162
+ // reply to gossip with the latest timestamps for the sources we've seen
167
163
// implemented for scuttlebutt class
168
164
history ( sources ) {
169
- return this . _updates . filter ( function ( update ) {
170
- return filter ( update , sources )
171
- } )
165
+ // our state (updates[]) has a similar shape to scuttlebutt's own updates.
166
+ return this . _reduxGetState ( ) . reduce ( ( arr , update ) => {
167
+ if (
168
+ update [ UPDATE_ACTION ]
169
+ && this . _isGossipType ( update [ UPDATE_ACTION ] . type )
170
+ && filter ( update , sources )
171
+ ) {
172
+ // scuttlebutt only wants ACTION, TIMESTAMP, SOURCE, and not: SNAPSHOT
173
+ arr . push ( update . slice ( 0 , 3 ) )
174
+ }
175
+
176
+ return arr
177
+ } , [ ] )
172
178
}
173
179
174
180
// apply an update locally
@@ -186,23 +192,4 @@ export default class Dispatcher extends Scuttlebutt {
186
192
super . localUpdate ( action )
187
193
}
188
194
}
189
-
190
- // super.localUpdate(this._filterUpdate(action))
191
- // Recurse through the value and attempt to prune unserializable leaf objects.
192
- // A well-structured app won't be dispatching bad actions like this, so
193
- // this might become a dev-only check. also, it's far from foolproof.
194
- _filterUpdate ( value ) {
195
- if ( typeof value !== 'object' )
196
- return value
197
-
198
- if ( value && value . constructor
199
- && / ( ^ S y n t h e t i c | E v e n t $ ) / . test ( value . constructor . name ) )
200
- return null
201
-
202
- const result = { }
203
- for ( const prop in value ) {
204
- result [ prop ] = this . _filterUpdate ( value [ prop ] ) ;
205
- }
206
- return result
207
- }
208
195
}
0 commit comments