feat: implement telemetry system for application usage tracking

- Added telemetry utility to capture application events and metrics.
- Integrated PostHog for event tracking with distinct user identification.
- Implemented telemetry initialization, event capturing, and shutdown procedures.

feat: add UV environment setup for Python management

- Created utilities to manage Python installation and configuration.
- Implemented network optimization checks for Python installation mirrors.
- Added functions to set up managed Python environments with error handling.

feat: enhance host API communication with token management

- Introduced host API token retrieval and management for secure requests.
- Updated host API fetch functions to include token in headers.
- Added support for creating event sources with authentication.

test: add comprehensive tests for gateway protocol and startup helpers

- Implemented unit tests for gateway protocol helpers, event dispatching, and state management.
- Added tests for startup recovery strategies and process policies.
- Ensured coverage for connection monitoring and restart governance logic.
This commit is contained in:
DEV_DSW
2026-04-23 17:21:57 +08:00
parent 655e7c51d2
commit 71bcc3b3c5
39 changed files with 5504 additions and 313 deletions

View File

@@ -0,0 +1,111 @@
import logManager from '@electron/service/logger';
import {
getDeferredRestartAction,
shouldDeferRestart,
type GatewayLifecycleState,
} from './process-policy';
type RestartDeferralState = {
state: GatewayLifecycleState;
startLock: boolean;
};
type DeferredRestartContext = RestartDeferralState & {
shouldReconnect: boolean;
};
export class GatewayRestartController {
private deferredRestartPending = false;
private deferredRestartRequestedAt = 0;
private lastRestartCompletedAt = 0;
private restartDebounceTimer: NodeJS.Timeout | null = null;
isRestartDeferred(context: RestartDeferralState): boolean {
return shouldDeferRestart(context);
}
markDeferredRestart(reason: string, context: RestartDeferralState): void {
if (!this.deferredRestartPending) {
logManager.info(
`Deferring Gateway restart (${reason}) until startup/reconnect settles (state=${context.state}, startLock=${context.startLock})`,
);
} else {
logManager.debug(
`Gateway restart already deferred; keeping pending request (${reason}, state=${context.state}, startLock=${context.startLock})`,
);
}
this.deferredRestartPending = true;
if (this.deferredRestartRequestedAt === 0) {
this.deferredRestartRequestedAt = Date.now();
}
}
recordRestartCompleted(): void {
this.lastRestartCompletedAt = Date.now();
}
flushDeferredRestart(
trigger: string,
context: DeferredRestartContext,
executeRestart: () => void,
): void {
const action = getDeferredRestartAction({
hasPendingRestart: this.deferredRestartPending,
state: context.state,
startLock: context.startLock,
shouldReconnect: context.shouldReconnect,
});
if (action === 'none') return;
if (action === 'wait') {
logManager.debug(
`Deferred Gateway restart still waiting (${trigger}, state=${context.state}, startLock=${context.startLock})`,
);
return;
}
const requestedAt = this.deferredRestartRequestedAt;
this.deferredRestartPending = false;
this.deferredRestartRequestedAt = 0;
if (action === 'drop') {
logManager.info(
`Dropping deferred Gateway restart (${trigger}) because lifecycle already recovered (state=${context.state}, shouldReconnect=${context.shouldReconnect})`,
);
return;
}
if (requestedAt > 0 && this.lastRestartCompletedAt >= requestedAt) {
logManager.info(
`Dropping deferred Gateway restart (${trigger}): a restart already completed after the request (requested=${requestedAt}, completed=${this.lastRestartCompletedAt})`,
);
return;
}
logManager.info(`Executing deferred Gateway restart now (${trigger})`);
executeRestart();
}
debouncedRestart(delayMs: number, executeRestart: () => void): void {
if (this.restartDebounceTimer) {
clearTimeout(this.restartDebounceTimer);
}
logManager.debug(`Gateway restart debounced (will fire in ${delayMs}ms)`);
this.restartDebounceTimer = setTimeout(() => {
this.restartDebounceTimer = null;
executeRestart();
}, delayMs);
}
clearDebounceTimer(): void {
if (this.restartDebounceTimer) {
clearTimeout(this.restartDebounceTimer);
this.restartDebounceTimer = null;
}
}
resetDeferredRestart(): void {
this.deferredRestartPending = false;
this.deferredRestartRequestedAt = 0;
}
}