add kernel scheduler service on background isolate
Tiered Timer.periodic instances (1min, 10min, 15min, 1hr, midnight) running on a dedicated Dart isolate. Tick messages sent back to the main isolate via SendPort and emitted as SchedulerTick events on the DaemonBus. Extensions subscribe with events.on<SchedulerTick>() and filter by tier. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -34,6 +34,7 @@ export 'src/notify.dart';
|
||||
export 'src/os.dart';
|
||||
export 'src/panels/arrangement.dart';
|
||||
export 'src/project.dart';
|
||||
export 'src/scheduler.dart';
|
||||
export 'src/secrets.dart';
|
||||
export 'src/tray.dart';
|
||||
export 'src/panels/drag_resize.dart';
|
||||
|
||||
@@ -22,6 +22,7 @@ import 'package:clide/kernel/src/os.dart';
|
||||
import 'package:clide/kernel/src/panels/arrangement.dart';
|
||||
import 'package:clide/kernel/src/panels/registry.dart';
|
||||
import 'package:clide/kernel/src/project.dart';
|
||||
import 'package:clide/kernel/src/scheduler.dart';
|
||||
import 'package:clide/kernel/src/secrets.dart';
|
||||
import 'package:clide/kernel/src/settings.dart';
|
||||
import 'package:clide/kernel/src/theme/controller.dart';
|
||||
@@ -61,6 +62,7 @@ class KernelServices {
|
||||
required this.extensions,
|
||||
required this.window,
|
||||
required this.toolCheck,
|
||||
required this.scheduler,
|
||||
});
|
||||
|
||||
final Logger log;
|
||||
@@ -88,6 +90,7 @@ class KernelServices {
|
||||
final ExtensionManager extensions;
|
||||
final WindowControls window;
|
||||
final ToolCheck toolCheck;
|
||||
final SchedulerService scheduler;
|
||||
|
||||
static Future<KernelServices> boot({
|
||||
required Directory appDir,
|
||||
@@ -136,6 +139,8 @@ class KernelServices {
|
||||
final focus = FocusTracker();
|
||||
final window = WindowControls();
|
||||
final toolCheck = ToolCheck();
|
||||
final scheduler = SchedulerService(events);
|
||||
scheduler.start();
|
||||
final project = ProjectManager(
|
||||
log: log,
|
||||
events: events,
|
||||
@@ -203,6 +208,7 @@ class KernelServices {
|
||||
extensions: extensions,
|
||||
window: window,
|
||||
toolCheck: toolCheck,
|
||||
scheduler: scheduler,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -223,6 +229,7 @@ class KernelServices {
|
||||
focus.dispose();
|
||||
project.dispose();
|
||||
extensions.dispose();
|
||||
scheduler.dispose();
|
||||
await log.dispose();
|
||||
messages.dispose();
|
||||
await events.dispose();
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
import 'dart:async';
|
||||
import 'dart:isolate';
|
||||
|
||||
import 'package:clide/kernel/src/events/bus.dart';
|
||||
import 'package:clide/kernel/src/events/types.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
enum SchedulerTier {
|
||||
oneMinute(Duration(minutes: 1)),
|
||||
tenMinutes(Duration(minutes: 10)),
|
||||
fifteenMinutes(Duration(minutes: 15)),
|
||||
oneHour(Duration(hours: 1)),
|
||||
midnight(Duration(minutes: 1));
|
||||
|
||||
const SchedulerTier(this.interval);
|
||||
final Duration interval;
|
||||
}
|
||||
|
||||
@immutable
|
||||
class SchedulerTick extends ClideEvent {
|
||||
const SchedulerTick({required this.tier});
|
||||
final SchedulerTier tier;
|
||||
|
||||
@override
|
||||
String get subsystem => 'scheduler';
|
||||
@override
|
||||
String get kind => 'tick';
|
||||
@override
|
||||
Map<String, Object?> payload() => {'tier': tier.name};
|
||||
}
|
||||
|
||||
class SchedulerService {
|
||||
SchedulerService(this._events);
|
||||
final DaemonBus _events;
|
||||
|
||||
Isolate? _isolate;
|
||||
ReceivePort? _port;
|
||||
StreamSubscription<dynamic>? _sub;
|
||||
|
||||
void start() {
|
||||
if (_isolate != null) return;
|
||||
_port = ReceivePort();
|
||||
_sub = _port!.listen((msg) {
|
||||
if (msg is String) {
|
||||
final tier = SchedulerTier.values.firstWhere((t) => t.name == msg);
|
||||
_events.emit(SchedulerTick(tier: tier));
|
||||
}
|
||||
});
|
||||
Isolate.spawn(_isolateEntry, _port!.sendPort).then((iso) => _isolate = iso);
|
||||
}
|
||||
|
||||
static void _isolateEntry(SendPort send) {
|
||||
int lastDay = DateTime.now().day;
|
||||
for (final tier in SchedulerTier.values) {
|
||||
if (tier == SchedulerTier.midnight) {
|
||||
Timer.periodic(const Duration(minutes: 1), (_) {
|
||||
final day = DateTime.now().day;
|
||||
if (day != lastDay) {
|
||||
lastDay = day;
|
||||
send.send(tier.name);
|
||||
}
|
||||
});
|
||||
continue;
|
||||
}
|
||||
Timer.periodic(tier.interval, (_) => send.send(tier.name));
|
||||
}
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
_sub?.cancel();
|
||||
_port?.close();
|
||||
_isolate?.kill(priority: Isolate.immediate);
|
||||
_isolate = null;
|
||||
_port = null;
|
||||
_sub = null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user