statebus 6.1.21 → 6.1.24
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.
- package/client.js +133 -27
- package/package.json +1 -1
- package/server.js +16 -14
- package/statebus.js +9 -6
package/client.js
CHANGED
|
@@ -62,7 +62,8 @@
|
|
|
62
62
|
var preprefix = prefix.slice(0,-1)
|
|
63
63
|
var has_prefix = new RegExp('^' + preprefix)
|
|
64
64
|
var is_absolute = /^https?:\/\//
|
|
65
|
-
var
|
|
65
|
+
var subscriptions = {}
|
|
66
|
+
var put_counter = 0
|
|
66
67
|
//if (url[url.length-1]=='/') url = url.substr(0,url.length-1)
|
|
67
68
|
function add_prefix (key) {
|
|
68
69
|
return is_absolute.test(key) ? key : preprefix + key }
|
|
@@ -73,45 +74,149 @@
|
|
|
73
74
|
function rem_prefixes (obj) {
|
|
74
75
|
return bus.translate_keys(bus.clone(obj), rem_prefix) }
|
|
75
76
|
|
|
77
|
+
|
|
78
|
+
var puts = new Map()
|
|
79
|
+
function enqueue_put (url, body) {
|
|
80
|
+
var id = put_counter++
|
|
81
|
+
puts.set(id, {url: url, body: body, id: id})
|
|
82
|
+
send_put(id)
|
|
83
|
+
}
|
|
84
|
+
function send_put (id) {
|
|
85
|
+
try {
|
|
86
|
+
puts.get(id).status = 'sending'
|
|
87
|
+
braid_fetch(
|
|
88
|
+
puts.get(id).url,
|
|
89
|
+
{
|
|
90
|
+
method: 'put',
|
|
91
|
+
headers: {
|
|
92
|
+
'content-type': 'application/json',
|
|
93
|
+
'put-order': id,
|
|
94
|
+
},
|
|
95
|
+
body: puts.get(id).body
|
|
96
|
+
}
|
|
97
|
+
).then(function (res) {
|
|
98
|
+
if (res.status !== 200)
|
|
99
|
+
console.error('Server gave error on PUT:',
|
|
100
|
+
e, 'for', puts.get(id).body)
|
|
101
|
+
else
|
|
102
|
+
console.log('Successful put!', puts.get(id).body)
|
|
103
|
+
puts.delete(id)
|
|
104
|
+
}).catch(function (e) {
|
|
105
|
+
console.error('Error on PUT, waiting...', puts.get(id).url)
|
|
106
|
+
puts.get(id).status = 'waiting'
|
|
107
|
+
// console.error('Error on PUT:', e, 'for', puts.get(id).body)
|
|
108
|
+
// puts.delete(id)
|
|
109
|
+
})
|
|
110
|
+
} catch (e) {
|
|
111
|
+
console.error('Error on PUT, waiting...', puts.get(id).url)
|
|
112
|
+
puts.get(id).status = 'waiting'
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function retry_put (id) {
|
|
116
|
+
setTimeout(function () {send_put(id)}, 1000)
|
|
117
|
+
}
|
|
118
|
+
function send_all_puts () {
|
|
119
|
+
puts.keys().forEach(function (id) {
|
|
120
|
+
if (puts.get(id).status === 'waiting') {
|
|
121
|
+
console.log('Sending waiting put', id)
|
|
122
|
+
send_put(id)
|
|
123
|
+
}
|
|
124
|
+
})
|
|
125
|
+
}
|
|
126
|
+
|
|
76
127
|
bus(prefix).to_save = function (obj, t) {
|
|
77
128
|
bus.save.fire(obj)
|
|
78
129
|
|
|
130
|
+
enqueue_put(url + rem_prefix(obj.key),
|
|
131
|
+
JSON.stringify(obj.val))
|
|
79
132
|
// var x = {save: obj}
|
|
80
133
|
// if (t.version) x.version = t.version
|
|
81
134
|
// if (t.parents) x.parents = t.parents
|
|
82
135
|
// if (t.patch) x.patch = t.patch
|
|
83
136
|
// if (t.patch) x.save = rem_prefix(x.save.key)
|
|
84
|
-
|
|
85
|
-
braid_fetch(url + rem_prefix(obj.key),
|
|
86
|
-
{
|
|
87
|
-
method: 'put',
|
|
88
|
-
'content-type': 'application/json',
|
|
89
|
-
body: JSON.stringify(obj.val)
|
|
90
|
-
})
|
|
91
137
|
}
|
|
92
138
|
|
|
93
139
|
bus(prefix).to_fetch = function (key, t) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
140
|
+
// Subscription can be in states:
|
|
141
|
+
// - connecting
|
|
142
|
+
// - connected
|
|
143
|
+
// - reconnect
|
|
144
|
+
// - reconnecting
|
|
145
|
+
// - aborted
|
|
146
|
+
|
|
147
|
+
// If we have an outstanding fetch running, then let's tell it to
|
|
148
|
+
// re-activate!
|
|
149
|
+
if (subscriptions[key]) {
|
|
150
|
+
// We should only be here if an existing subscription was
|
|
151
|
+
// aborted, but hasn't cleared yet.
|
|
152
|
+
console.assert(subscriptions[key].status === 'aborted',
|
|
153
|
+
'Refetching a subscription of status '
|
|
154
|
+
+ subscriptions[key].status)
|
|
155
|
+
|
|
156
|
+
console.trace('foo')
|
|
157
|
+
|
|
158
|
+
// Let's tell it to reconnect when it tries to clear!
|
|
159
|
+
subscriptions[key].status = 'reconnect'
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Otherwise, create a new subscription
|
|
163
|
+
else
|
|
164
|
+
subscribe (key, t)
|
|
165
|
+
|
|
166
|
+
function subscribe (key, t) {
|
|
167
|
+
var aborter = new AbortController(),
|
|
168
|
+
reconnect_attempts = 0
|
|
169
|
+
|
|
170
|
+
// Start the subscription!
|
|
171
|
+
braid_fetch(
|
|
172
|
+
// URL
|
|
173
|
+
url + rem_prefix(key),
|
|
174
|
+
|
|
175
|
+
// Options
|
|
176
|
+
{
|
|
177
|
+
method: 'get',
|
|
178
|
+
subscribe: true,
|
|
179
|
+
headers: {accept: 'application/json'},
|
|
180
|
+
signal: aborter.signal
|
|
181
|
+
}
|
|
182
|
+
).andThen( function (x) {
|
|
183
|
+
// New update received!
|
|
184
|
+
if (subscriptions[key].status === 'connecting') {
|
|
185
|
+
console.log('%c[*] opened ' + key,
|
|
186
|
+
'color: blue')
|
|
187
|
+
reconnect_attempts = 0
|
|
188
|
+
subscriptions[key].status = 'connected'
|
|
189
|
+
send_all_puts()
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Return the update
|
|
193
|
+
t.return({
|
|
194
|
+
key: key,
|
|
195
|
+
val: add_prefixes(JSON.parse(x.body))
|
|
196
|
+
})
|
|
197
|
+
}).catch( function (e) {
|
|
198
|
+
if (subscriptions[key].status === 'aborted') {
|
|
199
|
+
// Then this fetch is over and done with!
|
|
200
|
+
delete subscriptions[key]
|
|
201
|
+
return
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Reconnect!
|
|
205
|
+
setTimeout(function () { subscribe(key, t) },
|
|
206
|
+
reconnect_attempts > 0 ? 5000 : 1500)
|
|
207
|
+
subscriptions[key].status = 'reconnecting'
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
// Remember this subscription
|
|
211
|
+
subscriptions[key] = {
|
|
212
|
+
aborter: aborter,
|
|
213
|
+
status: 'connecting'
|
|
214
|
+
}
|
|
109
215
|
}
|
|
110
|
-
client_fetched_keys.add(key)
|
|
111
216
|
}
|
|
112
217
|
bus(prefix).to_forget = function (key) {
|
|
113
|
-
|
|
114
|
-
|
|
218
|
+
subscriptions[key].status = 'aborted'
|
|
219
|
+
subscriptions[key].aborter.abort()
|
|
115
220
|
}
|
|
116
221
|
}
|
|
117
222
|
|
|
@@ -586,7 +691,8 @@
|
|
|
586
691
|
for (var k in this.props)
|
|
587
692
|
if (this.props.hasOwnProperty(k))
|
|
588
693
|
new_props[k] = this.props[k]
|
|
589
|
-
if (this.state.value)
|
|
694
|
+
if (this.state.hasOwnProperty('value'))
|
|
695
|
+
new_props.value = this.state.value
|
|
590
696
|
new_props.onChange = this.onChange
|
|
591
697
|
return element(new_props)
|
|
592
698
|
}
|
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -219,24 +219,25 @@ function import_server (bus, options)
|
|
|
219
219
|
cbus.fetch(key, cb = (o) => {
|
|
220
220
|
var body = bus.to_http_body(o)
|
|
221
221
|
|
|
222
|
-
//
|
|
223
|
-
// if (!body) {
|
|
224
|
-
// console.log('no body! time to 404')
|
|
225
|
-
// res.statusCode = 404
|
|
226
|
-
// res.end()
|
|
227
|
-
// }
|
|
228
|
-
|
|
229
|
-
// Or if we're braid, send via subscription
|
|
230
|
-
// else
|
|
222
|
+
// If we're braiding, send via subscription
|
|
231
223
|
if (braidify)
|
|
224
|
+
// Note: if body === undefined, we need to send the
|
|
225
|
+
// equivalent of a 404. This is missing in braid spec:
|
|
226
|
+
// https://github.com/braid-org/braid-spec/issues/110
|
|
232
227
|
res.sendVersion({body: body || 'null'})
|
|
233
228
|
|
|
234
229
|
// Or just return the current version
|
|
235
|
-
else
|
|
236
|
-
|
|
230
|
+
else {
|
|
231
|
+
if (body !== undefined)
|
|
232
|
+
res.send(body)
|
|
233
|
+
else {
|
|
234
|
+
res.statusCode = 404
|
|
235
|
+
res.end()
|
|
236
|
+
}
|
|
237
|
+
}
|
|
237
238
|
|
|
238
|
-
// And shut down the connection if
|
|
239
|
-
if (!braidify || !req.subscribe
|
|
239
|
+
// And shut down the connection if there's no subscription
|
|
240
|
+
if (!braidify || !req.subscribe)
|
|
240
241
|
end_it_all()
|
|
241
242
|
})
|
|
242
243
|
}
|
|
@@ -587,6 +588,7 @@ function import_server (bus, options)
|
|
|
587
588
|
}
|
|
588
589
|
})
|
|
589
590
|
|
|
591
|
+
// console.log('websocket listening on', '/' + bus.options.websocket_path)
|
|
590
592
|
s.installHandlers(httpserver, {prefix:'/' + bus.options.websocket_path})
|
|
591
593
|
},
|
|
592
594
|
|
|
@@ -595,7 +597,7 @@ function import_server (bus, options)
|
|
|
595
597
|
url = url.replace(/^istate:\/\//, 'ws://')
|
|
596
598
|
url = url.replace(/^statei:\/\//, 'ws://')
|
|
597
599
|
WebSocket = require('websocket').w3cwebsocket
|
|
598
|
-
return new WebSocket(url+'/'+bus.options.websocket_path+'/websocket')
|
|
600
|
+
return new WebSocket(url + '/' + bus.options.websocket_path + '/websocket')
|
|
599
601
|
},
|
|
600
602
|
client_creds: function client_creds (server_url) {
|
|
601
603
|
// Right now the server just creates a different random id each time
|
package/statebus.js
CHANGED
|
@@ -430,9 +430,11 @@
|
|
|
430
430
|
statelog(key, yellow, 'v', 'Deleting ' + key)
|
|
431
431
|
// Call the to_delete handlers
|
|
432
432
|
var handlers_called = bus.route(key, 'to_delete', key)
|
|
433
|
-
if (handlers_called === 0)
|
|
433
|
+
if (handlers_called === 0) {
|
|
434
434
|
// And go ahead and delete if there aren't any!
|
|
435
435
|
delete cache[key]
|
|
436
|
+
delete backup_cache[key]
|
|
437
|
+
}
|
|
436
438
|
|
|
437
439
|
// Call the on_delete handlers
|
|
438
440
|
bus.route(key, 'on_delete', cache[key] || {key: key}, t)
|
|
@@ -828,9 +830,10 @@
|
|
|
828
830
|
// except through an explicit .revise() function.
|
|
829
831
|
if (o) t.version = new_version()
|
|
830
832
|
|
|
831
|
-
if (method === 'to_delete')
|
|
833
|
+
if (method === 'to_delete') {
|
|
832
834
|
delete bus.cache[key]
|
|
833
|
-
|
|
835
|
+
delete bus.backup_cache[key]
|
|
836
|
+
} else if (method === 'to_save') {
|
|
834
837
|
bus.save.fire(o || arg, t)
|
|
835
838
|
bus.route(key, 'on_set_sync', o || arg, t)
|
|
836
839
|
} else {
|
|
@@ -2179,13 +2182,13 @@
|
|
|
2179
2182
|
if (a_array !== b_array) return ' = ' + JSON.stringify(b)
|
|
2180
2183
|
if (a_array) {
|
|
2181
2184
|
if (a.length === b.length-1
|
|
2182
|
-
&&
|
|
2183
|
-
return '.push(' +JSON.stringify(b[b.length]) + ')'
|
|
2185
|
+
&& deep_equals(a[a.length-1], b[b.length-2])) {
|
|
2186
|
+
return '.push(' +JSON.stringify(b[b.length-1]) + ')'
|
|
2184
2187
|
}
|
|
2185
2188
|
for (var i=0; i < a.length; i++) {
|
|
2186
2189
|
var tmp = sorta_diff (a[i], b[i])
|
|
2187
2190
|
if (tmp)
|
|
2188
|
-
return '['+i+']
|
|
2191
|
+
return '['+i+']'+tmp
|
|
2189
2192
|
}
|
|
2190
2193
|
return null
|
|
2191
2194
|
}
|