@dra2020/baseclient 1.0.173 → 1.0.175
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/dist/baseclient.js +94 -12
- package/dist/baseclient.js.map +1 -1
- package/dist/fsm/fsm.d.ts +5 -0
- package/dist/geo/multiblockmapping.d.ts +6 -2
- package/lib/fsm/fsm.ts +47 -1
- package/lib/geo/multiblockmapping.ts +62 -8
- package/package.json +1 -1
package/dist/fsm/fsm.d.ts
CHANGED
|
@@ -15,15 +15,19 @@ export declare const FSM_CUSTOM7: number;
|
|
|
15
15
|
export declare const FSM_CUSTOM8: number;
|
|
16
16
|
export declare const FSM_CUSTOM9: number;
|
|
17
17
|
export type FsmIndex = Set<Fsm>;
|
|
18
|
+
export type FsmExceptionHandler = (fsm: Fsm, err: any) => void;
|
|
18
19
|
export declare class FsmManager {
|
|
19
20
|
theId: number;
|
|
20
21
|
theEpoch: number;
|
|
21
22
|
bTickSet: boolean;
|
|
22
23
|
theTickList: FsmIndex;
|
|
23
24
|
theBusyLoopCount: number;
|
|
25
|
+
theExceptionCount: number;
|
|
26
|
+
onException: FsmExceptionHandler;
|
|
24
27
|
constructor();
|
|
25
28
|
forceTick(fsm: Fsm): void;
|
|
26
29
|
doTick(): void;
|
|
30
|
+
tickException(f: Fsm, err: any): void;
|
|
27
31
|
}
|
|
28
32
|
export interface FsmEnvironment {
|
|
29
33
|
fsmManager: FsmManager;
|
|
@@ -55,6 +59,7 @@ export declare class Fsm {
|
|
|
55
59
|
waitOnCompleted(f: Fsm): void;
|
|
56
60
|
_completed(f: Fsm): void;
|
|
57
61
|
tick(): void;
|
|
62
|
+
tickException(err: any): void;
|
|
58
63
|
}
|
|
59
64
|
export declare class FsmOnDone extends Fsm {
|
|
60
65
|
cb: any;
|
|
@@ -14,14 +14,18 @@ export declare class MultiBlockMapping {
|
|
|
14
14
|
entries: Entry[];
|
|
15
15
|
stamp: number;
|
|
16
16
|
constructor(tag?: string, bm?: BlockMapping);
|
|
17
|
-
add(tag: string, bm: BlockMapping): void;
|
|
17
|
+
add(tag: string, bm: BlockMapping, rbm?: ReverseBlockMapping): void;
|
|
18
|
+
addFrom(src: MultiBlockMapping, tag?: string): void;
|
|
18
19
|
remove(tag: string): void;
|
|
20
|
+
has(tag: string): boolean;
|
|
19
21
|
map(blockid: string): string;
|
|
20
22
|
multimap(blockid: string): string[];
|
|
21
23
|
bmOf(tag: string): BlockMapping;
|
|
24
|
+
rbmOf(tag: string): ReverseBlockMapping;
|
|
22
25
|
mapmain(blockid: string): string;
|
|
23
26
|
rev(geoid: string): string[];
|
|
24
|
-
|
|
27
|
+
forEachBase(cb: (blockid: string) => void, tag?: string): void;
|
|
28
|
+
forEachBlock(cb: (blockid: string) => void): void;
|
|
25
29
|
forEachRev(cb: (geoidid: string, blocks: string[]) => void): void;
|
|
26
30
|
}
|
|
27
31
|
export {};
|
package/lib/fsm/fsm.ts
CHANGED
|
@@ -53,6 +53,8 @@ function FsmStateToString(state: number): string
|
|
|
53
53
|
|
|
54
54
|
export type FsmIndex = Set<Fsm>;
|
|
55
55
|
|
|
56
|
+
export type FsmExceptionHandler = (fsm: Fsm, err: any) => void;
|
|
57
|
+
|
|
56
58
|
export class FsmManager
|
|
57
59
|
{
|
|
58
60
|
theId: number;
|
|
@@ -60,6 +62,8 @@ export class FsmManager
|
|
|
60
62
|
bTickSet: boolean;
|
|
61
63
|
theTickList: FsmIndex;
|
|
62
64
|
theBusyLoopCount: number;
|
|
65
|
+
theExceptionCount: number;
|
|
66
|
+
onException: FsmExceptionHandler;
|
|
63
67
|
|
|
64
68
|
constructor()
|
|
65
69
|
{
|
|
@@ -68,6 +72,8 @@ export class FsmManager
|
|
|
68
72
|
this.bTickSet = false;
|
|
69
73
|
this.theTickList = new Set<Fsm>();
|
|
70
74
|
this.theBusyLoopCount = 0;
|
|
75
|
+
this.theExceptionCount = 0;
|
|
76
|
+
this.onException = (fsm: Fsm, err: any) => { console.error(`Fsm(${fsm.constructor.name}): exception in tick:`, err) };
|
|
71
77
|
this.doTick = this.doTick.bind(this);
|
|
72
78
|
}
|
|
73
79
|
|
|
@@ -92,7 +98,16 @@ export class FsmManager
|
|
|
92
98
|
let thisTickList = this.theTickList;
|
|
93
99
|
this.theTickList = new Set<Fsm>();
|
|
94
100
|
|
|
95
|
-
thisTickList.forEach((f: Fsm) =>
|
|
101
|
+
thisTickList.forEach((f: Fsm) => {
|
|
102
|
+
try
|
|
103
|
+
{
|
|
104
|
+
f.tick();
|
|
105
|
+
}
|
|
106
|
+
catch (err)
|
|
107
|
+
{
|
|
108
|
+
this.tickException(f, err);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
96
111
|
}
|
|
97
112
|
|
|
98
113
|
if (this.theTickList.size == 0)
|
|
@@ -102,6 +117,29 @@ export class FsmManager
|
|
|
102
117
|
|
|
103
118
|
this.theEpoch++;
|
|
104
119
|
}
|
|
120
|
+
|
|
121
|
+
// An exception escaping a tick would otherwise unwind out of setImmediate and take down the whole
|
|
122
|
+
// process (or, in the browser, leave the tick loop wedged). Instead, report it and let the Fsm
|
|
123
|
+
// fail itself so anything waiting on it sees a dependent error rather than hanging forever.
|
|
124
|
+
tickException(f: Fsm, err: any): void
|
|
125
|
+
{
|
|
126
|
+
this.theExceptionCount++;
|
|
127
|
+
try
|
|
128
|
+
{
|
|
129
|
+
this.onException(f, err);
|
|
130
|
+
}
|
|
131
|
+
catch (e) {}
|
|
132
|
+
try
|
|
133
|
+
{
|
|
134
|
+
f.tickException(err);
|
|
135
|
+
}
|
|
136
|
+
catch (e)
|
|
137
|
+
{
|
|
138
|
+
try { this.onException(f, e) } catch (e2) {}
|
|
139
|
+
if (! f.done)
|
|
140
|
+
f.setState(FSM_ERROR);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
105
143
|
}
|
|
106
144
|
|
|
107
145
|
export interface FsmEnvironment
|
|
@@ -225,6 +263,14 @@ export class Fsm
|
|
|
225
263
|
tick(): void
|
|
226
264
|
{
|
|
227
265
|
}
|
|
266
|
+
|
|
267
|
+
// Called (after FsmManager.onException has reported it) when tick() throws. Override to clean up or
|
|
268
|
+
// respond, but make sure the Fsm ends up done.
|
|
269
|
+
tickException(err: any): void
|
|
270
|
+
{
|
|
271
|
+
if (! this.done)
|
|
272
|
+
this.setState(FSM_ERROR);
|
|
273
|
+
}
|
|
228
274
|
}
|
|
229
275
|
|
|
230
276
|
// Launches callback provided when the associated Fsm (or Fsm array) completes.
|
|
@@ -21,6 +21,16 @@ export function reverseBlockMapping(bm: BlockMapping): ReverseBlockMapping
|
|
|
21
21
|
return rev;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
// A set of block mappings consulted as one, without copying any of them.
|
|
25
|
+
//
|
|
26
|
+
// Entries are either independent (e.g. one per state of a multi-state map, whose block ids never
|
|
27
|
+
// overlap) or overlapping (a base mapping followed by overrides such as precinct updates). Overlapping
|
|
28
|
+
// entries must be added in priority order: map() and rev() walk from the last entry back, so a later
|
|
29
|
+
// entry wins.
|
|
30
|
+
//
|
|
31
|
+
// A full block mapping, and the reverse mapping computed from it, are large (TX has ~670K blocks), so
|
|
32
|
+
// combining mappings shares them rather than copying: add() takes an already-computed reverse mapping,
|
|
33
|
+
// and addFrom() takes both from another MultiBlockMapping.
|
|
24
34
|
export class MultiBlockMapping
|
|
25
35
|
{
|
|
26
36
|
entries: Entry[];
|
|
@@ -34,14 +44,32 @@ export class MultiBlockMapping
|
|
|
34
44
|
this.entries.push({ tag, bm });
|
|
35
45
|
}
|
|
36
46
|
|
|
37
|
-
|
|
47
|
+
// Adds or replaces the entry for tag. Pass rbm when the reverse mapping of bm is already computed,
|
|
48
|
+
// so it is shared rather than built again.
|
|
49
|
+
add(tag: string, bm: BlockMapping, rbm?: ReverseBlockMapping): void
|
|
38
50
|
{
|
|
39
|
-
this.entries.
|
|
40
|
-
if (
|
|
41
|
-
|
|
51
|
+
let e = this.entries.find(e => e.tag === tag);
|
|
52
|
+
if (e)
|
|
53
|
+
{
|
|
54
|
+
e.bm = bm;
|
|
55
|
+
if (rbm) e.rbm = rbm; else delete e.rbm;
|
|
56
|
+
}
|
|
57
|
+
else
|
|
58
|
+
this.entries.push(rbm ? { tag, bm, rbm } : { tag, bm });
|
|
42
59
|
this.stamp++;
|
|
43
60
|
}
|
|
44
61
|
|
|
62
|
+
// Adds the entry for tag from another mapping - or, with no tag, all of its entries in order - sharing
|
|
63
|
+
// both the block mapping and its reverse mapping. The reverse mapping is computed on the source first
|
|
64
|
+
// if need be, so that it is built once, there, and not separately in each mapping that shares it.
|
|
65
|
+
addFrom(src: MultiBlockMapping, tag?: string): void
|
|
66
|
+
{
|
|
67
|
+
src.entries.forEach(e => {
|
|
68
|
+
if (tag === undefined || e.tag === tag)
|
|
69
|
+
this.add(e.tag, e.bm, src.rbmOf(e.tag));
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
45
73
|
remove(tag: string): void
|
|
46
74
|
{
|
|
47
75
|
for (let i = this.entries.length-1; i >= 0; i--)
|
|
@@ -52,6 +80,11 @@ export class MultiBlockMapping
|
|
|
52
80
|
}
|
|
53
81
|
}
|
|
54
82
|
|
|
83
|
+
has(tag: string): boolean
|
|
84
|
+
{
|
|
85
|
+
return this.entries.some(e => e.tag === tag);
|
|
86
|
+
}
|
|
87
|
+
|
|
55
88
|
map(blockid: string): string
|
|
56
89
|
{
|
|
57
90
|
// Walk backwards to pick up overrides first
|
|
@@ -77,6 +110,17 @@ export class MultiBlockMapping
|
|
|
77
110
|
return e ? e.bm : null;
|
|
78
111
|
}
|
|
79
112
|
|
|
113
|
+
// The reverse mapping of the entry for tag, computed on first use.
|
|
114
|
+
rbmOf(tag: string): ReverseBlockMapping
|
|
115
|
+
{
|
|
116
|
+
let e = this.entries.find(e => e.tag === tag);
|
|
117
|
+
if (! e) return null;
|
|
118
|
+
if (! e.rbm) e.rbm = reverseBlockMapping(e.bm);
|
|
119
|
+
return e.rbm;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Maps through the first entry only. Meaningful only where that entry is the base mapping and the
|
|
123
|
+
// rest are overrides; for independent entries (a multi-state mapping) use map().
|
|
80
124
|
mapmain(blockid: string): string
|
|
81
125
|
{
|
|
82
126
|
return this.entries.length ? this.entries[0].bm[blockid] : undefined;
|
|
@@ -95,11 +139,21 @@ export class MultiBlockMapping
|
|
|
95
139
|
return undefined;
|
|
96
140
|
}
|
|
97
141
|
|
|
98
|
-
//
|
|
99
|
-
|
|
142
|
+
// Walks the blocks of one entry: the one for tag, or with no tag the first. This is the right walk
|
|
143
|
+
// over "all blocks" only when that entry is a base mapping covering them and the others are overrides
|
|
144
|
+
// of it - it sees nothing of a multi-state mapping but its first state. See forEachBlock.
|
|
145
|
+
forEachBase(cb: (blockid: string) => void, tag?: string): void
|
|
146
|
+
{
|
|
147
|
+
let e = tag === undefined ? this.entries[0] : this.entries.find(e => e.tag === tag);
|
|
148
|
+
if (e)
|
|
149
|
+
Object.keys(e.bm).forEach(blockid => cb(blockid));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Walks the blocks of every entry. A block mapped by several entries (a base and its overrides) is
|
|
153
|
+
// visited once for each of them; independent entries (a multi-state mapping) never repeat a block.
|
|
154
|
+
forEachBlock(cb: (blockid: string) => void): void
|
|
100
155
|
{
|
|
101
|
-
|
|
102
|
-
Object.keys(this.entries[0].bm).forEach(blockid => cb(blockid));
|
|
156
|
+
this.entries.forEach(e => Object.keys(e.bm).forEach(blockid => cb(blockid)));
|
|
103
157
|
}
|
|
104
158
|
|
|
105
159
|
// Walk maps in reverse order, careful to not invoke on same geoid
|