@matter/general 0.16.0-alpha.0-20250817-1b000357c → 0.16.0-alpha.0-20250820-24939dd26
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/cjs/codec/DnsCodec.d.ts +8 -6
- package/dist/cjs/codec/DnsCodec.d.ts.map +1 -1
- package/dist/cjs/codec/DnsCodec.js +10 -7
- package/dist/cjs/codec/DnsCodec.js.map +1 -1
- package/dist/cjs/crypto/Crypto.d.ts +32 -36
- package/dist/cjs/crypto/Crypto.d.ts.map +1 -1
- package/dist/cjs/environment/Environment.d.ts.map +1 -1
- package/dist/cjs/environment/Environment.js +2 -1
- package/dist/cjs/environment/Environment.js.map +1 -1
- package/dist/cjs/log/Diagnostic.d.ts +4 -6
- package/dist/cjs/log/Diagnostic.d.ts.map +1 -1
- package/dist/cjs/log/Diagnostic.js +6 -26
- package/dist/cjs/log/Diagnostic.js.map +1 -1
- package/dist/cjs/log/Logger.js +1 -1
- package/dist/cjs/log/Logger.js.map +1 -1
- package/dist/cjs/net/RetrySchedule.d.ts +10 -11
- package/dist/cjs/net/RetrySchedule.d.ts.map +1 -1
- package/dist/cjs/net/RetrySchedule.js +8 -7
- package/dist/cjs/net/RetrySchedule.js.map +1 -1
- package/dist/cjs/net/ServerAddress.d.ts +15 -4
- package/dist/cjs/net/ServerAddress.d.ts.map +1 -1
- package/dist/cjs/net/ServerAddress.js +33 -3
- package/dist/cjs/net/ServerAddress.js.map +2 -2
- package/dist/cjs/net/UdpMulticastServer.d.ts.map +1 -1
- package/dist/cjs/net/UdpMulticastServer.js +2 -1
- package/dist/cjs/net/UdpMulticastServer.js.map +1 -1
- package/dist/cjs/storage/StringifyTools.d.ts +2 -1
- package/dist/cjs/storage/StringifyTools.d.ts.map +1 -1
- package/dist/cjs/storage/StringifyTools.js +3 -0
- package/dist/cjs/storage/StringifyTools.js.map +1 -1
- package/dist/cjs/time/Duration.d.ts +47 -0
- package/dist/cjs/time/Duration.d.ts.map +1 -0
- package/dist/cjs/time/Duration.js +145 -0
- package/dist/cjs/time/Duration.js.map +6 -0
- package/dist/cjs/time/Time.d.ts +21 -19
- package/dist/cjs/time/Time.d.ts.map +1 -1
- package/dist/cjs/time/Time.js +44 -33
- package/dist/cjs/time/Time.js.map +1 -1
- package/dist/cjs/time/TimeUnit.d.ts +87 -0
- package/dist/cjs/time/TimeUnit.d.ts.map +1 -0
- package/dist/cjs/time/TimeUnit.js +88 -0
- package/dist/cjs/time/TimeUnit.js.map +6 -0
- package/dist/cjs/time/Timespan.d.ts +26 -0
- package/dist/cjs/time/Timespan.d.ts.map +1 -0
- package/dist/cjs/time/Timespan.js +52 -0
- package/dist/cjs/time/Timespan.js.map +6 -0
- package/dist/cjs/time/Timestamp.d.ts +47 -0
- package/dist/cjs/time/Timestamp.d.ts.map +1 -0
- package/dist/cjs/time/Timestamp.js +78 -0
- package/dist/cjs/time/Timestamp.js.map +6 -0
- package/dist/cjs/time/index.d.ts +4 -0
- package/dist/cjs/time/index.d.ts.map +1 -1
- package/dist/cjs/time/index.js +4 -0
- package/dist/cjs/time/index.js.map +1 -1
- package/dist/cjs/transaction/Status.d.ts +1 -1
- package/dist/cjs/transaction/Status.d.ts.map +1 -1
- package/dist/cjs/transaction/Status.js +2 -1
- package/dist/cjs/transaction/Status.js.map +1 -1
- package/dist/cjs/transaction/Tx.d.ts.map +1 -1
- package/dist/cjs/transaction/Tx.js +10 -8
- package/dist/cjs/transaction/Tx.js.map +1 -1
- package/dist/cjs/util/Cache.d.ts +5 -4
- package/dist/cjs/util/Cache.d.ts.map +1 -1
- package/dist/cjs/util/Cache.js +11 -11
- package/dist/cjs/util/Cache.js.map +1 -1
- package/dist/cjs/util/DataReadQueue.d.ts +2 -1
- package/dist/cjs/util/DataReadQueue.d.ts.map +1 -1
- package/dist/cjs/util/DataReadQueue.js +9 -3
- package/dist/cjs/util/DataReadQueue.js.map +1 -1
- package/dist/cjs/util/DeepEqual.d.ts +13 -1
- package/dist/cjs/util/DeepEqual.d.ts.map +1 -1
- package/dist/cjs/util/DeepEqual.js +24 -5
- package/dist/cjs/util/DeepEqual.js.map +2 -2
- package/dist/cjs/util/Observable.d.ts +4 -3
- package/dist/cjs/util/Observable.d.ts.map +1 -1
- package/dist/cjs/util/Observable.js +16 -15
- package/dist/cjs/util/Observable.js.map +1 -1
- package/dist/cjs/util/PromiseQueue.d.ts +2 -1
- package/dist/cjs/util/PromiseQueue.d.ts.map +1 -1
- package/dist/cjs/util/PromiseQueue.js +2 -1
- package/dist/cjs/util/PromiseQueue.js.map +1 -1
- package/dist/cjs/util/Promises.d.ts +3 -2
- package/dist/cjs/util/Promises.d.ts.map +1 -1
- package/dist/cjs/util/Promises.js +4 -4
- package/dist/cjs/util/Promises.js.map +1 -1
- package/dist/esm/codec/DnsCodec.d.ts +8 -6
- package/dist/esm/codec/DnsCodec.d.ts.map +1 -1
- package/dist/esm/codec/DnsCodec.js +10 -7
- package/dist/esm/codec/DnsCodec.js.map +1 -1
- package/dist/esm/crypto/Crypto.d.ts +32 -36
- package/dist/esm/crypto/Crypto.d.ts.map +1 -1
- package/dist/esm/environment/Environment.d.ts.map +1 -1
- package/dist/esm/environment/Environment.js +2 -1
- package/dist/esm/environment/Environment.js.map +1 -1
- package/dist/esm/log/Diagnostic.d.ts +4 -6
- package/dist/esm/log/Diagnostic.d.ts.map +1 -1
- package/dist/esm/log/Diagnostic.js +6 -26
- package/dist/esm/log/Diagnostic.js.map +1 -1
- package/dist/esm/log/Logger.js +1 -1
- package/dist/esm/log/Logger.js.map +1 -1
- package/dist/esm/net/RetrySchedule.d.ts +10 -11
- package/dist/esm/net/RetrySchedule.d.ts.map +1 -1
- package/dist/esm/net/RetrySchedule.js +8 -7
- package/dist/esm/net/RetrySchedule.js.map +1 -1
- package/dist/esm/net/ServerAddress.d.ts +15 -4
- package/dist/esm/net/ServerAddress.d.ts.map +1 -1
- package/dist/esm/net/ServerAddress.js +33 -3
- package/dist/esm/net/ServerAddress.js.map +2 -2
- package/dist/esm/net/UdpMulticastServer.d.ts.map +1 -1
- package/dist/esm/net/UdpMulticastServer.js +2 -1
- package/dist/esm/net/UdpMulticastServer.js.map +1 -1
- package/dist/esm/storage/StringifyTools.d.ts +2 -1
- package/dist/esm/storage/StringifyTools.d.ts.map +1 -1
- package/dist/esm/storage/StringifyTools.js +3 -0
- package/dist/esm/storage/StringifyTools.js.map +1 -1
- package/dist/esm/time/Duration.d.ts +47 -0
- package/dist/esm/time/Duration.d.ts.map +1 -0
- package/dist/esm/time/Duration.js +125 -0
- package/dist/esm/time/Duration.js.map +6 -0
- package/dist/esm/time/Time.d.ts +21 -19
- package/dist/esm/time/Time.d.ts.map +1 -1
- package/dist/esm/time/Time.js +44 -33
- package/dist/esm/time/Time.js.map +1 -1
- package/dist/esm/time/TimeUnit.d.ts +87 -0
- package/dist/esm/time/TimeUnit.d.ts.map +1 -0
- package/dist/esm/time/TimeUnit.js +68 -0
- package/dist/esm/time/TimeUnit.js.map +6 -0
- package/dist/esm/time/Timespan.d.ts +26 -0
- package/dist/esm/time/Timespan.d.ts.map +1 -0
- package/dist/esm/time/Timespan.js +32 -0
- package/dist/esm/time/Timespan.js.map +6 -0
- package/dist/esm/time/Timestamp.d.ts +47 -0
- package/dist/esm/time/Timestamp.d.ts.map +1 -0
- package/dist/esm/time/Timestamp.js +58 -0
- package/dist/esm/time/Timestamp.js.map +6 -0
- package/dist/esm/time/index.d.ts +4 -0
- package/dist/esm/time/index.d.ts.map +1 -1
- package/dist/esm/time/index.js +4 -0
- package/dist/esm/time/index.js.map +1 -1
- package/dist/esm/transaction/Status.d.ts +1 -1
- package/dist/esm/transaction/Status.d.ts.map +1 -1
- package/dist/esm/transaction/Status.js +2 -1
- package/dist/esm/transaction/Status.js.map +1 -1
- package/dist/esm/transaction/Tx.d.ts.map +1 -1
- package/dist/esm/transaction/Tx.js +10 -8
- package/dist/esm/transaction/Tx.js.map +1 -1
- package/dist/esm/util/Cache.d.ts +5 -4
- package/dist/esm/util/Cache.d.ts.map +1 -1
- package/dist/esm/util/Cache.js +11 -11
- package/dist/esm/util/Cache.js.map +1 -1
- package/dist/esm/util/DataReadQueue.d.ts +2 -1
- package/dist/esm/util/DataReadQueue.d.ts.map +1 -1
- package/dist/esm/util/DataReadQueue.js +9 -3
- package/dist/esm/util/DataReadQueue.js.map +1 -1
- package/dist/esm/util/DeepEqual.d.ts +13 -1
- package/dist/esm/util/DeepEqual.d.ts.map +1 -1
- package/dist/esm/util/DeepEqual.js +24 -5
- package/dist/esm/util/DeepEqual.js.map +2 -2
- package/dist/esm/util/Observable.d.ts +4 -3
- package/dist/esm/util/Observable.d.ts.map +1 -1
- package/dist/esm/util/Observable.js +16 -15
- package/dist/esm/util/Observable.js.map +1 -1
- package/dist/esm/util/PromiseQueue.d.ts +2 -1
- package/dist/esm/util/PromiseQueue.d.ts.map +1 -1
- package/dist/esm/util/PromiseQueue.js +2 -1
- package/dist/esm/util/PromiseQueue.js.map +1 -1
- package/dist/esm/util/Promises.d.ts +3 -2
- package/dist/esm/util/Promises.d.ts.map +1 -1
- package/dist/esm/util/Promises.js +4 -4
- package/dist/esm/util/Promises.js.map +1 -1
- package/package.json +3 -3
- package/src/codec/DnsCodec.ts +27 -8
- package/src/environment/Environment.ts +2 -1
- package/src/log/Diagnostic.ts +9 -37
- package/src/log/Logger.ts +1 -1
- package/src/net/RetrySchedule.ts +14 -14
- package/src/net/ServerAddress.ts +44 -5
- package/src/net/UdpMulticastServer.ts +2 -1
- package/src/storage/StringifyTools.ts +5 -0
- package/src/time/Duration.ts +181 -0
- package/src/time/Time.ts +50 -39
- package/src/time/TimeUnit.ts +159 -0
- package/src/time/Timespan.ts +52 -0
- package/src/time/Timestamp.ts +94 -0
- package/src/time/index.ts +4 -0
- package/src/transaction/Status.ts +2 -1
- package/src/transaction/Tx.ts +9 -7
- package/src/util/Cache.ts +11 -10
- package/src/util/DataReadQueue.ts +9 -3
- package/src/util/DeepEqual.ts +38 -13
- package/src/util/Observable.ts +19 -17
- package/src/util/PromiseQueue.ts +4 -2
- package/src/util/Promises.ts +6 -5
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Matter.js Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Duration } from "./Duration.js";
|
|
8
|
+
import { Timestamp } from "./Timestamp.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A period between two {@link Timestamp}s.
|
|
12
|
+
*/
|
|
13
|
+
export interface Timespan {
|
|
14
|
+
start: Timestamp;
|
|
15
|
+
stop: Timestamp;
|
|
16
|
+
duration: Duration;
|
|
17
|
+
|
|
18
|
+
from(newStart: Timestamp.Definition): Timespan;
|
|
19
|
+
to(newStart: Timestamp.Definition): Timespan;
|
|
20
|
+
valueOf(): { start: Timestamp; stop: Timestamp };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Create a new timespan representing time between {@link start} and {@link stop}.
|
|
25
|
+
*/
|
|
26
|
+
export function Timespan(start: Timestamp.Definition, stop: Timestamp.Definition) {
|
|
27
|
+
return Object.create(prototype, {
|
|
28
|
+
start: { value: Timestamp(start), enumerable: true },
|
|
29
|
+
stop: { value: Timestamp(stop), enumerable: true },
|
|
30
|
+
}) as Timespan;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const prototype: Timespan = {
|
|
34
|
+
start: 0 as Timestamp,
|
|
35
|
+
stop: 0 as Timestamp,
|
|
36
|
+
|
|
37
|
+
get duration() {
|
|
38
|
+
return (this.stop - this.start) as Duration;
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
from(this: Timespan, newStart) {
|
|
42
|
+
return Timespan(newStart, this.stop);
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
to(this: Timespan, newStop) {
|
|
46
|
+
return Timespan(this.start, newStop);
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
valueOf(this: Timespan) {
|
|
50
|
+
return { start: this.start, stop: this.stop };
|
|
51
|
+
},
|
|
52
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Matter.js Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { UnexpectedDataError } from "#MatterError.js";
|
|
8
|
+
import { Branded } from "#util/Type.js";
|
|
9
|
+
import { Time } from "./Time.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A UNIX epoch timestamp in milliseconds.
|
|
13
|
+
*
|
|
14
|
+
* Note that the precision of the timestamp may be greater than milliseconds but is limited to floating point precision.
|
|
15
|
+
*/
|
|
16
|
+
export type Timestamp = Branded<number, "Timestamp"> | 0;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Create a timestamp.
|
|
20
|
+
*
|
|
21
|
+
* Input may be a UNIX epoch value in milliseconds, a parseable date string, or a {@link Date}.
|
|
22
|
+
*/
|
|
23
|
+
export function Timestamp<T extends undefined | Timestamp.Definition>(
|
|
24
|
+
source: T,
|
|
25
|
+
): T extends undefined ? undefined | Timestamp : Timestamp {
|
|
26
|
+
if (source === undefined) {
|
|
27
|
+
return Time.nowMs;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (typeof source === "string") {
|
|
31
|
+
const date = Date.parse(source);
|
|
32
|
+
if (Number.isNaN(date.valueOf())) {
|
|
33
|
+
throw new TimestampFormatError("Invalid timestamp format");
|
|
34
|
+
}
|
|
35
|
+
} else if (typeof source === "object" && source !== null && source instanceof Date) {
|
|
36
|
+
if (Number.isNaN(source.valueOf())) {
|
|
37
|
+
throw new TimestampFormatError("Cannot convert date to timestamp because it is invalid");
|
|
38
|
+
}
|
|
39
|
+
source = source.getTime() as T;
|
|
40
|
+
} else if (typeof source === "bigint") {
|
|
41
|
+
source = Number(source) as T;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (typeof source === "number") {
|
|
45
|
+
if (Number.isNaN(source)) {
|
|
46
|
+
throw new TimestampFormatError("A timestamp may not be NaN");
|
|
47
|
+
}
|
|
48
|
+
} else {
|
|
49
|
+
throw new TimestampFormatError(`Timestamp is not a number (received ${typeof source})`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return source as Timestamp;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Thrown when a textual timestamp cannot be parsed.
|
|
57
|
+
*/
|
|
58
|
+
export class TimestampFormatError extends UnexpectedDataError {}
|
|
59
|
+
|
|
60
|
+
export namespace Timestamp {
|
|
61
|
+
/**
|
|
62
|
+
* Values that may be used to initialize a timestamp.
|
|
63
|
+
*/
|
|
64
|
+
export type Definition = number | bigint | string | Date;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Create a low-resolution timestamp from a seconds value.
|
|
68
|
+
*/
|
|
69
|
+
export function fromSeconds(source: number) {
|
|
70
|
+
return Math.floor(source * 1000);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Create a high-resolution timestamp from a microsecond value.
|
|
75
|
+
*/
|
|
76
|
+
export function fromMicroseconds(source: number | bigint) {
|
|
77
|
+
if (typeof source === "bigint") {
|
|
78
|
+
source = Number(source);
|
|
79
|
+
}
|
|
80
|
+
return Timestamp(source / 1000);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The UNIX epoch.
|
|
85
|
+
*/
|
|
86
|
+
export const zero = Timestamp(0);
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Obtain a {@link Date} for a {@link Timestamp}.
|
|
90
|
+
*/
|
|
91
|
+
export function dateOf(timestamp: Timestamp) {
|
|
92
|
+
return new Date(timestamp);
|
|
93
|
+
}
|
|
94
|
+
}
|
package/src/time/index.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { LogLevel } from "#log/LogLevel.js";
|
|
8
|
+
import { Millis } from "#time/TimeUnit.js";
|
|
8
9
|
import { TransactionFlowError } from "./errors.js";
|
|
9
10
|
import type { Transaction } from "./Transaction.js";
|
|
10
11
|
|
|
@@ -74,7 +75,7 @@ export namespace Status {
|
|
|
74
75
|
* A value of 0 forces lock reports for all async transactions; a negative value disables reporting.
|
|
75
76
|
*/
|
|
76
77
|
// eslint-disable-next-line prefer-const
|
|
77
|
-
export let
|
|
78
|
+
export let slowTransactionTime = Millis(200);
|
|
78
79
|
|
|
79
80
|
/**
|
|
80
81
|
* The log level for slow transaction reporting.
|
package/src/transaction/Tx.ts
CHANGED
|
@@ -8,6 +8,8 @@ import { Diagnostic } from "#log/Diagnostic.js";
|
|
|
8
8
|
import { Logger } from "#log/Logger.js";
|
|
9
9
|
import { ImplementationError, ReadOnlyError } from "#MatterError.js";
|
|
10
10
|
import { Time, Timer } from "#time/Time.js";
|
|
11
|
+
import { Timestamp } from "#time/Timestamp.js";
|
|
12
|
+
import { Millis } from "#time/TimeUnit.js";
|
|
11
13
|
import { asError } from "#util/Error.js";
|
|
12
14
|
import { Observable } from "#util/Observable.js";
|
|
13
15
|
import { MaybePromise } from "#util/Promises.js";
|
|
@@ -810,11 +812,11 @@ function throwIfErrored(errored: undefined | Array<Participant>, when: string) {
|
|
|
810
812
|
* "Slow" async transaction monitoring implementation.
|
|
811
813
|
*/
|
|
812
814
|
const Monitor = (function () {
|
|
813
|
-
const monitored = new Map<Tx,
|
|
815
|
+
const monitored = new Map<Tx, Timestamp>();
|
|
814
816
|
let monitor: Timer | undefined;
|
|
815
817
|
|
|
816
818
|
function check() {
|
|
817
|
-
const now = Time.nowMs
|
|
819
|
+
const now = Time.nowMs;
|
|
818
820
|
for (const [tx, slowAt] of monitored) {
|
|
819
821
|
if (now > slowAt) {
|
|
820
822
|
tx.treatAsSlow();
|
|
@@ -824,12 +826,12 @@ const Monitor = (function () {
|
|
|
824
826
|
|
|
825
827
|
return {
|
|
826
828
|
add(tx: Tx) {
|
|
827
|
-
const {
|
|
828
|
-
if (
|
|
829
|
+
const { slowTransactionTime } = Status;
|
|
830
|
+
if (slowTransactionTime < 0) {
|
|
829
831
|
return;
|
|
830
832
|
}
|
|
831
833
|
|
|
832
|
-
if (!
|
|
834
|
+
if (!slowTransactionTime) {
|
|
833
835
|
tx.treatAsSlow();
|
|
834
836
|
return;
|
|
835
837
|
}
|
|
@@ -838,9 +840,9 @@ const Monitor = (function () {
|
|
|
838
840
|
return;
|
|
839
841
|
}
|
|
840
842
|
|
|
841
|
-
monitored.set(tx, Time.nowMs
|
|
843
|
+
monitored.set(tx, Timestamp(Time.nowMs + slowTransactionTime));
|
|
842
844
|
if (monitor === undefined) {
|
|
843
|
-
monitor = Time.getPeriodicTimer("tx-lock-monitor",
|
|
845
|
+
monitor = Time.getPeriodicTimer("tx-lock-monitor", Millis(slowTransactionTime / 10), check);
|
|
844
846
|
monitor.start();
|
|
845
847
|
}
|
|
846
848
|
},
|
package/src/util/Cache.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* SPDX-License-Identifier: Apache-2.0
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { Duration } from "#time/Duration.js";
|
|
9
10
|
import { Diagnostic } from "../log/Diagnostic.js";
|
|
10
11
|
import { Time, Timer } from "../time/Time.js";
|
|
11
12
|
|
|
@@ -17,12 +18,12 @@ class GenericCache<T> {
|
|
|
17
18
|
|
|
18
19
|
constructor(
|
|
19
20
|
name: string,
|
|
20
|
-
private readonly
|
|
21
|
+
private readonly expiration: Duration,
|
|
21
22
|
private readonly expireCallback?: (key: string, value: T) => Promise<void>,
|
|
22
23
|
) {
|
|
23
24
|
this.periodicTimer = Time.getPeriodicTimer(
|
|
24
25
|
Diagnostic.upgrade(`${name} cache expiration`, [Diagnostic.strong(name), "cache expiration"]),
|
|
25
|
-
|
|
26
|
+
expiration,
|
|
26
27
|
() => this.expire(),
|
|
27
28
|
).start();
|
|
28
29
|
this.periodicTimer.utility = true;
|
|
@@ -56,9 +57,9 @@ class GenericCache<T> {
|
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
private async expire() {
|
|
59
|
-
const now = Time.nowMs
|
|
60
|
+
const now = Time.nowMs;
|
|
60
61
|
for (const [key, timestamp] of this.timestamps.entries()) {
|
|
61
|
-
if (now - timestamp < this.
|
|
62
|
+
if (now - timestamp < this.expiration) continue;
|
|
62
63
|
await this.delete(key);
|
|
63
64
|
}
|
|
64
65
|
}
|
|
@@ -68,10 +69,10 @@ export class Cache<T> extends GenericCache<T> {
|
|
|
68
69
|
constructor(
|
|
69
70
|
name: string,
|
|
70
71
|
private readonly generator: (...params: any[]) => T,
|
|
71
|
-
|
|
72
|
+
expiration: Duration,
|
|
72
73
|
expireCallback?: (key: string, value: T) => Promise<void>,
|
|
73
74
|
) {
|
|
74
|
-
super(name,
|
|
75
|
+
super(name, expiration, expireCallback);
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
get(...params: any[]) {
|
|
@@ -82,7 +83,7 @@ export class Cache<T> extends GenericCache<T> {
|
|
|
82
83
|
this.values.set(key, value);
|
|
83
84
|
this.knownKeys.add(key);
|
|
84
85
|
}
|
|
85
|
-
this.timestamps.set(key, Time.nowMs
|
|
86
|
+
this.timestamps.set(key, Time.nowMs);
|
|
86
87
|
return value;
|
|
87
88
|
}
|
|
88
89
|
}
|
|
@@ -91,10 +92,10 @@ export class AsyncCache<T> extends GenericCache<T> {
|
|
|
91
92
|
constructor(
|
|
92
93
|
name: string,
|
|
93
94
|
private readonly generator: (...params: any[]) => Promise<T>,
|
|
94
|
-
|
|
95
|
+
expiration: Duration,
|
|
95
96
|
expireCallback?: (key: string, value: T) => Promise<void>,
|
|
96
97
|
) {
|
|
97
|
-
super(name,
|
|
98
|
+
super(name, expiration, expireCallback);
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
async get(...params: any[]) {
|
|
@@ -105,7 +106,7 @@ export class AsyncCache<T> extends GenericCache<T> {
|
|
|
105
106
|
this.values.set(key, value);
|
|
106
107
|
this.knownKeys.add(key);
|
|
107
108
|
}
|
|
108
|
-
this.timestamps.set(key, Time.nowMs
|
|
109
|
+
this.timestamps.set(key, Time.nowMs);
|
|
109
110
|
return value;
|
|
110
111
|
}
|
|
111
112
|
}
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* SPDX-License-Identifier: Apache-2.0
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { Duration } from "#time/Duration.js";
|
|
10
|
+
import { Minutes } from "#time/TimeUnit.js";
|
|
9
11
|
import { MatterFlowError } from "../MatterError.js";
|
|
10
12
|
import { Time, Timer } from "../time/Time.js";
|
|
11
13
|
import { createPromise } from "./Promises.js";
|
|
@@ -16,7 +18,7 @@ export class DataReadQueue<T> implements Stream<T> {
|
|
|
16
18
|
#pendingRead?: { resolver: (data: T) => void; rejecter: (reason: any) => void; timeoutTimer?: Timer };
|
|
17
19
|
#closed = false;
|
|
18
20
|
|
|
19
|
-
async read(
|
|
21
|
+
async read(timeout = Minutes.one): Promise<T> {
|
|
20
22
|
const { promise, resolver, rejecter } = createPromise<T>();
|
|
21
23
|
if (this.#closed) throw new EndOfStreamError();
|
|
22
24
|
const data = this.#queue.shift();
|
|
@@ -27,8 +29,12 @@ export class DataReadQueue<T> implements Stream<T> {
|
|
|
27
29
|
this.#pendingRead = {
|
|
28
30
|
resolver,
|
|
29
31
|
rejecter,
|
|
30
|
-
timeoutTimer: Time.getTimer("Queue timeout",
|
|
31
|
-
rejecter(
|
|
32
|
+
timeoutTimer: Time.getTimer("Queue timeout", timeout, () =>
|
|
33
|
+
rejecter(
|
|
34
|
+
new NoResponseTimeoutError(
|
|
35
|
+
`Expected response data missing within timeout of ${Duration.format(timeout)}`,
|
|
36
|
+
),
|
|
37
|
+
),
|
|
32
38
|
).start(),
|
|
33
39
|
};
|
|
34
40
|
return promise;
|
package/src/util/DeepEqual.ts
CHANGED
|
@@ -4,19 +4,41 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* An object that supports custom deep equality.
|
|
9
|
+
*/
|
|
10
|
+
export interface DeepComparable {
|
|
11
|
+
/**
|
|
12
|
+
* Deep-compare this object to another.
|
|
13
|
+
*/
|
|
14
|
+
[DeepComparable.equals](other: unknown): boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export namespace DeepComparable {
|
|
18
|
+
export const equals = Symbol("deepEquals");
|
|
19
|
+
}
|
|
20
|
+
|
|
7
21
|
// TODO - implement more efficient specialization for Array and ArrayBuffer
|
|
8
22
|
// TODO - currently will hang on self-referential data structures
|
|
9
|
-
export function isDeepEqual(a:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
23
|
+
export function isDeepEqual(a: unknown, b: unknown, ignoreUndefinedProperties = false): boolean {
|
|
24
|
+
const aIsObject = typeof a === "object" && a !== null;
|
|
25
|
+
if (aIsObject) {
|
|
26
|
+
if (DeepComparable.equals in a) {
|
|
27
|
+
return (a as DeepComparable)[DeepComparable.equals](b);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const bIsObject = typeof b === "object" && b !== null;
|
|
32
|
+
if (bIsObject) {
|
|
33
|
+
if (DeepComparable.equals in b) {
|
|
34
|
+
return (b as DeepComparable)[DeepComparable.equals](a);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!aIsObject || !bIsObject) {
|
|
18
39
|
return a === b;
|
|
19
40
|
}
|
|
41
|
+
|
|
20
42
|
// Create arrays of property names
|
|
21
43
|
const aProps = Object.getOwnPropertyNames(a);
|
|
22
44
|
const bProps = Object.getOwnPropertyNames(b);
|
|
@@ -29,16 +51,19 @@ export function isDeepEqual(a: any, b: any, ignoreUndefinedProperties = false):
|
|
|
29
51
|
for (let i = 0; i < aProps.length; i++) {
|
|
30
52
|
const propName = aProps[i];
|
|
31
53
|
|
|
32
|
-
|
|
54
|
+
const aprop = (a as Record<string, unknown>)[propName];
|
|
55
|
+
const bprop = (b as Record<string, unknown>)[propName];
|
|
56
|
+
|
|
57
|
+
if (typeof aprop !== typeof bprop) {
|
|
33
58
|
return false;
|
|
34
59
|
}
|
|
35
|
-
if (typeof
|
|
36
|
-
if (!isDeepEqual(
|
|
60
|
+
if (typeof aprop === "object") {
|
|
61
|
+
if (!isDeepEqual(aprop, bprop)) {
|
|
37
62
|
return false;
|
|
38
63
|
}
|
|
39
64
|
} else {
|
|
40
65
|
// If values of same property are not equal, objects are not equivalent
|
|
41
|
-
if (
|
|
66
|
+
if (aprop !== bprop) {
|
|
42
67
|
return false;
|
|
43
68
|
}
|
|
44
69
|
}
|
package/src/util/Observable.ts
CHANGED
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { Duration } from "#time/Duration.js";
|
|
7
8
|
import { Time, Timer } from "#time/Time.js";
|
|
9
|
+
import { Instant, Millis, Seconds } from "#time/TimeUnit.js";
|
|
8
10
|
import { ImplementationError } from "../MatterError.js";
|
|
9
11
|
import { Logger } from "../log/Logger.js";
|
|
10
12
|
import "../polyfills/disposable.js";
|
|
@@ -654,7 +656,7 @@ export namespace ObserverGroup {
|
|
|
654
656
|
export class QuietObservable<T extends any[] = any[]> extends BasicObservable<T> implements QuietObservable.State<T> {
|
|
655
657
|
#emitAutomatically = QuietObservable.defaults.emitAutomatically;
|
|
656
658
|
#suppressionEnabled = QuietObservable.defaults.suppressionEnabled;
|
|
657
|
-
#
|
|
659
|
+
#minimumEmitInterval = QuietObservable.defaults.minimumEmitInterval;
|
|
658
660
|
#shouldEmit?: QuietObservable.EmitPredicate<T>;
|
|
659
661
|
#source?: Observable<T>;
|
|
660
662
|
#sink?: Observable<T>;
|
|
@@ -676,15 +678,15 @@ export class QuietObservable<T extends any[] = any[]> extends BasicObservable<T>
|
|
|
676
678
|
}
|
|
677
679
|
|
|
678
680
|
set config(config: QuietObservable.Configuration<T>) {
|
|
679
|
-
const { suppressionEnabled,
|
|
681
|
+
const { suppressionEnabled, minimumEmitInterval, emitAutomatically } = config;
|
|
680
682
|
if (emitAutomatically !== undefined) {
|
|
681
683
|
this.emitAutomatically = emitAutomatically;
|
|
682
684
|
}
|
|
683
685
|
if (suppressionEnabled !== undefined) {
|
|
684
686
|
this.suppressionEnabled = suppressionEnabled;
|
|
685
687
|
}
|
|
686
|
-
if (
|
|
687
|
-
this.
|
|
688
|
+
if (minimumEmitInterval !== undefined) {
|
|
689
|
+
this.minimumEmitInterval = minimumEmitInterval;
|
|
688
690
|
}
|
|
689
691
|
if ("shouldEmit" in config) {
|
|
690
692
|
this.shouldEmit = config.shouldEmit;
|
|
@@ -726,19 +728,19 @@ export class QuietObservable<T extends any[] = any[]> extends BasicObservable<T>
|
|
|
726
728
|
this.#suppressionEnabled = value;
|
|
727
729
|
}
|
|
728
730
|
|
|
729
|
-
get
|
|
730
|
-
return this.#
|
|
731
|
+
get minimumEmitInterval() {
|
|
732
|
+
return this.#minimumEmitInterval;
|
|
731
733
|
}
|
|
732
734
|
|
|
733
|
-
set
|
|
734
|
-
if (this.#
|
|
735
|
+
set minimumEmitInterval(value: Duration) {
|
|
736
|
+
if (this.#minimumEmitInterval === value) {
|
|
735
737
|
return;
|
|
736
738
|
}
|
|
737
739
|
const needStart = this.#emitTimer !== undefined;
|
|
738
740
|
if (needStart) {
|
|
739
741
|
this.#stop();
|
|
740
742
|
}
|
|
741
|
-
this.#
|
|
743
|
+
this.#minimumEmitInterval = value;
|
|
742
744
|
if (needStart) {
|
|
743
745
|
this.#start();
|
|
744
746
|
}
|
|
@@ -812,12 +814,12 @@ export class QuietObservable<T extends any[] = any[]> extends BasicObservable<T>
|
|
|
812
814
|
this.#deferredPayload = payload;
|
|
813
815
|
return;
|
|
814
816
|
}
|
|
815
|
-
const now = Time.nowMs
|
|
817
|
+
const now = Time.nowMs;
|
|
816
818
|
if (
|
|
817
819
|
immediate ||
|
|
818
820
|
!this.#suppressionEnabled ||
|
|
819
821
|
this.#lastEmitAt === undefined ||
|
|
820
|
-
this.#lastEmitAt + this.#
|
|
822
|
+
this.#lastEmitAt + this.#minimumEmitInterval < now
|
|
821
823
|
) {
|
|
822
824
|
return this.#emit(payload, now);
|
|
823
825
|
}
|
|
@@ -851,7 +853,7 @@ export class QuietObservable<T extends any[] = any[]> extends BasicObservable<T>
|
|
|
851
853
|
|
|
852
854
|
#emit(payload: T, now?: number) {
|
|
853
855
|
this.#deferredPayload = undefined;
|
|
854
|
-
this.#lastEmitAt = now ?? Time.nowMs
|
|
856
|
+
this.#lastEmitAt = now ?? Time.nowMs;
|
|
855
857
|
this.#stop();
|
|
856
858
|
super.emit(...payload);
|
|
857
859
|
}
|
|
@@ -861,11 +863,11 @@ export class QuietObservable<T extends any[] = any[]> extends BasicObservable<T>
|
|
|
861
863
|
return;
|
|
862
864
|
}
|
|
863
865
|
|
|
864
|
-
let timeout;
|
|
866
|
+
let timeout: Duration;
|
|
865
867
|
if (this.#lastEmitAt === undefined) {
|
|
866
|
-
timeout =
|
|
868
|
+
timeout = Instant;
|
|
867
869
|
} else {
|
|
868
|
-
timeout = this.#
|
|
870
|
+
timeout = Millis(this.#minimumEmitInterval - ((now ?? Time.nowMs) - this.#lastEmitAt));
|
|
869
871
|
}
|
|
870
872
|
|
|
871
873
|
if (timeout <= 0) {
|
|
@@ -900,7 +902,7 @@ export namespace QuietObservable {
|
|
|
900
902
|
/**
|
|
901
903
|
* The minimum time between emits in milliseconds.
|
|
902
904
|
*/
|
|
903
|
-
|
|
905
|
+
minimumEmitInterval: Duration;
|
|
904
906
|
|
|
905
907
|
/**
|
|
906
908
|
* An input observable this observable will automatically observe to produce events.
|
|
@@ -956,6 +958,6 @@ export namespace QuietObservable {
|
|
|
956
958
|
export const defaults: State = {
|
|
957
959
|
emitAutomatically: true,
|
|
958
960
|
suppressionEnabled: true,
|
|
959
|
-
|
|
961
|
+
minimumEmitInterval: Seconds.one,
|
|
960
962
|
};
|
|
961
963
|
}
|
package/src/util/PromiseQueue.ts
CHANGED
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { Duration } from "#time/Duration.js";
|
|
7
8
|
import { Time } from "#time/Time.js";
|
|
9
|
+
import { Instant } from "#time/TimeUnit.js";
|
|
8
10
|
import { Logger } from "../log/Logger.js";
|
|
9
11
|
import { createPromise } from "./Promises.js";
|
|
10
12
|
|
|
@@ -14,12 +16,12 @@ const logger = Logger.get("PromiseQueue");
|
|
|
14
16
|
* A queue that processes promises with a given concurrency and delays after each promise if desired.
|
|
15
17
|
*/
|
|
16
18
|
export class PromiseQueue {
|
|
17
|
-
readonly #delay:
|
|
19
|
+
readonly #delay: Duration;
|
|
18
20
|
readonly #queue = new Array<{ func: () => Promise<any>; rejecter: (reason?: any) => void }>();
|
|
19
21
|
readonly #concurrency: number;
|
|
20
22
|
#runningCount = 0;
|
|
21
23
|
|
|
22
|
-
constructor(concurrency = 1, delay =
|
|
24
|
+
constructor(concurrency = 1, delay = Instant) {
|
|
23
25
|
this.#concurrency = concurrency;
|
|
24
26
|
this.#delay = delay;
|
|
25
27
|
}
|
package/src/util/Promises.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* SPDX-License-Identifier: Apache-2.0
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { Duration } from "#time/Duration.js";
|
|
9
10
|
import { asError } from "#util/Error.js";
|
|
10
11
|
import { InternalError, TimeoutError } from "../MatterError.js";
|
|
11
12
|
import { Time } from "../time/Time.js";
|
|
@@ -74,12 +75,12 @@ export class PromiseTimeoutError extends TimeoutError {}
|
|
|
74
75
|
*
|
|
75
76
|
* By default, rejects with {@link PromiseTimeoutError} on timeout but you can override by supplying {@link cancel}.
|
|
76
77
|
*
|
|
77
|
-
* @param
|
|
78
|
+
* @param timeout the timeout in milliseconds
|
|
78
79
|
* @param promise a promise that resolves or rejects when the timed task completes
|
|
79
80
|
* @param cancel invoked on timeout (default implementation throws {@link PromiseTimeoutError})
|
|
80
81
|
*/
|
|
81
82
|
export async function withTimeout<T>(
|
|
82
|
-
|
|
83
|
+
timeout: Duration,
|
|
83
84
|
promise: Promise<T>,
|
|
84
85
|
cancel?: AbortController | (() => void),
|
|
85
86
|
): Promise<T> {
|
|
@@ -97,8 +98,8 @@ export async function withTimeout<T>(
|
|
|
97
98
|
let cancelTimer: undefined | (() => void);
|
|
98
99
|
|
|
99
100
|
// Sub-promise 1, the timer
|
|
100
|
-
const
|
|
101
|
-
const timer = Time.getTimer("promise-timeout",
|
|
101
|
+
const timedOut = new Promise<void>((resolve, reject) => {
|
|
102
|
+
const timer = Time.getTimer("promise-timeout", timeout, () => {
|
|
102
103
|
try {
|
|
103
104
|
cancelFn();
|
|
104
105
|
} catch (e) {
|
|
@@ -130,7 +131,7 @@ export async function withTimeout<T>(
|
|
|
130
131
|
);
|
|
131
132
|
|
|
132
133
|
// Output promise, resolves like input promise unless timed out
|
|
133
|
-
await Promise.all([
|
|
134
|
+
await Promise.all([timedOut, producer]);
|
|
134
135
|
|
|
135
136
|
return result as T;
|
|
136
137
|
}
|