@talex-touch/utils 1.0.30 → 1.0.32
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/animation/window-node.ts +205 -0
- package/animation/window.ts +19 -15
- package/auth/clerk-types.ts +1 -1
- package/auth/index.ts +1 -1
- package/auth/useAuthState.ts +6 -5
- package/auth/useClerkConfig.ts +6 -6
- package/auth/useClerkProvider.ts +3 -2
- package/channel/index.ts +28 -21
- package/common/file-scan-constants.ts +137 -121
- package/common/file-scan-utils.ts +49 -25
- package/common/index.ts +3 -3
- package/common/search/gather.ts +1 -1
- package/common/search/index.ts +5 -6
- package/common/storage/constants.ts +3 -2
- package/common/storage/entity/app-settings.ts +19 -3
- package/common/storage/entity/shortcut-settings.ts +10 -10
- package/common/storage/shortcut-storage.ts +6 -4
- package/common/utils/file.ts +15 -4
- package/common/utils/index.ts +62 -52
- package/common/utils/polling.ts +114 -63
- package/common/utils/task-queue.ts +11 -10
- package/common/utils/time.ts +50 -47
- package/common/utils/timing.ts +41 -37
- package/core-box/builder/index.ts +1 -1
- package/core-box/builder/tuff-builder.ts +255 -230
- package/core-box/index.ts +3 -6
- package/core-box/preview/index.ts +1 -0
- package/core-box/preview/types.ts +43 -0
- package/core-box/tuff/index.ts +1 -1
- package/core-box/tuff/tuff-dsl.ts +419 -253
- package/electron/clipboard-helper.ts +20 -12
- package/electron/download-manager.ts +43 -42
- package/electron/env-tool.ts +19 -18
- package/electron/file-parsers/index.ts +2 -2
- package/electron/file-parsers/parsers/text-parser.ts +15 -14
- package/electron/file-parsers/registry.ts +9 -7
- package/electron/file-parsers/types.ts +4 -4
- package/electron/index.ts +1 -1
- package/eventbus/index.ts +11 -11
- package/index.ts +6 -5
- package/intelligence/client.ts +87 -0
- package/intelligence/index.ts +1 -0
- package/package.json +14 -14
- package/permission/index.ts +8 -8
- package/plugin/channel.ts +77 -68
- package/plugin/index.ts +113 -84
- package/plugin/install.ts +8 -8
- package/plugin/log/types.ts +5 -5
- package/plugin/node/index.ts +1 -1
- package/plugin/node/logger-manager.ts +14 -11
- package/plugin/node/logger.ts +8 -8
- package/plugin/plugin-source.ts +11 -11
- package/plugin/preload.ts +6 -3
- package/plugin/providers/registry.ts +8 -7
- package/plugin/providers/types.ts +6 -6
- package/plugin/sdk/channel.ts +20 -20
- package/plugin/sdk/clipboard.ts +8 -6
- package/plugin/sdk/common.ts +10 -6
- package/plugin/sdk/core-box.ts +2 -3
- package/plugin/sdk/division-box.ts +266 -0
- package/plugin/sdk/enum/bridge-event.ts +1 -1
- package/plugin/sdk/examples/storage-onDidChange-example.js +1 -1
- package/plugin/sdk/features.ts +34 -26
- package/plugin/sdk/hooks/bridge.ts +3 -6
- package/plugin/sdk/hooks/index.ts +1 -1
- package/plugin/sdk/hooks/life-cycle.ts +4 -10
- package/plugin/sdk/index.ts +9 -13
- package/plugin/sdk/service/index.ts +3 -3
- package/plugin/sdk/storage.ts +4 -4
- package/plugin/sdk/system.ts +1 -1
- package/plugin/sdk/types.ts +169 -143
- package/plugin/sdk/window/index.ts +8 -5
- package/preload/loading.ts +6 -6
- package/preload/renderer.ts +4 -2
- package/renderer/hooks/arg-mapper.ts +1 -2
- package/renderer/hooks/index.ts +2 -0
- package/renderer/hooks/initialize.ts +10 -8
- package/renderer/hooks/performance.ts +4 -4
- package/renderer/hooks/use-channel.ts +150 -0
- package/renderer/hooks/use-intelligence.ts +236 -0
- package/renderer/index.ts +6 -1
- package/renderer/ref.ts +32 -36
- package/renderer/slots.ts +29 -26
- package/renderer/storage/app-settings.ts +16 -6
- package/renderer/storage/base-storage.ts +236 -88
- package/renderer/storage/index.ts +3 -0
- package/renderer/storage/intelligence-storage.ts +215 -0
- package/renderer/storage/openers.ts +13 -3
- package/renderer/touch-sdk/env.ts +41 -41
- package/renderer/touch-sdk/index.ts +1 -1
- package/renderer/touch-sdk/terminal.ts +5 -5
- package/renderer/touch-sdk/utils.ts +4 -3
- package/search/levenshtein-utils.ts +11 -11
- package/search/types.ts +102 -103
- package/service/index.ts +11 -11
- package/service/protocol/index.ts +217 -14
- package/types/division-box.ts +248 -0
- package/types/download.ts +72 -34
- package/types/icon.ts +2 -1
- package/types/index.ts +3 -1
- package/types/intelligence.ts +413 -0
- package/types/modules/base.ts +16 -16
- package/types/modules/index.ts +1 -1
- package/types/modules/module-lifecycle.ts +21 -21
- package/types/modules/module-manager.ts +11 -11
- package/types/modules/module.ts +16 -16
- package/types/storage.ts +0 -1
- package/types/touch-app-core.ts +32 -32
- package/types/update.ts +79 -21
- package/core-box/README.md +0 -218
- package/core-box/builder/tuff-builder.example.ts.bak +0 -258
- package/core-box/run-tests.sh +0 -7
- package/core-box/search.ts +0 -1
|
@@ -36,8 +36,9 @@ export interface AdaptiveTaskQueueOptions {
|
|
|
36
36
|
const DEFAULT_YIELD_INTERVAL_MS = 17
|
|
37
37
|
|
|
38
38
|
async function delay(ms: number): Promise<void> {
|
|
39
|
-
if (ms <= 0)
|
|
40
|
-
|
|
39
|
+
if (ms <= 0)
|
|
40
|
+
return
|
|
41
|
+
await new Promise<void>(resolve => setTimeout(resolve, ms))
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
/**
|
|
@@ -50,10 +51,11 @@ async function delay(ms: number): Promise<void> {
|
|
|
50
51
|
export async function runAdaptiveTaskQueue<T>(
|
|
51
52
|
items: readonly T[],
|
|
52
53
|
handler: (item: T, index: number) => Promise<void> | void,
|
|
53
|
-
options: AdaptiveTaskQueueOptions = {}
|
|
54
|
+
options: AdaptiveTaskQueueOptions = {},
|
|
54
55
|
): Promise<void> {
|
|
55
56
|
const total = items.length
|
|
56
|
-
if (total === 0)
|
|
57
|
+
if (total === 0)
|
|
58
|
+
return
|
|
57
59
|
|
|
58
60
|
const {
|
|
59
61
|
estimatedTaskTimeMs = 1,
|
|
@@ -61,7 +63,7 @@ export async function runAdaptiveTaskQueue<T>(
|
|
|
61
63
|
maxBatchSize,
|
|
62
64
|
logger = console,
|
|
63
65
|
label = 'AdaptiveTaskQueue',
|
|
64
|
-
onYield
|
|
66
|
+
onYield,
|
|
65
67
|
} = options
|
|
66
68
|
|
|
67
69
|
const safeTaskMs = Math.max(estimatedTaskTimeMs, 0.1)
|
|
@@ -71,11 +73,10 @@ export async function runAdaptiveTaskQueue<T>(
|
|
|
71
73
|
const currentPerformance = typeof globalThis !== 'undefined' ? (globalThis as any)?.performance : undefined
|
|
72
74
|
const now = () => (currentPerformance ? currentPerformance.now() : Date.now())
|
|
73
75
|
|
|
74
|
-
|
|
75
76
|
const startTime = now()
|
|
76
77
|
|
|
77
78
|
logger.debug?.(
|
|
78
|
-
`[${label}] Starting queue for ${total} item(s). batchSize=${batchSize}, estimated=${safeTaskMs.toFixed(2)}ms
|
|
79
|
+
`[${label}] Starting queue for ${total} item(s). batchSize=${batchSize}, estimated=${safeTaskMs.toFixed(2)}ms`,
|
|
79
80
|
)
|
|
80
81
|
|
|
81
82
|
for (let index = 0; index < total; index++) {
|
|
@@ -90,19 +91,19 @@ export async function runAdaptiveTaskQueue<T>(
|
|
|
90
91
|
logger.debug?.(
|
|
91
92
|
`[${label}] Yielded after ${processed}/${total} item(s); wait ${(
|
|
92
93
|
afterYield - beforeYield
|
|
93
|
-
).toFixed(1)}ms
|
|
94
|
+
).toFixed(1)}ms`,
|
|
94
95
|
)
|
|
95
96
|
onYield?.({
|
|
96
97
|
processed,
|
|
97
98
|
total,
|
|
98
99
|
batchSize,
|
|
99
|
-
elapsedMs
|
|
100
|
+
elapsedMs,
|
|
100
101
|
})
|
|
101
102
|
}
|
|
102
103
|
}
|
|
103
104
|
|
|
104
105
|
const endTime = now()
|
|
105
106
|
logger.debug?.(
|
|
106
|
-
`[${label}] Completed ${total} item(s) in ${((endTime - startTime) / 1000).toFixed(2)}s
|
|
107
|
+
`[${label}] Completed ${total} item(s) in ${((endTime - startTime) / 1000).toFixed(2)}s`,
|
|
107
108
|
)
|
|
108
109
|
}
|
package/common/utils/time.ts
CHANGED
|
@@ -19,11 +19,11 @@ export class TimeoutError extends Error {
|
|
|
19
19
|
* @param message - An optional message describing the timeout error. Defaults to 'Operation timed out'.
|
|
20
20
|
*/
|
|
21
21
|
constructor(message: string = 'Operation timed out') {
|
|
22
|
-
super(message)
|
|
23
|
-
this.name = 'TimeoutError'
|
|
22
|
+
super(message)
|
|
23
|
+
this.name = 'TimeoutError'
|
|
24
24
|
// Maintain proper stack trace for the error.
|
|
25
25
|
if (Error.captureStackTrace) {
|
|
26
|
-
Error.captureStackTrace(this, TimeoutError)
|
|
26
|
+
Error.captureStackTrace(this, TimeoutError)
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
}
|
|
@@ -62,19 +62,19 @@ export class TimeoutError extends Error {
|
|
|
62
62
|
export function withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {
|
|
63
63
|
if (ms <= 0) {
|
|
64
64
|
// If timeout is 0 or negative, return the original Promise without a timeout mechanism.
|
|
65
|
-
return promise
|
|
65
|
+
return promise
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
// Create a promise that rejects in <ms> milliseconds
|
|
69
69
|
const timeout = new Promise<never>((_, reject) => {
|
|
70
70
|
const id = setTimeout(() => {
|
|
71
|
-
clearTimeout(id)
|
|
72
|
-
reject(new TimeoutError(`Promise timed out after ${ms} ms`))
|
|
73
|
-
}, ms)
|
|
74
|
-
})
|
|
71
|
+
clearTimeout(id)
|
|
72
|
+
reject(new TimeoutError(`Promise timed out after ${ms} ms`))
|
|
73
|
+
}, ms)
|
|
74
|
+
})
|
|
75
75
|
|
|
76
76
|
// Race the input promise against the timeout promise
|
|
77
|
-
return Promise.race([promise, timeout])
|
|
77
|
+
return Promise.race([promise, timeout])
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
/**
|
|
@@ -82,13 +82,13 @@ export function withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {
|
|
|
82
82
|
* computes `T` based on the current attempt number.
|
|
83
83
|
* @template T The type of the value.
|
|
84
84
|
*/
|
|
85
|
-
type DynamicValue<T> = T | ((attempt: number) => T)
|
|
85
|
+
type DynamicValue<T> = T | ((attempt: number) => T)
|
|
86
86
|
|
|
87
87
|
/**
|
|
88
88
|
* Defines a generic asynchronous function type that returns a Promise.
|
|
89
89
|
* @template T The type of the Promise's resolution value.
|
|
90
90
|
*/
|
|
91
|
-
type AsyncFunction<T> = (...args: any[]) => Promise<T
|
|
91
|
+
type AsyncFunction<T> = (...args: any[]) => Promise<T>
|
|
92
92
|
|
|
93
93
|
/**
|
|
94
94
|
* Defines the options for configuring the retrier behavior.
|
|
@@ -100,45 +100,45 @@ export interface RetrierOptions {
|
|
|
100
100
|
* - If a `function`, it dynamically calculates the maximum retries based on the current attempt number (starting from 1).
|
|
101
101
|
* @defaultValue 2 (meaning 1 initial attempt + 2 retries, total 3 attempts)
|
|
102
102
|
*/
|
|
103
|
-
maxRetries?: DynamicValue<number
|
|
103
|
+
maxRetries?: DynamicValue<number>
|
|
104
104
|
/**
|
|
105
105
|
* The timeout duration for each individual attempt in milliseconds.
|
|
106
106
|
* - If a `number`, it represents a fixed timeout for each attempt.
|
|
107
107
|
* - If a `function`, it dynamically calculates the timeout based on the current attempt number.
|
|
108
108
|
* @defaultValue 5000 (5 seconds)
|
|
109
109
|
*/
|
|
110
|
-
timeoutMs?: DynamicValue<number
|
|
110
|
+
timeoutMs?: DynamicValue<number>
|
|
111
111
|
/**
|
|
112
112
|
* Callback invoked at the beginning of each attempt.
|
|
113
113
|
* @param attempt - The current attempt number (starts from 1).
|
|
114
114
|
* @param error - The error from the previous attempt, if any (undefined for the first attempt).
|
|
115
115
|
*/
|
|
116
|
-
onAttempt?: (attempt: number, error?: Error) => void
|
|
116
|
+
onAttempt?: (attempt: number, error?: Error) => void
|
|
117
117
|
/**
|
|
118
118
|
* Callback invoked upon successful completion of the operation.
|
|
119
119
|
* @template T The type of the successful result.
|
|
120
120
|
* @param result - The successful result of the operation.
|
|
121
121
|
* @param attempt - The attempt number on which the operation succeeded.
|
|
122
122
|
*/
|
|
123
|
-
onSuccess?: <T>(result: T, attempt: number) => void
|
|
123
|
+
onSuccess?: <T>(result: T, attempt: number) => void
|
|
124
124
|
/**
|
|
125
125
|
* Callback invoked when all retries have been exhausted and the operation ultimately fails.
|
|
126
126
|
* @param error - The final error that caused the operation to fail.
|
|
127
127
|
* @param attempt - The total number of attempts made before final failure.
|
|
128
128
|
*/
|
|
129
|
-
onFailure?: (error: Error, attempt: number) => void
|
|
129
|
+
onFailure?: (error: Error, attempt: number) => void
|
|
130
130
|
/**
|
|
131
131
|
* Callback invoked before initiating a retry, indicating that a retry will occur.
|
|
132
132
|
* @param attempt - The attempt number that just failed and will lead to the next retry.
|
|
133
133
|
* @param error - The error that caused the current attempt to fail.
|
|
134
134
|
*/
|
|
135
|
-
onRetry?: (attempt: number, error: Error) => void
|
|
135
|
+
onRetry?: (attempt: number, error: Error) => void
|
|
136
136
|
/**
|
|
137
137
|
* Callback invoked when a single attempt times out. Note that this is a specific type of failure that leads to a retry.
|
|
138
138
|
* @param attempt - The attempt number that timed out.
|
|
139
139
|
* @param ms - The timeout duration (in milliseconds) that was set for this specific attempt.
|
|
140
140
|
*/
|
|
141
|
-
onTimeout?: (attempt: number, ms: number) => void
|
|
141
|
+
onTimeout?: (attempt: number, ms: number) => void
|
|
142
142
|
/**
|
|
143
143
|
* A predicate function that determines whether a given error should trigger a retry.
|
|
144
144
|
* If this function returns `false`, the retrier will immediately stop and throw the error.
|
|
@@ -147,7 +147,7 @@ export interface RetrierOptions {
|
|
|
147
147
|
* @param attempt - The current attempt number.
|
|
148
148
|
* @returns `true` if a retry should occur, `false` otherwise.
|
|
149
149
|
*/
|
|
150
|
-
shouldRetry?: (error: Error, attempt: number) => boolean
|
|
150
|
+
shouldRetry?: (error: Error, attempt: number) => boolean
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
/**
|
|
@@ -218,7 +218,7 @@ export function createRetrier(options: RetrierOptions = {}) {
|
|
|
218
218
|
onRetry,
|
|
219
219
|
onTimeout,
|
|
220
220
|
shouldRetry = () => true, // Default: retry on all errors
|
|
221
|
-
} = options
|
|
221
|
+
} = options
|
|
222
222
|
|
|
223
223
|
/**
|
|
224
224
|
* Resolves a DynamicValue to its concrete value for the given attempt.
|
|
@@ -228,8 +228,8 @@ export function createRetrier(options: RetrierOptions = {}) {
|
|
|
228
228
|
* @returns The concrete value.
|
|
229
229
|
*/
|
|
230
230
|
const resolveDynamicValue = <T_Val>(value: DynamicValue<T_Val>, attempt: number): T_Val => {
|
|
231
|
-
return typeof value === 'function' ? (value as (attempt: number) => T_Val)(attempt) : value
|
|
232
|
-
}
|
|
231
|
+
return typeof value === 'function' ? (value as (attempt: number) => T_Val)(attempt) : value
|
|
232
|
+
}
|
|
233
233
|
|
|
234
234
|
/**
|
|
235
235
|
* A higher-order function that takes an asynchronous function and returns a new function
|
|
@@ -243,53 +243,55 @@ export function createRetrier(options: RetrierOptions = {}) {
|
|
|
243
243
|
*/
|
|
244
244
|
return function <T, Func extends AsyncFunction<T>>(func: Func): ((...args: Parameters<Func>) => Promise<T>) {
|
|
245
245
|
return async function (this: ThisParameterType<Func>, ...args: Parameters<Func>): Promise<T> {
|
|
246
|
-
let currentAttempt = 0
|
|
247
|
-
let lastError: Error | undefined
|
|
246
|
+
let currentAttempt = 0
|
|
247
|
+
let lastError: Error | undefined
|
|
248
248
|
|
|
249
249
|
// Resolve maxRetries once or dynamically per attempt based on DynamicValue type
|
|
250
|
-
const calculatedMaxRetries = resolveDynamicValue(maxRetries, 1)
|
|
250
|
+
const calculatedMaxRetries = resolveDynamicValue(maxRetries, 1) // Calculate for the first attempt as starting point
|
|
251
251
|
|
|
252
252
|
// Loop through attempts up to the maximum allowed retries
|
|
253
253
|
while (currentAttempt <= calculatedMaxRetries) {
|
|
254
|
-
currentAttempt
|
|
255
|
-
onAttempt?.(currentAttempt, lastError)
|
|
254
|
+
currentAttempt++
|
|
255
|
+
onAttempt?.(currentAttempt, lastError) // Notify about current attempt, including previous error if any
|
|
256
256
|
|
|
257
257
|
// Resolve timeoutMs dynamically for the current attempt
|
|
258
|
-
const currentTimeoutMs = resolveDynamicValue(timeoutMs, currentAttempt)
|
|
258
|
+
const currentTimeoutMs = resolveDynamicValue(timeoutMs, currentAttempt)
|
|
259
259
|
|
|
260
260
|
try {
|
|
261
261
|
// Execute the original function with its original `this` context and arguments,
|
|
262
262
|
// wrapped by the `withTimeout` utility.
|
|
263
|
-
const result = await withTimeout(func.apply(this, args), currentTimeoutMs)
|
|
264
|
-
onSuccess?.(result, currentAttempt)
|
|
265
|
-
return result
|
|
266
|
-
}
|
|
267
|
-
|
|
263
|
+
const result = await withTimeout(func.apply(this, args), currentTimeoutMs)
|
|
264
|
+
onSuccess?.(result, currentAttempt) // Notify success
|
|
265
|
+
return result // Return the successful result
|
|
266
|
+
}
|
|
267
|
+
catch (error: any) {
|
|
268
|
+
lastError = error // Store the error for the next attempt's `onAttempt` callback
|
|
268
269
|
|
|
269
270
|
// Notify if the specific error was a timeout
|
|
270
271
|
if (error instanceof TimeoutError) {
|
|
271
|
-
onTimeout?.(currentAttempt, currentTimeoutMs)
|
|
272
|
-
}
|
|
272
|
+
onTimeout?.(currentAttempt, currentTimeoutMs)
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
273
275
|
// console.warn(`Attempt ${currentAttempt} failed with error:`, error.message); // Example internal logging
|
|
274
276
|
}
|
|
275
277
|
|
|
276
278
|
// Determine if a retry should proceed based on the `shouldRetry` predicate and max attempts
|
|
277
|
-
const shouldProceedRetry = shouldRetry(error, currentAttempt)
|
|
279
|
+
const shouldProceedRetry = shouldRetry(error, currentAttempt)
|
|
278
280
|
|
|
279
281
|
if (!shouldProceedRetry || currentAttempt > calculatedMaxRetries) {
|
|
280
|
-
onFailure?.(error, currentAttempt)
|
|
281
|
-
throw error
|
|
282
|
+
onFailure?.(error, currentAttempt) // Notify final failure
|
|
283
|
+
throw error // Throw the error if no more retries or `shouldRetry` returns false
|
|
282
284
|
}
|
|
283
285
|
|
|
284
|
-
onRetry?.(currentAttempt, error)
|
|
286
|
+
onRetry?.(currentAttempt, error) // Notify that a retry will occur
|
|
285
287
|
// Optional: Add a delay here for exponential backoff or other retry strategies.
|
|
286
288
|
// e.g., `await new Promise(resolve => setTimeout(resolve, Math.pow(2, currentAttempt) * 100));`
|
|
287
289
|
}
|
|
288
290
|
}
|
|
289
291
|
// This line should ideally not be reached if the loop's conditions are correct and errors are always thrown.
|
|
290
|
-
throw new Error('Retrier exhausted all attempts without success. This is an unexpected state.')
|
|
291
|
-
}
|
|
292
|
-
}
|
|
292
|
+
throw new Error('Retrier exhausted all attempts without success. This is an unexpected state.')
|
|
293
|
+
}
|
|
294
|
+
}
|
|
293
295
|
}
|
|
294
296
|
|
|
295
297
|
/**
|
|
@@ -359,16 +361,17 @@ export function useRetrier<T, Func extends AsyncFunction<T>>(func: Func): ((...a
|
|
|
359
361
|
timeoutMs: 5000, // Default: 5 seconds timeout
|
|
360
362
|
onAttempt: (attempt, error) => {
|
|
361
363
|
if (attempt > 1) {
|
|
362
|
-
console.log(`[UseRetrier Default] Attempt ${attempt} (after previous error: ${error?.message || 'None'})...`)
|
|
363
|
-
}
|
|
364
|
-
|
|
364
|
+
console.log(`[UseRetrier Default] Attempt ${attempt} (after previous error: ${error?.message || 'None'})...`)
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
console.log(`[UseRetrier Default] Starting initial attempt ${attempt}...`)
|
|
365
368
|
}
|
|
366
369
|
},
|
|
367
370
|
onSuccess: (result, attempt) => console.log(`[UseRetrier Default] ✅ Succeeded on attempt ${attempt}. Result:`, result),
|
|
368
371
|
onFailure: (error, attempt) => console.error(`[UseRetrier Default] ❌ Failed after ${attempt} attempts. Final Error:`, error.message),
|
|
369
372
|
onRetry: (attempt, error) => console.warn(`[UseRetrier Default] 🔄 Will retry. Attempt ${attempt} failed with: ${error.message}`),
|
|
370
373
|
onTimeout: (attempt, ms) => console.warn(`[UseRetrier Default] ⏰ Attempt ${attempt} timed out after ${ms}ms.`),
|
|
371
|
-
})
|
|
374
|
+
})
|
|
372
375
|
// Use the created default retrier to wrap the provided function.
|
|
373
|
-
return defaultRetrier(func)
|
|
376
|
+
return defaultRetrier(func)
|
|
374
377
|
}
|
package/common/utils/timing.ts
CHANGED
|
@@ -24,7 +24,7 @@ const DEFAULT_HISTORY_LIMIT = 50
|
|
|
24
24
|
export const DEFAULT_TIMING_LOG_THRESHOLDS: Readonly<ResolvedTimingLogThresholds> = Object.freeze({
|
|
25
25
|
none: 16.7,
|
|
26
26
|
info: 200,
|
|
27
|
-
warn: 500
|
|
27
|
+
warn: 500,
|
|
28
28
|
})
|
|
29
29
|
|
|
30
30
|
export const DEFAULT_TIMING_OPTIONS: Readonly<Required<Pick<TimingOptions, 'autoLog' | 'storeHistory'>> & {
|
|
@@ -32,7 +32,7 @@ export const DEFAULT_TIMING_OPTIONS: Readonly<Required<Pick<TimingOptions, 'auto
|
|
|
32
32
|
}> = Object.freeze({
|
|
33
33
|
autoLog: DEFAULT_AUTO_LOG,
|
|
34
34
|
storeHistory: DEFAULT_STORE_HISTORY,
|
|
35
|
-
logThresholds: DEFAULT_TIMING_LOG_THRESHOLDS
|
|
35
|
+
logThresholds: DEFAULT_TIMING_LOG_THRESHOLDS,
|
|
36
36
|
})
|
|
37
37
|
|
|
38
38
|
export const DEFAULT_TIMING_MANAGER_CONFIG: Readonly<
|
|
@@ -43,7 +43,7 @@ export const DEFAULT_TIMING_MANAGER_CONFIG: Readonly<
|
|
|
43
43
|
autoLog: DEFAULT_AUTO_LOG,
|
|
44
44
|
storeHistory: DEFAULT_STORE_HISTORY,
|
|
45
45
|
historyLimit: DEFAULT_HISTORY_LIMIT,
|
|
46
|
-
logThresholds: DEFAULT_TIMING_LOG_THRESHOLDS
|
|
46
|
+
logThresholds: DEFAULT_TIMING_LOG_THRESHOLDS,
|
|
47
47
|
})
|
|
48
48
|
|
|
49
49
|
export interface TimingStats {
|
|
@@ -83,7 +83,7 @@ export interface TimingOptions {
|
|
|
83
83
|
logThresholds?: TimingLogThresholdOverrides
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
interface ResolvedTimingOptions {
|
|
87
87
|
autoLog: boolean
|
|
88
88
|
storeHistory: boolean
|
|
89
89
|
historyLimit: number
|
|
@@ -101,13 +101,13 @@ export class TimingManager {
|
|
|
101
101
|
constructor(config: TimingManagerConfig = {}) {
|
|
102
102
|
const mergedThresholds: ResolvedTimingLogThresholds = {
|
|
103
103
|
...DEFAULT_TIMING_LOG_THRESHOLDS,
|
|
104
|
-
...(config.logThresholds ?? {})
|
|
104
|
+
...(config.logThresholds ?? {}),
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
this.config = {
|
|
108
108
|
...DEFAULT_TIMING_MANAGER_CONFIG,
|
|
109
109
|
...config,
|
|
110
|
-
logThresholds: mergedThresholds
|
|
110
|
+
logThresholds: mergedThresholds,
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
|
|
@@ -142,12 +142,13 @@ export class TimingManager {
|
|
|
142
142
|
|
|
143
143
|
getStats(label: string): TimingStats | undefined {
|
|
144
144
|
const stats = this.stats.get(label)
|
|
145
|
-
if (!stats)
|
|
145
|
+
if (!stats)
|
|
146
|
+
return undefined
|
|
146
147
|
return { ...stats }
|
|
147
148
|
}
|
|
148
149
|
|
|
149
150
|
getAllStats(): TimingStats[] {
|
|
150
|
-
return Array.from(this.stats.values()).map(
|
|
151
|
+
return Array.from(this.stats.values()).map(s => ({ ...s }))
|
|
151
152
|
}
|
|
152
153
|
|
|
153
154
|
getHistory(label: string): TimingRecord[] {
|
|
@@ -159,7 +160,7 @@ export class TimingManager {
|
|
|
159
160
|
const stats = this.moduleStats.get(moduleKey)
|
|
160
161
|
return stats ? { ...stats } : undefined
|
|
161
162
|
}
|
|
162
|
-
return Array.from(this.moduleStats.values()).map(
|
|
163
|
+
return Array.from(this.moduleStats.values()).map(s => ({ ...s }))
|
|
163
164
|
}
|
|
164
165
|
|
|
165
166
|
reset(label?: string): void {
|
|
@@ -183,7 +184,7 @@ export class TimingManager {
|
|
|
183
184
|
maxMs: Number.NEGATIVE_INFINITY,
|
|
184
185
|
minMs: Number.POSITIVE_INFINITY,
|
|
185
186
|
lastMs: 0,
|
|
186
|
-
errorCount: 0
|
|
187
|
+
errorCount: 0,
|
|
187
188
|
}
|
|
188
189
|
|
|
189
190
|
next.count += 1
|
|
@@ -214,7 +215,7 @@ export class TimingManager {
|
|
|
214
215
|
const logThresholds: ResolvedTimingLogThresholds = {
|
|
215
216
|
...DEFAULT_TIMING_LOG_THRESHOLDS,
|
|
216
217
|
...(this.config.logThresholds ?? {}),
|
|
217
|
-
...(options.logThresholds ?? {})
|
|
218
|
+
...(options.logThresholds ?? {}),
|
|
218
219
|
}
|
|
219
220
|
|
|
220
221
|
return {
|
|
@@ -223,7 +224,7 @@ export class TimingManager {
|
|
|
223
224
|
historyLimit: options.historyLimit ?? this.config.historyLimit ?? DEFAULT_HISTORY_LIMIT,
|
|
224
225
|
logThresholds,
|
|
225
226
|
formatter: options.formatter ?? this.config.formatter ?? defaultFormatter,
|
|
226
|
-
logger: options.logger ?? this.config.logger ?? defaultLogger
|
|
227
|
+
logger: options.logger ?? this.config.logger ?? defaultLogger,
|
|
227
228
|
}
|
|
228
229
|
}
|
|
229
230
|
}
|
|
@@ -232,7 +233,7 @@ export class TimingScope {
|
|
|
232
233
|
constructor(
|
|
233
234
|
private readonly manager: TimingManager,
|
|
234
235
|
private readonly label: string,
|
|
235
|
-
private readonly options: TimingOptions
|
|
236
|
+
private readonly options: TimingOptions,
|
|
236
237
|
) {}
|
|
237
238
|
|
|
238
239
|
async cost<T>(fn: () => Promise<T> | T, meta: TimingMeta = {}, overrides: TimingOptions = {}): Promise<T> {
|
|
@@ -241,7 +242,8 @@ export class TimingScope {
|
|
|
241
242
|
const result = await fn()
|
|
242
243
|
this.finish(startedAt, meta, undefined, overrides)
|
|
243
244
|
return result
|
|
244
|
-
}
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
245
247
|
this.finish(startedAt, meta, error, overrides)
|
|
246
248
|
throw error
|
|
247
249
|
}
|
|
@@ -256,7 +258,8 @@ export class TimingScope {
|
|
|
256
258
|
const value = await fn(index)
|
|
257
259
|
this.finish(startedAt, { ...iterationMeta, iteration: index }, undefined, overrides)
|
|
258
260
|
results.push(value)
|
|
259
|
-
}
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
260
263
|
this.finish(startedAt, { ...iterationMeta, iteration: index }, error, overrides)
|
|
261
264
|
throw error
|
|
262
265
|
}
|
|
@@ -274,9 +277,9 @@ export class TimingScope {
|
|
|
274
277
|
durationMs,
|
|
275
278
|
startedAt,
|
|
276
279
|
endedAt,
|
|
277
|
-
meta
|
|
280
|
+
meta,
|
|
278
281
|
},
|
|
279
|
-
{ ...this.options, ...overrides }
|
|
282
|
+
{ ...this.options, ...overrides },
|
|
280
283
|
)
|
|
281
284
|
}
|
|
282
285
|
|
|
@@ -296,7 +299,7 @@ export class TimingScope {
|
|
|
296
299
|
startedAt,
|
|
297
300
|
endedAt,
|
|
298
301
|
meta,
|
|
299
|
-
error
|
|
302
|
+
error,
|
|
300
303
|
}
|
|
301
304
|
|
|
302
305
|
this.manager.record(this.label, record, { ...this.options, ...overrides })
|
|
@@ -305,10 +308,10 @@ export class TimingScope {
|
|
|
305
308
|
|
|
306
309
|
function defaultFormatter(record: TimingRecord, stats: TimingStats): string {
|
|
307
310
|
const duration = record.durationMs.toFixed(2)
|
|
308
|
-
const levelTag
|
|
309
|
-
record.logLevel && record.logLevel !== 'info' ? ` [${record.logLevel.toUpperCase()}]` : ''
|
|
311
|
+
const levelTag
|
|
312
|
+
= record.logLevel && record.logLevel !== 'info' ? ` [${record.logLevel.toUpperCase()}]` : ''
|
|
310
313
|
return `⏱ [${record.label}] ${duration} ms${levelTag} (avg: ${stats.avgMs.toFixed(
|
|
311
|
-
2
|
|
314
|
+
2,
|
|
312
315
|
)} ms, max: ${stats.maxMs.toFixed(2)} ms, count: ${stats.count})`
|
|
313
316
|
}
|
|
314
317
|
|
|
@@ -370,7 +373,7 @@ export function completeTiming(
|
|
|
370
373
|
label: string,
|
|
371
374
|
startedAt: number,
|
|
372
375
|
meta: TimingMeta = {},
|
|
373
|
-
options: TimingOptions = {}
|
|
376
|
+
options: TimingOptions = {},
|
|
374
377
|
): number {
|
|
375
378
|
const endedAt = now()
|
|
376
379
|
const durationMs = endedAt - startedAt
|
|
@@ -381,9 +384,9 @@ export function completeTiming(
|
|
|
381
384
|
durationMs,
|
|
382
385
|
startedAt,
|
|
383
386
|
endedAt,
|
|
384
|
-
meta
|
|
387
|
+
meta,
|
|
385
388
|
},
|
|
386
|
-
options
|
|
389
|
+
options,
|
|
387
390
|
)
|
|
388
391
|
return durationMs
|
|
389
392
|
}
|
|
@@ -392,7 +395,7 @@ export function logTiming(
|
|
|
392
395
|
label: string,
|
|
393
396
|
durationMs: number,
|
|
394
397
|
meta: TimingMeta = {},
|
|
395
|
-
options: TimingOptions = {}
|
|
398
|
+
options: TimingOptions = {},
|
|
396
399
|
): void {
|
|
397
400
|
const endedAt = now()
|
|
398
401
|
const startedAt = endedAt - durationMs
|
|
@@ -403,9 +406,9 @@ export function logTiming(
|
|
|
403
406
|
durationMs,
|
|
404
407
|
startedAt,
|
|
405
408
|
endedAt,
|
|
406
|
-
meta
|
|
409
|
+
meta,
|
|
407
410
|
},
|
|
408
|
-
options
|
|
411
|
+
options,
|
|
409
412
|
)
|
|
410
413
|
}
|
|
411
414
|
|
|
@@ -422,14 +425,14 @@ export const timingLogger = {
|
|
|
422
425
|
label,
|
|
423
426
|
startedAt: startTiming(),
|
|
424
427
|
meta,
|
|
425
|
-
options
|
|
428
|
+
options,
|
|
426
429
|
}
|
|
427
430
|
},
|
|
428
431
|
|
|
429
432
|
finish(
|
|
430
433
|
token: TimingLoggerToken,
|
|
431
434
|
meta: TimingMeta = {},
|
|
432
|
-
overrides: TimingOptions = {}
|
|
435
|
+
overrides: TimingOptions = {},
|
|
433
436
|
): number {
|
|
434
437
|
const mergedMeta = { ...token.meta, ...meta }
|
|
435
438
|
const mergedOptions = mergeTimingOptions(token.options, overrides)
|
|
@@ -440,7 +443,7 @@ export const timingLogger = {
|
|
|
440
443
|
label: string,
|
|
441
444
|
durationMs: number,
|
|
442
445
|
meta: TimingMeta = {},
|
|
443
|
-
options: TimingOptions = {}
|
|
446
|
+
options: TimingOptions = {},
|
|
444
447
|
): number {
|
|
445
448
|
logTiming(label, durationMs, meta, options)
|
|
446
449
|
return durationMs
|
|
@@ -450,7 +453,7 @@ export const timingLogger = {
|
|
|
450
453
|
label: string,
|
|
451
454
|
fn: () => Promise<T> | T,
|
|
452
455
|
meta: TimingMeta = {},
|
|
453
|
-
options: TimingOptions = {}
|
|
456
|
+
options: TimingOptions = {},
|
|
454
457
|
): Promise<T> {
|
|
455
458
|
const scope = createTiming(label, options)
|
|
456
459
|
return scope.cost(fn, meta)
|
|
@@ -460,11 +463,11 @@ export const timingLogger = {
|
|
|
460
463
|
label: string,
|
|
461
464
|
durationMs: number,
|
|
462
465
|
meta: TimingMeta = {},
|
|
463
|
-
options: TimingOptions = {}
|
|
466
|
+
options: TimingOptions = {},
|
|
464
467
|
): number {
|
|
465
468
|
logTiming(label, durationMs, meta, options)
|
|
466
469
|
return durationMs
|
|
467
|
-
}
|
|
470
|
+
},
|
|
468
471
|
}
|
|
469
472
|
|
|
470
473
|
export function createTiming(label: string, options: TimingOptions = {}): TimingScope {
|
|
@@ -473,9 +476,10 @@ export function createTiming(label: string, options: TimingOptions = {}): Timing
|
|
|
473
476
|
|
|
474
477
|
function mergeTimingOptions(
|
|
475
478
|
base: TimingOptions = {},
|
|
476
|
-
override: TimingOptions = {}
|
|
479
|
+
override: TimingOptions = {},
|
|
477
480
|
): TimingOptions {
|
|
478
|
-
if (!base && !override)
|
|
481
|
+
if (!base && !override)
|
|
482
|
+
return {}
|
|
479
483
|
if (!override || Object.keys(override).length === 0) {
|
|
480
484
|
return { ...base }
|
|
481
485
|
}
|
|
@@ -488,7 +492,7 @@ function mergeTimingOptions(
|
|
|
488
492
|
...override,
|
|
489
493
|
logThresholds: {
|
|
490
494
|
...(base.logThresholds ?? {}),
|
|
491
|
-
...(override.logThresholds ?? {})
|
|
492
|
-
}
|
|
495
|
+
...(override.logThresholds ?? {}),
|
|
496
|
+
},
|
|
493
497
|
}
|
|
494
498
|
}
|