socket-function 1.1.48 → 1.1.49
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/index.d.ts +16 -1
- package/package.json +1 -1
- package/test.ts +5 -11
- package/time/trueTimeShim.d.ts +16 -1
- package/time/trueTimeShim.ts +43 -7
package/index.d.ts
CHANGED
|
@@ -1560,13 +1560,28 @@ declare module "socket-function/time/trueTimeShim" {
|
|
|
1560
1560
|
fromTime: number;
|
|
1561
1561
|
toTime: number;
|
|
1562
1562
|
};
|
|
1563
|
+
export declare function computeTweenedOffset(components: {
|
|
1564
|
+
systemTime: number;
|
|
1565
|
+
fromOffset: number;
|
|
1566
|
+
toOffset: number;
|
|
1567
|
+
fromTime: number;
|
|
1568
|
+
}): number;
|
|
1563
1569
|
export declare function getTimeComponents(): {
|
|
1564
1570
|
systemTime: number;
|
|
1565
1571
|
offset: number;
|
|
1566
1572
|
};
|
|
1567
1573
|
export declare function getTrueTime(): number;
|
|
1568
1574
|
export declare function getTrueTimeOffset(): number;
|
|
1569
|
-
export
|
|
1575
|
+
export type TrueTimeProof = {
|
|
1576
|
+
systemTime: number;
|
|
1577
|
+
fromOffset: number;
|
|
1578
|
+
toOffset: number;
|
|
1579
|
+
fromTime: number;
|
|
1580
|
+
toTime: number;
|
|
1581
|
+
offset: number;
|
|
1582
|
+
measurement?: TimeOffsetProof;
|
|
1583
|
+
};
|
|
1584
|
+
export declare function getTrueTimeProof(): TrueTimeProof | undefined;
|
|
1570
1585
|
export declare function waitForFirstTimeSync(): Promise<void> | undefined;
|
|
1571
1586
|
declare global {
|
|
1572
1587
|
var TRUE_TIME_ALREADY_SHIMMED: boolean;
|
package/package.json
CHANGED
package/test.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getTimeComponentsDetailed, waitForFirstTimeSync } from "./time/trueTimeShim";
|
|
1
|
+
import { computeTweenedOffset, getTimeComponentsDetailed, waitForFirstTimeSync } from "./time/trueTimeShim";
|
|
2
2
|
import * as fs from "fs";
|
|
3
3
|
import * as path from "path";
|
|
4
4
|
|
|
@@ -19,7 +19,6 @@ async function sampleMode() {
|
|
|
19
19
|
toOffset: number;
|
|
20
20
|
fromTime: number;
|
|
21
21
|
toTime: number;
|
|
22
|
-
fraction: number;
|
|
23
22
|
};
|
|
24
23
|
|
|
25
24
|
const samples: Sample[] = [];
|
|
@@ -28,11 +27,8 @@ async function sampleMode() {
|
|
|
28
27
|
for (let i = 0; i < SAMPLE_COUNT; i++) {
|
|
29
28
|
const detailed = getTimeComponentsDetailed();
|
|
30
29
|
|
|
31
|
-
// Calculate
|
|
32
|
-
const
|
|
33
|
-
const duration = detailed.toTime - detailed.fromTime;
|
|
34
|
-
const fraction = duration > 0 ? Math.min(1, elapsed / duration) : 0;
|
|
35
|
-
const offset = detailed.fromOffset + (detailed.toOffset - detailed.fromOffset) * fraction;
|
|
30
|
+
// Calculate the tween using the same systemTime
|
|
31
|
+
const offset = computeTweenedOffset(detailed);
|
|
36
32
|
|
|
37
33
|
samples.push({
|
|
38
34
|
id: TEST_RUN_ID,
|
|
@@ -42,7 +38,6 @@ async function sampleMode() {
|
|
|
42
38
|
toOffset: detailed.toOffset,
|
|
43
39
|
fromTime: detailed.fromTime,
|
|
44
40
|
toTime: detailed.toTime,
|
|
45
|
-
fraction,
|
|
46
41
|
});
|
|
47
42
|
|
|
48
43
|
if (SAMPLE_INTERVAL_MS > 0) {
|
|
@@ -88,7 +83,6 @@ async function verifyMode() {
|
|
|
88
83
|
toOffset: number;
|
|
89
84
|
fromTime: number;
|
|
90
85
|
toTime: number;
|
|
91
|
-
fraction: number;
|
|
92
86
|
file: string;
|
|
93
87
|
};
|
|
94
88
|
|
|
@@ -126,13 +120,13 @@ async function verifyMode() {
|
|
|
126
120
|
console.error(` systemTime: ${prev.systemTime}`);
|
|
127
121
|
console.error(` offset: ${prev.offset}`);
|
|
128
122
|
console.error(` trueTime: ${prevTrueTime}`);
|
|
129
|
-
console.error(`
|
|
123
|
+
console.error(` tween: ${prev.fromOffset} -> ${prev.toOffset}`);
|
|
130
124
|
console.error(` timeWindow: ${prev.fromTime} -> ${prev.toTime}`);
|
|
131
125
|
console.error(` Current [ID: ${sample.id}, file: ${sample.file}]:`);
|
|
132
126
|
console.error(` systemTime: ${sample.systemTime}`);
|
|
133
127
|
console.error(` offset: ${sample.offset}`);
|
|
134
128
|
console.error(` trueTime: ${trueTime}`);
|
|
135
|
-
console.error(`
|
|
129
|
+
console.error(` tween: ${sample.fromOffset} -> ${sample.toOffset}`);
|
|
136
130
|
console.error(` timeWindow: ${sample.fromTime} -> ${sample.toTime}`);
|
|
137
131
|
console.error(` Difference: ${trueTime - lastTrueTime}ms`);
|
|
138
132
|
}
|
package/time/trueTimeShim.d.ts
CHANGED
|
@@ -15,13 +15,28 @@ export declare function getTimeComponentsDetailed(): {
|
|
|
15
15
|
fromTime: number;
|
|
16
16
|
toTime: number;
|
|
17
17
|
};
|
|
18
|
+
export declare function computeTweenedOffset(components: {
|
|
19
|
+
systemTime: number;
|
|
20
|
+
fromOffset: number;
|
|
21
|
+
toOffset: number;
|
|
22
|
+
fromTime: number;
|
|
23
|
+
}): number;
|
|
18
24
|
export declare function getTimeComponents(): {
|
|
19
25
|
systemTime: number;
|
|
20
26
|
offset: number;
|
|
21
27
|
};
|
|
22
28
|
export declare function getTrueTime(): number;
|
|
23
29
|
export declare function getTrueTimeOffset(): number;
|
|
24
|
-
export
|
|
30
|
+
export type TrueTimeProof = {
|
|
31
|
+
systemTime: number;
|
|
32
|
+
fromOffset: number;
|
|
33
|
+
toOffset: number;
|
|
34
|
+
fromTime: number;
|
|
35
|
+
toTime: number;
|
|
36
|
+
offset: number;
|
|
37
|
+
measurement?: TimeOffsetProof;
|
|
38
|
+
};
|
|
39
|
+
export declare function getTrueTimeProof(): TrueTimeProof | undefined;
|
|
25
40
|
export declare function waitForFirstTimeSync(): Promise<void> | undefined;
|
|
26
41
|
declare global {
|
|
27
42
|
var TRUE_TIME_ALREADY_SHIMMED: boolean;
|
package/time/trueTimeShim.ts
CHANGED
|
@@ -22,6 +22,9 @@ const NTP_TIMEOUT = 1000 * 10;
|
|
|
22
22
|
// the real time to catch up with it.
|
|
23
23
|
const MINIMUM_TIME_RATE = 0.5;
|
|
24
24
|
|
|
25
|
+
// The offset tweens toward its target at this fraction of elapsed real time, then plateaus once it gets there. Must stay below 1 so output time keeps moving forward even while the offset is shrinking. Tweening across the whole transition window instead would mean a badly-off clock (many seconds) takes the entire window to converge, which breaks transactional consistency with other machines.
|
|
26
|
+
const OFFSET_TWEEN_RATE = 0.5;
|
|
27
|
+
|
|
25
28
|
const THROW_ON_ERROR = false;
|
|
26
29
|
|
|
27
30
|
// Hugely important as if we don't synchronize between processes, it means our logs are going to be confusing and out of order.
|
|
@@ -138,13 +141,24 @@ export function getTimeComponentsDetailed(): {
|
|
|
138
141
|
}
|
|
139
142
|
}
|
|
140
143
|
|
|
144
|
+
export function computeTweenedOffset(components: {
|
|
145
|
+
systemTime: number;
|
|
146
|
+
fromOffset: number;
|
|
147
|
+
toOffset: number;
|
|
148
|
+
fromTime: number;
|
|
149
|
+
}): number {
|
|
150
|
+
const elapsed = Math.max(0, components.systemTime - components.fromTime);
|
|
151
|
+
const delta = components.toOffset - components.fromOffset;
|
|
152
|
+
const maxChange = elapsed * OFFSET_TWEEN_RATE;
|
|
153
|
+
if (Math.abs(delta) <= maxChange) {
|
|
154
|
+
return components.toOffset;
|
|
155
|
+
}
|
|
156
|
+
return components.fromOffset + Math.sign(delta) * maxChange;
|
|
157
|
+
}
|
|
158
|
+
|
|
141
159
|
export function getTimeComponents(): { systemTime: number; offset: number } {
|
|
142
160
|
const detailed = getTimeComponentsDetailed();
|
|
143
|
-
|
|
144
|
-
const duration = detailed.toTime - detailed.fromTime;
|
|
145
|
-
const fraction = duration > 0 ? Math.min(1, elapsed / duration) : 0;
|
|
146
|
-
const offset = detailed.fromOffset + (detailed.toOffset - detailed.fromOffset) * fraction;
|
|
147
|
-
return { systemTime: detailed.systemTime, offset };
|
|
161
|
+
return { systemTime: detailed.systemTime, offset: computeTweenedOffset(detailed) };
|
|
148
162
|
}
|
|
149
163
|
|
|
150
164
|
export function getTrueTime() {
|
|
@@ -174,8 +188,30 @@ export function getTrueTimeOffset() {
|
|
|
174
188
|
const { offset } = getTimeComponents();
|
|
175
189
|
return offset;
|
|
176
190
|
}
|
|
177
|
-
export
|
|
178
|
-
|
|
191
|
+
export type TrueTimeProof = {
|
|
192
|
+
systemTime: number;
|
|
193
|
+
// The tween endpoints the current offset is moving between. When offset !== toOffset we are still converging.
|
|
194
|
+
fromOffset: number;
|
|
195
|
+
toOffset: number;
|
|
196
|
+
fromTime: number;
|
|
197
|
+
toTime: number;
|
|
198
|
+
offset: number;
|
|
199
|
+
// The raw measurement that produced the newest offset. Undefined if the offset came from a caller-provided base that only returns numbers.
|
|
200
|
+
measurement?: TimeOffsetProof;
|
|
201
|
+
};
|
|
202
|
+
export function getTrueTimeProof(): TrueTimeProof | undefined {
|
|
203
|
+
const data = cachedTimeOffsetData;
|
|
204
|
+
if (!data) return undefined;
|
|
205
|
+
const detailed = getTimeComponentsDetailed();
|
|
206
|
+
return {
|
|
207
|
+
systemTime: detailed.systemTime,
|
|
208
|
+
fromOffset: detailed.fromOffset,
|
|
209
|
+
toOffset: detailed.toOffset,
|
|
210
|
+
fromTime: detailed.fromTime,
|
|
211
|
+
toTime: detailed.toTime,
|
|
212
|
+
offset: computeTweenedOffset(detailed),
|
|
213
|
+
measurement: data.proof,
|
|
214
|
+
};
|
|
179
215
|
}
|
|
180
216
|
export function waitForFirstTimeSync(): Promise<void> | undefined {
|
|
181
217
|
if (didFirstTimeSync) return undefined;
|