-
Notifications
You must be signed in to change notification settings - Fork 6
/
sparse-map.ts
110 lines (87 loc) · 3.2 KB
/
sparse-map.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import { Observable } from 'rxjs/Observable';
import { Updatable, MergeStrategy } from './updatable';
import './standard-operators';
export type Pair<K, V> = { Key: K, Value: V };
export interface SparseMap<K, V> {
listen(key: K, hint?: any): Updatable<V>;
listenAll(hint?: any): Map<K, Updatable<V>>;
setDirect(key: K, value: Updatable<V>): Promise<void>;
setLazy(key: K, value: Observable<V>): Promise<void>;
invalidate(key: K): Promise<void>;
};
export class SparseMapMixins {
static listenMany<K, V>(this: SparseMap<K, V>, keys: Array<K>, hint?: any): Map<K, Updatable<V>> {
return keys.reduce((acc, x) => {
acc.set(x, this.listen(x, hint));
return acc;
}, new Map<K, Updatable<V>>());
}
static get<K, V>(this: SparseMap<K, V>, key: K): Promise<V> {
return this.listen(key).take(1).toPromise();
}
static getMany<K, V>(this: SparseMap<K, V>, keys: Array<K>, hint?: any): Promise<Map<K, V>> {
return Observable.of(...keys)
.flatMap(k => this.listen(k, hint).take(1).map(v => ({Key: k, Value: v})))
.reduce((acc, x) => {
acc.set(x.Key, x.Value);
return acc;
}, new Map<K, V>())
.toPromise();
}
static setValue<K, V>(this: SparseMap<K, V>, key: K, value: V): Promise<void> {
return this.setLazy(key, Observable.of(value));
}
static setPromise<K, V>(this: SparseMap<K, V>, key: K, value: () => Promise<V>): Promise<void> {
return this.setLazy(key, Observable.defer(() => Observable.fromPromise(value())));
}
}
class InMemorySparseMap<K, V> implements SparseMap<K, V> {
private _latest: Map<K, Updatable<V>>;
private _factory: ((key: K, hint?: any) => Observable<V>) | undefined;
private _strategy: MergeStrategy;
constructor(factory: ((key: K, hint?: any) => Observable<V>) | undefined = undefined, strategy: MergeStrategy = 'overwrite') {
this._latest = new Map();
this._factory = factory;
this._strategy = strategy;
}
listen(key: K, hint?: any): Updatable<V> {
let ret = this._latest.get(key);
if (ret) return ret;
if (this._factory) {
let fact = this._factory.bind(this);
ret = new Updatable<V>(() => fact(key, hint), this._strategy);
} else {
ret = new Updatable<V>(undefined, this._strategy);
}
this._latest.set(key, ret);
return ret;
}
listenAll(hint?: any): Map<K, Updatable<V>> {
let ret = new Map<K, Updatable<V>>();
for (let k of this._latest.keys()) {
ret.set(k, this._latest.get(k));
}
return ret;
}
setDirect(key: K, value: Updatable<V>): Promise<void> {
let prev = this._latest.get(key);
if (prev) prev.playOnto(Observable.empty());
this._latest.set(key, value);
return Promise.resolve();
}
setLazy(key: K, value: Observable<V>): Promise<void> {
this.listen(key).playOnto(value);
return Promise.resolve();
}
invalidate(key: K): Promise<void> {
let val = this._latest.get(key);
if (val) {
// Release whatever subscription val's playOnto is holding currently
val.playOnto(Observable.empty());
this._latest.delete(key);
}
return Promise.resolve();
}
}
InMemorySparseMap.prototype = Object.assign(InMemorySparseMap.prototype, SparseMapMixins);
export { InMemorySparseMap };