@live-change/dao 0.3.11 → 0.3.15
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/lib/DaoCache.js +14 -14
- package/lib/DaoProxy.js +20 -6
- package/lib/ExtendedObservableList.js +2 -2
- package/lib/Observable.js +25 -11
- package/lib/ObservableList.js +4 -1
- package/lib/ObservablePromiseProxy.js +5 -2
- package/lib/ObservableProxy.js +19 -2
- package/lib/ObservableValue.js +4 -0
- package/lib/ReactiveServerConnection.js +21 -16
- package/package.json +1 -1
package/lib/DaoCache.js
CHANGED
|
@@ -30,14 +30,17 @@ class CacheState {
|
|
|
30
30
|
|
|
31
31
|
turnOff() {
|
|
32
32
|
if(!this.cached) throw new Error("uncache of not cached")
|
|
33
|
+
if(!this.observable) throw new Error("race condition")
|
|
33
34
|
this.cached = false
|
|
34
35
|
this.cache.cachedCount --
|
|
35
|
-
this.observable
|
|
36
|
+
const observable = this.observable
|
|
36
37
|
this.observable = null
|
|
38
|
+
observable.unobserve(this.cache.dummyObserver)
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
turnOn() {
|
|
40
42
|
if(this.cached) throw new Error("already cached")
|
|
43
|
+
if(this.observable) throw new Error("race condition")
|
|
41
44
|
this.cached = true
|
|
42
45
|
this.cache.cachedCount ++
|
|
43
46
|
this.cache.cache.push(this)
|
|
@@ -81,13 +84,7 @@ class CacheState {
|
|
|
81
84
|
if(delta > 0) {
|
|
82
85
|
this.score += delta * this.settings.singleReadScore
|
|
83
86
|
}
|
|
84
|
-
this.updateCacheState()
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
dipose() {
|
|
88
|
-
if(this.cached) {
|
|
89
|
-
this.observable.unobserve(this.cache.dummyObserver)
|
|
90
|
-
}
|
|
87
|
+
setTimeout(() => this.updateCacheState(), 0)
|
|
91
88
|
}
|
|
92
89
|
}
|
|
93
90
|
|
|
@@ -140,10 +137,13 @@ class DaoCache extends EventEmitter {
|
|
|
140
137
|
}
|
|
141
138
|
|
|
142
139
|
clear() {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
140
|
+
const now = Date.now()
|
|
141
|
+
for(const cacheState of this.cache) {
|
|
142
|
+
cacheState.score = 0
|
|
143
|
+
cacheState.scoreTime = now
|
|
144
|
+
if(cacheState.cached) cacheState.turnOff()
|
|
146
145
|
}
|
|
146
|
+
this.cache = []
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
clean() {
|
|
@@ -177,7 +177,6 @@ class DaoCache extends EventEmitter {
|
|
|
177
177
|
}
|
|
178
178
|
for(const [key, value] of this.cacheState.entries()) {
|
|
179
179
|
if(value.score < value.settings.deleteStatsScore) {
|
|
180
|
-
this.cacheState.dispose()
|
|
181
180
|
this.cacheState.delete(key)
|
|
182
181
|
}
|
|
183
182
|
}
|
|
@@ -197,8 +196,9 @@ class DaoCache extends EventEmitter {
|
|
|
197
196
|
|
|
198
197
|
noticeObserverCount(what, count, delta) {
|
|
199
198
|
//console.log("OBSERVER COUNT", JSON.stringify(what), count, "D", delta)
|
|
200
|
-
|
|
201
|
-
if(!cacheState) return
|
|
199
|
+
let cacheState = this.getOrCreateCacheState(what)
|
|
200
|
+
if(!cacheState && delta <= 0) return
|
|
201
|
+
cacheState = this.getOrCreateCacheState(what)
|
|
202
202
|
if(delta > 0) {
|
|
203
203
|
//console.log("CACHE TEST", cacheState.cached)
|
|
204
204
|
if(cacheState.observable) {
|
package/lib/DaoProxy.js
CHANGED
|
@@ -20,9 +20,11 @@ class DaoProxy extends EventEmitter {
|
|
|
20
20
|
this.dao = dao
|
|
21
21
|
if(this.dao) {
|
|
22
22
|
for(let [id, observable] of this.observables.entries()) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
if(!observable.disposed) {
|
|
24
|
+
let what = JSON.parse(id)
|
|
25
|
+
const target = this.dao.observable(what)
|
|
26
|
+
observable.setTarget(target)
|
|
27
|
+
}
|
|
26
28
|
}
|
|
27
29
|
if(this.dao.on) {
|
|
28
30
|
this.dao.on('connect', this.onConnect)
|
|
@@ -45,11 +47,23 @@ class DaoProxy extends EventEmitter {
|
|
|
45
47
|
} else {
|
|
46
48
|
observable = new ObservableProxy()
|
|
47
49
|
}
|
|
48
|
-
|
|
50
|
+
const oldDispose = observable.dispose
|
|
49
51
|
observable.dispose = (...args) => {
|
|
50
|
-
|
|
52
|
+
this.observables.delete(spath)
|
|
51
53
|
oldDispose.call(observable, ...args)
|
|
52
|
-
}
|
|
54
|
+
}
|
|
55
|
+
const oldRespawn = observable.respawn
|
|
56
|
+
observable.respawn = (...args) => {
|
|
57
|
+
const newObservable = this.observables.get(spath)
|
|
58
|
+
if(newObservable && newObservable !== observable) {
|
|
59
|
+
observable.observable = newObservable
|
|
60
|
+
} else if(this.dao) {
|
|
61
|
+
observable.observable = this.dao.observable(what)
|
|
62
|
+
} else {
|
|
63
|
+
observable.observable = null
|
|
64
|
+
}
|
|
65
|
+
oldRespawn.call(observable, ...args)
|
|
66
|
+
}
|
|
53
67
|
this.observables.set(JSON.stringify(what), observable)
|
|
54
68
|
return observable
|
|
55
69
|
}
|
|
@@ -30,11 +30,11 @@ class ExtendedObservableList extends ObservableList {
|
|
|
30
30
|
}
|
|
31
31
|
this.list = undefined
|
|
32
32
|
}
|
|
33
|
-
|
|
33
|
+
super.dispose.apply(this)
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
respawn() {
|
|
37
|
-
|
|
37
|
+
super.respawn.apply(this)
|
|
38
38
|
this.observableList.observe(this)
|
|
39
39
|
}
|
|
40
40
|
|
package/lib/Observable.js
CHANGED
|
@@ -22,7 +22,10 @@ class Observable {
|
|
|
22
22
|
fireObservers(signal, ...args) {
|
|
23
23
|
if(this.disposed) return
|
|
24
24
|
let handled = false
|
|
25
|
-
|
|
25
|
+
const observersToFire = this.observers
|
|
26
|
+
for(const observer of observersToFire) {
|
|
27
|
+
handled = this.fireObserver(observer, signal, ...args) || handled
|
|
28
|
+
}
|
|
26
29
|
if(signal == 'error') {
|
|
27
30
|
let error = args[0]
|
|
28
31
|
handled = this.handleError(error) || handled
|
|
@@ -90,27 +93,38 @@ class Observable {
|
|
|
90
93
|
|
|
91
94
|
wait() {
|
|
92
95
|
let finished = false
|
|
96
|
+
let resultObserver
|
|
97
|
+
let errorObserver
|
|
93
98
|
|
|
94
99
|
const waitPromise = new Promise((resolve, reject) => {
|
|
95
|
-
|
|
100
|
+
errorObserver = (error) => {
|
|
101
|
+
if(resultObserver) this.unobserve(resultObserver)
|
|
102
|
+
resultObserver = undefined
|
|
103
|
+
if(errorObserver) this.uncatch(errorObserver)
|
|
104
|
+
errorObserver = undefined
|
|
105
|
+
if(finished) return
|
|
96
106
|
finished = true
|
|
97
|
-
this.unobserve(resultObserver)
|
|
98
|
-
this.uncatch(errorObserver)
|
|
99
|
-
resolve(signal)
|
|
100
|
-
}
|
|
101
|
-
const errorObserver = (error) => {
|
|
102
|
-
finished = true
|
|
103
|
-
this.unobserve(resultObserver)
|
|
104
|
-
this.uncatch(errorObserver)
|
|
105
107
|
reject(error)
|
|
106
108
|
}
|
|
107
109
|
if(!finished) this.catch(errorObserver)
|
|
110
|
+
resultObserver = (signal) => {
|
|
111
|
+
if(resultObserver) this.unobserve(resultObserver)
|
|
112
|
+
resultObserver = undefined
|
|
113
|
+
if(errorObserver) this.uncatch(errorObserver)
|
|
114
|
+
errorObserver = undefined
|
|
115
|
+
if(finished) return
|
|
116
|
+
finished = true
|
|
117
|
+
resolve(signal)
|
|
118
|
+
}
|
|
108
119
|
if(!finished) this.observe(resultObserver)
|
|
109
120
|
})
|
|
110
121
|
waitPromise.cancel = () => {
|
|
111
|
-
finished = true
|
|
112
122
|
this.unobserve(resultObserver)
|
|
123
|
+
resultObserver = undefined
|
|
113
124
|
this.uncatch(errorObserver)
|
|
125
|
+
errorObserver = undefined
|
|
126
|
+
if(finished) return
|
|
127
|
+
finished = true
|
|
114
128
|
reject('canceled')
|
|
115
129
|
}
|
|
116
130
|
return waitPromise
|
package/lib/ObservableList.js
CHANGED
|
@@ -176,7 +176,7 @@ class ObservableList extends Observable {
|
|
|
176
176
|
this.errorProperties.splice(i, 1)
|
|
177
177
|
i--
|
|
178
178
|
if(this.isUseless()) this.dispose()
|
|
179
|
-
return
|
|
179
|
+
return
|
|
180
180
|
}
|
|
181
181
|
}
|
|
182
182
|
throw new Error("cannot unbind not bound property "+property)
|
|
@@ -282,6 +282,9 @@ class ObservableList extends Observable {
|
|
|
282
282
|
getValue() {
|
|
283
283
|
return this.list
|
|
284
284
|
}
|
|
285
|
+
getError() {
|
|
286
|
+
return this.savedError
|
|
287
|
+
}
|
|
285
288
|
}
|
|
286
289
|
|
|
287
290
|
module.exports = ObservableList
|
|
@@ -10,7 +10,8 @@ class ObservablePromiseProxy extends Observable {
|
|
|
10
10
|
this.observer = (signal, ...args) => {
|
|
11
11
|
this.fireObservers(signal, ...args)
|
|
12
12
|
}
|
|
13
|
-
promise
|
|
13
|
+
this.promise = promise
|
|
14
|
+
this.promise.then((result) => {
|
|
14
15
|
if(result.observe) {
|
|
15
16
|
this.init(result)
|
|
16
17
|
} else {
|
|
@@ -51,7 +52,9 @@ class ObservablePromiseProxy extends Observable {
|
|
|
51
52
|
}
|
|
52
53
|
}
|
|
53
54
|
getValue() {
|
|
54
|
-
|
|
55
|
+
if(!this.observable) return undefined
|
|
56
|
+
if(!this.observable.getValue) return undefined
|
|
57
|
+
return this.observable.getValue()
|
|
55
58
|
}
|
|
56
59
|
}
|
|
57
60
|
|
package/lib/ObservableProxy.js
CHANGED
|
@@ -17,6 +17,7 @@ class ObservableProxy extends Observable {
|
|
|
17
17
|
setTarget(observable) {
|
|
18
18
|
if(this === observable) throw new Error('infinite loop')
|
|
19
19
|
if(!this.disposed && this.observable) {
|
|
20
|
+
//console.log("SET TARGET UNOBSERVE TARGET")
|
|
20
21
|
this.observable.unobserve(this.observer)
|
|
21
22
|
for(let [object, property] of this.properties) {
|
|
22
23
|
this.observable.unbindProperty(object, property)
|
|
@@ -27,6 +28,7 @@ class ObservableProxy extends Observable {
|
|
|
27
28
|
}
|
|
28
29
|
this.observable = observable
|
|
29
30
|
if(!this.disposed && this.observable) {
|
|
31
|
+
//console.log("SET TARGET OBSERVE TARGET")
|
|
30
32
|
this.observable.observe(this.observer)
|
|
31
33
|
for(let [object, property] of this.properties) {
|
|
32
34
|
this.observable.bindProperty(object, property)
|
|
@@ -51,6 +53,7 @@ class ObservableProxy extends Observable {
|
|
|
51
53
|
|
|
52
54
|
reobserveTarget() {
|
|
53
55
|
if(!this.disposed && this.observable) {
|
|
56
|
+
//console.log("REOBSERVE TARGET!", this.observable)
|
|
54
57
|
this.observable.unobserve(this.observer)
|
|
55
58
|
this.observable.observe(this.observer)
|
|
56
59
|
}
|
|
@@ -64,13 +67,27 @@ class ObservableProxy extends Observable {
|
|
|
64
67
|
catch(...args) {
|
|
65
68
|
let beenDisposed = this.disposed
|
|
66
69
|
Observable.prototype.catch.apply(this, args)
|
|
67
|
-
if(!beenDisposed)
|
|
70
|
+
if(!beenDisposed) {
|
|
71
|
+
if(this.observable.getError) {
|
|
72
|
+
const error = this.observable.getError()
|
|
73
|
+
if(error) this.fireObserver(args[0], 'error', error)
|
|
74
|
+
} else {
|
|
75
|
+
this.reobserveTarget()
|
|
76
|
+
}
|
|
77
|
+
}
|
|
68
78
|
}
|
|
69
79
|
|
|
70
80
|
observe(...args) {
|
|
71
81
|
let beenDisposed = this.disposed
|
|
72
82
|
Observable.prototype.observe.apply(this, args)
|
|
73
|
-
if(!beenDisposed)
|
|
83
|
+
if(!beenDisposed) {
|
|
84
|
+
if(this.observable.getValue) {
|
|
85
|
+
const value = this.observable.getValue()
|
|
86
|
+
if(value !== undefined) this.fireObserver(args[0], 'set', value)
|
|
87
|
+
} else {
|
|
88
|
+
this.reobserveTarget()
|
|
89
|
+
}
|
|
90
|
+
}
|
|
74
91
|
}
|
|
75
92
|
|
|
76
93
|
bindProperty(object, property) {
|
package/lib/ObservableValue.js
CHANGED
|
@@ -389,8 +389,7 @@ class ReactiveServerConnection extends EventEmitter {
|
|
|
389
389
|
|
|
390
390
|
if(this.settings.fastAuth) {
|
|
391
391
|
try {
|
|
392
|
-
this.credentials
|
|
393
|
-
this.daoPromise = this.daoFactory(this.credentials, this.connection, this)
|
|
392
|
+
this.handleDaoPromise(this.daoFactory(this.credentials, this.connection, this))
|
|
394
393
|
} catch(error) {
|
|
395
394
|
return this.handleDaoFactoryError(error)
|
|
396
395
|
}
|
|
@@ -515,9 +514,11 @@ class ReactiveServerConnection extends EventEmitter {
|
|
|
515
514
|
handleUnobserve(message) {
|
|
516
515
|
const path = message.what
|
|
517
516
|
const spath = JSON.stringify(path)
|
|
518
|
-
|
|
517
|
+
debug('handle unobserve', spath)
|
|
519
518
|
const observation = this.observations.get(spath)
|
|
520
|
-
if(!observation)
|
|
519
|
+
if(!observation) {
|
|
520
|
+
throw new Error("Unobserve of not observed "+spath)
|
|
521
|
+
}
|
|
521
522
|
observation.unobserve(message.pushed)
|
|
522
523
|
}
|
|
523
524
|
|
|
@@ -696,6 +697,21 @@ class ReactiveServerConnection extends EventEmitter {
|
|
|
696
697
|
this.closeConnection()
|
|
697
698
|
}
|
|
698
699
|
|
|
700
|
+
handleDaoPromise(daoPromise) {
|
|
701
|
+
this.daoPromise = daoPromise
|
|
702
|
+
if(!this.daoPromise.then) {
|
|
703
|
+
this.dao = this.daoPromise
|
|
704
|
+
this.daoPromise = null
|
|
705
|
+
} else {
|
|
706
|
+
this.daoPromise.catch(error => this.handleDaoFactoryError(error)).then(dd => {
|
|
707
|
+
if(!dd) return this.handleDaoFactoryError("dao not defined")
|
|
708
|
+
this.dao = dd
|
|
709
|
+
this.daoPromise = null
|
|
710
|
+
for(const message of this.daoGenerationQueue) this.handleAuthorizedMessage(message)
|
|
711
|
+
})
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
|
|
699
715
|
handleMessage(message) {
|
|
700
716
|
if (!this.dao && !this.daoPromise) {
|
|
701
717
|
if (!message) {
|
|
@@ -704,21 +720,10 @@ class ReactiveServerConnection extends EventEmitter {
|
|
|
704
720
|
}
|
|
705
721
|
try {
|
|
706
722
|
this.credentials = message
|
|
707
|
-
this.
|
|
723
|
+
this.handleDaoPromise(this.daoFactory(this.credentials, this.connection, this))
|
|
708
724
|
} catch(error) {
|
|
709
725
|
return this.handleDaoFactoryError(error)
|
|
710
726
|
}
|
|
711
|
-
if(!this.daoPromise.then) {
|
|
712
|
-
this.dao = this.daoPromise
|
|
713
|
-
this.daoPromise = null
|
|
714
|
-
} else {
|
|
715
|
-
this.daoPromise.catch(error => this.handleDaoFactoryError(error)).then(dd => {
|
|
716
|
-
if(!dd) return this.handleDaoFactoryError("dao not defined")
|
|
717
|
-
this.dao = dd
|
|
718
|
-
this.daoPromise = null
|
|
719
|
-
for(const message of this.daoGenerationQueue) this.handleAuthorizedMessage(message)
|
|
720
|
-
})
|
|
721
|
-
}
|
|
722
727
|
} else if(this.daoPromise && !this.dao) {
|
|
723
728
|
this.daoGenerationQueue.push(message)
|
|
724
729
|
} else {
|
package/package.json
CHANGED