mirror of
https://github.com/nimbold/Firelink.git
synced 2026-08-22 08:56:44 +00:00
fix(scheduler): harden scheduled actions and speed limits
- Persist scheduler dispatch markers and retry unacknowledged events across renderer and process restarts. - Fence queue admission, Torrent moves, and permit activation during system actions with an explicit force path. - Preserve Aria2 zero-limit overrides and normalize global limits across startup, queued, retry, and live paths. - Guard scheduler lifecycle races, completion post-actions, settings bindings, and regression coverage.
This commit is contained in:
@@ -15,6 +15,10 @@ const download = (id: string, status: DownloadItem['status']): DownloadItem => (
|
||||
});
|
||||
|
||||
describe('schedulerCompletionState', () => {
|
||||
it('does not treat an empty scheduler set as completed', () => {
|
||||
expect(schedulerCompletionState([], [])).toBe('incomplete');
|
||||
});
|
||||
|
||||
it('stays active while any tracked scheduler download can still progress', () => {
|
||||
expect(schedulerCompletionState([
|
||||
download('a', 'completed'),
|
||||
|
||||
@@ -7,6 +7,8 @@ export const schedulerCompletionState = (
|
||||
downloads: DownloadItem[],
|
||||
schedulerActiveDownloadIds: string[],
|
||||
): SchedulerCompletionState => {
|
||||
if (schedulerActiveDownloadIds.length === 0) return 'incomplete';
|
||||
|
||||
const scheduledItems = schedulerActiveDownloadIds.map(id =>
|
||||
downloads.find(download => download.id === id)
|
||||
);
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { beginSchedulerControl, isSchedulerControlCurrent } from './schedulerControl';
|
||||
|
||||
describe('scheduler control generation', () => {
|
||||
it('invalidates an older asynchronous scheduler operation', () => {
|
||||
const first = beginSchedulerControl();
|
||||
expect(isSchedulerControlCurrent(first)).toBe(true);
|
||||
|
||||
const second = beginSchedulerControl();
|
||||
expect(isSchedulerControlCurrent(first)).toBe(false);
|
||||
expect(isSchedulerControlCurrent(second)).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
let schedulerControlGeneration = 0;
|
||||
|
||||
/**
|
||||
* Start a new scheduler control lifecycle. A later manual pause or scheduler
|
||||
* event invalidates earlier asynchronous queue operations before they can
|
||||
* publish stale running state.
|
||||
*/
|
||||
export const beginSchedulerControl = (): number => {
|
||||
schedulerControlGeneration += 1;
|
||||
return schedulerControlGeneration;
|
||||
};
|
||||
|
||||
export const isSchedulerControlCurrent = (generation: number): boolean =>
|
||||
schedulerControlGeneration === generation;
|
||||
Reference in New Issue
Block a user