@@ -4,8 +4,7 @@ import * as orderedHistory from './orderedHistory'
4
4
5
5
import {
6
6
// action constants
7
- UPDATE_TIMESTAMP ,
8
- UPDATE_SOURCE ,
7
+ UPDATE_ACTION ,
9
8
10
9
META_TIMESTAMP ,
11
10
META_SOURCE
@@ -77,16 +76,16 @@ export default class Dispatcher extends Scuttlebutt {
77
76
78
77
this . _isGossipType = this . options . isGossipType
79
78
80
- // history of all current updates
81
- // timestamp-source-sorted for time travel and replay
82
- this . _updates = [ ]
83
79
84
80
// redux methods to wrap
85
81
this . _reduxDispatch = ( ) => {
86
82
throw new Error ( 'Are you sure you called wrapDispatch?' )
87
83
}
88
84
this . _reduxGetState = ( ) => {
89
- throw new Error ( 'Are you sure you called wrapGetState?' )
85
+ // throw new Error('Are you sure you called wrapGetState?')
86
+ // this must return a default state for the very first history call,
87
+ // before .wrapGetState has been applied in the store enhancer.
88
+ return [ ]
90
89
}
91
90
}
92
91
@@ -131,44 +130,50 @@ export default class Dispatcher extends Scuttlebutt {
131
130
// implemented for scuttlebutt class
132
131
applyUpdate ( update ) {
133
132
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
133
+ // copy the object so we can modify its properties later
134
+ localAction = { meta : { } , ...action } ,
135
+ dispatch = ( shouldApply ) => {
136
+ if ( ! shouldApply ) {
137
+ return
138
+ } else if ( this . _customDispatch ) {
139
+ this . _customDispatch ( localAction )
140
+ } else {
141
+ this . _reduxDispatch ( localAction )
141
142
}
142
143
}
143
144
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
- ) )
145
+ // add our metadata to the action as non-enumerable properties
146
+ Object . defineProperty ( localAction . meta , META_TIMESTAMP , {
147
+ enumerable : false ,
148
+ value : timestamp
149
+ } )
150
+ Object . defineProperty ( localAction . meta , META_SOURCE , {
151
+ enumerable : false ,
152
+ value : source
153
+ } )
155
154
156
- if ( this . _customDispatch ) {
157
- this . _customDispatch ( localAction )
158
- } else {
159
- this . _reduxDispatch ( localAction )
160
- }
155
+ dispatch ( true )
161
156
162
157
// recieved message succesfully. if false, peers may retry the message.
163
158
return true
164
159
}
165
160
166
- // gossip
161
+ // reply to gossip with the latest timestamps for the sources we've seen
167
162
// implemented for scuttlebutt class
168
163
history ( sources ) {
169
- return this . _updates . filter ( function ( update ) {
170
- return filter ( update , sources )
171
- } )
164
+ // our state (updates[]) has a similar shape to scuttlebutt's own updates.
165
+ return this . _reduxGetState ( ) . reduce ( ( arr , update ) => {
166
+ if (
167
+ update [ UPDATE_ACTION ]
168
+ && this . _isGossipType ( update [ UPDATE_ACTION ] . type )
169
+ && filter ( update , sources )
170
+ ) {
171
+ // scuttlebutt only wants ACTION, TIMESTAMP, SOURCE, and not: SNAPSHOT
172
+ arr . push ( update . slice ( 0 , 3 ) )
173
+ }
174
+
175
+ return arr
176
+ } , [ ] )
172
177
}
173
178
174
179
// apply an update locally
@@ -186,23 +191,4 @@ export default class Dispatcher extends Scuttlebutt {
186
191
super . localUpdate ( action )
187
192
}
188
193
}
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
194
}
0 commit comments