mirror of
https://github.com/nimbold/Firelink.git
synced 2026-08-07 01:44:01 +00:00
fix(tools): harden scheduler limits and logs
Guard scheduler system actions against pending work, serialize diagnostic log transitions, and keep speed-limit saves truthful after backend failures.\n\nNo linked issue was found for this audit.
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
const { invoke } = vi.hoisted(() => ({ invoke: vi.fn() }));
|
||||
|
||||
vi.mock('@tauri-apps/api/core', () => ({ invoke }));
|
||||
vi.mock('@tauri-apps/plugin-log', () => ({
|
||||
attachLogger: vi.fn(),
|
||||
debug: vi.fn(),
|
||||
error: vi.fn(),
|
||||
info: vi.fn(),
|
||||
trace: vi.fn(),
|
||||
warn: vi.fn()
|
||||
}));
|
||||
|
||||
import { setLogPaused, setLogStreamActive } from './logger';
|
||||
|
||||
describe('logger stream transitions', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('serializes enable and disable transitions', async () => {
|
||||
let releaseFirst!: () => void;
|
||||
invoke
|
||||
.mockImplementationOnce(() => new Promise<void>(resolve => { releaseFirst = resolve; }))
|
||||
.mockResolvedValueOnce(undefined);
|
||||
|
||||
const enabling = setLogStreamActive(true);
|
||||
const disabling = setLogStreamActive(false);
|
||||
await Promise.resolve();
|
||||
|
||||
expect(invoke).toHaveBeenCalledTimes(1);
|
||||
releaseFirst();
|
||||
await Promise.all([enabling, disabling]);
|
||||
|
||||
expect(invoke.mock.calls).toEqual([
|
||||
['set_log_stream_active', { active: true }],
|
||||
['set_log_stream_active', { active: false }]
|
||||
]);
|
||||
});
|
||||
|
||||
it('serializes pause transitions so the backend cannot finish out of order', async () => {
|
||||
let releaseFirst!: () => void;
|
||||
invoke
|
||||
.mockImplementationOnce(() => new Promise<void>(resolve => { releaseFirst = resolve; }))
|
||||
.mockResolvedValueOnce(undefined);
|
||||
|
||||
const pausing = setLogPaused(true);
|
||||
const resuming = setLogPaused(false);
|
||||
await Promise.resolve();
|
||||
|
||||
expect(invoke).toHaveBeenCalledTimes(1);
|
||||
releaseFirst();
|
||||
await Promise.all([pausing, resuming]);
|
||||
|
||||
expect(invoke.mock.calls).toEqual([
|
||||
['toggle_log_pause', { pause: true }],
|
||||
['toggle_log_pause', { pause: false }]
|
||||
]);
|
||||
});
|
||||
});
|
||||
+17
-3
@@ -5,6 +5,8 @@ import { invoke } from '@tauri-apps/api/core';
|
||||
let isPaused = true;
|
||||
|
||||
let initPromise: Promise<void> | null = null;
|
||||
let logPauseTransition = Promise.resolve();
|
||||
let logStreamTransition = Promise.resolve();
|
||||
|
||||
export const initLogger = () => {
|
||||
if (!initPromise) {
|
||||
@@ -15,9 +17,21 @@ export const initLogger = () => {
|
||||
return initPromise;
|
||||
};
|
||||
|
||||
export const setLogPaused = async (pause: boolean) => {
|
||||
isPaused = pause;
|
||||
await invoke('toggle_log_pause', { pause }).catch(console.error);
|
||||
export const setLogPaused = (pause: boolean): Promise<void> => {
|
||||
const transition = logPauseTransition.then(async () => {
|
||||
await invoke('toggle_log_pause', { pause });
|
||||
isPaused = pause;
|
||||
});
|
||||
logPauseTransition = transition.catch(() => undefined);
|
||||
return transition;
|
||||
};
|
||||
|
||||
export const setLogStreamActive = (active: boolean): Promise<void> => {
|
||||
const transition = logStreamTransition.then(async () => {
|
||||
await invoke('set_log_stream_active', { active });
|
||||
});
|
||||
logStreamTransition = transition.catch(() => undefined);
|
||||
return transition;
|
||||
};
|
||||
|
||||
export const getLogPaused = () => isPaused;
|
||||
|
||||
Reference in New Issue
Block a user