linux scheduler tested

This commit is contained in:
Toki 2025-01-01 09:52:37 +09:00
parent 3584245979
commit f99c3a3f1a
6 changed files with 109 additions and 73 deletions

11
.vscode/launch.json vendored
View file

@ -100,14 +100,14 @@
"request": "launch",
"type": "dart",
"program": "./bin/main.dart",
"args": ["scheduler", "-r", "./assets/scheduler.yaml"]
"args": ["scheduler", "-r", "./assets/scheduler2.yaml"]
},
{
"name": "scheduler unregist",
"request": "launch",
"type": "dart",
"program": "./bin/main.dart",
"args": ["scheduler", "-u", "test"]
"args": ["scheduler", "-u", "test2"]
},
{
"name": "scheduler background",
@ -115,6 +115,13 @@
"type": "dart",
"program": "./bin/main.dart",
"args": ["scheduler", "-s"]
},
{
"name": "scheduler enable",
"request": "launch",
"type": "dart",
"program": "./bin/main.dart",
"args": ["scheduler", "-e", "test2", "true"]
}
]
}

View file

@ -7,7 +7,7 @@ scheduler:
property:
workspace: /Users/toki/works/oto_cli
workspace: /home/deck/work/oto_cli
pipeline:
@ -25,10 +25,10 @@ commands:
id: diff
param:
paths:
- /Users/toki/works/oto_cli/lib/oto/data/command_data.dart
- /Users/toki/works/oto_cli/lib/oto/data/jenkins_data.dart
- /Users/toki/works/oto_cli/lib/oto/data/jira_data.dart
- /Users/toki/works/oto_cli/lib/oto/data/pipeline_data.dart
- <!property.workspace>/lib/oto/data/command_data.dart
- <!property.workspace>/lib/oto/data/jenkins_data.dart
- <!property.workspace>/lib/oto/data/jira_data.dart
- <!property.workspace>/lib/oto/data/pipeline_data.dart
setDiff: <@property.isDiff>
- command: Shell

View file

@ -1,5 +1,10 @@
import 'dart:io';
import 'package:oto_cli/cli/commands/scheduler/scheduler_manager.dart';
class SchedulerLinux extends SchedulerManager {
}
@override
String get exePath {
return Platform.resolvedExecutable;
}
}

View file

@ -1,4 +1,3 @@
import 'dart:collection';
import 'dart:convert';
import 'dart:io';
@ -18,7 +17,6 @@ import 'package:oto_cli/oto/data/command_data.dart';
import 'package:path/path.dart' as path;
class SchedulerManager {
static String get _schedulerPath {
var debugPath = isDebug ? '.debug' : '';
return '$dataPath$debugPath/scheduler';
@ -30,7 +28,12 @@ class SchedulerManager {
ProcessInfo? _currentScheduler;
final Map<String, IsolateHandler> _map = {};
final logFile = File('$_logsPath/scheduler_${getDate()}_${getTime().replaceAll(':', '')}_[$pid].txt');
final logFile = File(
'$_logsPath/scheduler_${getDate()}_${getTime().replaceAll(':', '')}_[$pid].txt');
String get exePath {
return throw UnimplementedError('Unimplemented exePath');
}
String get _settingsPath {
return '$_schedulerPath/settings.json';
@ -38,7 +41,7 @@ class SchedulerManager {
SchedulerListData get _localData {
var file = File(_settingsPath);
if(!file.existsSync()) {
if (!file.existsSync()) {
_localData = SchedulerListData();
}
return SchedulerListData.fromJson(jsonDecode(file.readAsStringSync()));
@ -46,7 +49,8 @@ class SchedulerManager {
set _localData(SchedulerListData data) {
var file = File(_settingsPath);
file.writeAsStringSync(JsonEncoder.withIndent(' ').convert(data.toJson()), mode: FileMode.write, flush: true);
file.writeAsStringSync(JsonEncoder.withIndent(' ').convert(data.toJson()),
mode: FileMode.write, flush: true);
}
String get _startupID {
@ -56,11 +60,11 @@ class SchedulerManager {
HashSet<String> get _schedulers {
HashSet<String> hash = HashSet();
var dir = Directory(_schedulerPath);
if(dir.existsSync()) {
if (dir.existsSync()) {
var fileList = dir.listSync();
for(var item in fileList) {
if(item is File) {
if(path.extension(item.path).toLowerCase().contains('.yaml')) {
for (var item in fileList) {
if (item is File) {
if (path.extension(item.path).toLowerCase().contains('.yaml')) {
hash.add(path.basenameWithoutExtension(item.path));
}
}
@ -70,13 +74,13 @@ class SchedulerManager {
}
SchedulerManager();
factory SchedulerManager.create() {
if(Platform.isMacOS) {
if (Platform.isMacOS) {
return SchedulerOsx();
} else if(Platform.isWindows) {
} else if (Platform.isWindows) {
return SchedulerWindows();
} else if(Platform.isLinux) {
} else if (Platform.isLinux) {
return SchedulerLinux();
} else {
throw UnsupportedError('This platform not supported.');
@ -85,7 +89,7 @@ class SchedulerManager {
Future regist(String filePath) async {
var file = File(filePath);
if(!file.existsSync()) {
if (!file.existsSync()) {
return throw Exception("The file '$filePath' does not exist.");
}
Map<String, dynamic>? map;
@ -93,26 +97,28 @@ class SchedulerManager {
try {
map = Application.getMapFromYamlA(await file.readAsString());
build = DataBuild.fromJson(map!);
} on Exception catch(e, stacktace) {
} on Exception catch (e, stacktace) {
print(stacktace);
return throw Exception("The file '$filePath' is not in yaml format or is an unsupported build format.");
return throw Exception(
"The file '$filePath' is not in yaml format or is an unsupported build format.");
}
if(build.scheduler == null) {
if (build.scheduler == null) {
return throw Exception('Scheduler entry does not exist within yaml.');
}
var dirLogs = Directory(_logsPath);
var alias = build.scheduler!.alias;
var hash = _schedulers;
if(hash.contains(alias)) {
return throw Exception('A scheduler with the same alias is registered. Please do it with a different alias.');
if (hash.contains(alias)) {
return throw Exception(
'A scheduler with the same alias is registered. Please do it with a different alias.');
}
await _checkStartup();
await _checkProcess();
await _startProcess();
if(!dirLogs.existsSync()) {
if (!dirLogs.existsSync()) {
dirLogs.createSync(recursive: true);
}
var newPath = '$_schedulerPath/$alias.yaml';
@ -135,7 +141,7 @@ class SchedulerManager {
}
Future unregist(String alias) async {
if(_schedulers.contains(alias)) {
if (_schedulers.contains(alias)) {
var file = File('$_schedulerPath/$alias.yaml');
file.deleteSync();
} else {
@ -143,7 +149,7 @@ class SchedulerManager {
}
var local = _localData;
if(local.map.containsKey(alias)) {
if (local.map.containsKey(alias)) {
local.map.remove(alias);
_localData = local;
}
@ -156,7 +162,7 @@ class SchedulerManager {
Future showList() async {
print('');
var scheduleList = _schedulers;
if(scheduleList.isEmpty) {
if (scheduleList.isEmpty) {
print(':::: There are no registered schedulers.');
print('');
} else {
@ -164,12 +170,13 @@ class SchedulerManager {
print('');
print('${' [Enable]'.padRight(20)}${'[Alias]'.padRight(20)}[Path]');
var local = _localData;
for(var item in _schedulers) {
for (var item in _schedulers) {
var enable = true;
if(local.map.containsKey(item)) {
if (local.map.containsKey(item)) {
enable = local.map[item]!.enable;
}
print('${' - $enable'.padRight(20)}${item.padRight(20)}$_schedulerPath/$item.yaml');
print(
'${' - $enable'.padRight(20)}${item.padRight(20)}$_schedulerPath/$item.yaml');
}
print('');
}
@ -179,7 +186,7 @@ class SchedulerManager {
Future enableScheduler(String alias, bool enable) async {
var local = _localData;
if(_schedulers.contains(alias)) {
if (_schedulers.contains(alias)) {
var data = SchedulerData();
data.alias = alias;
data.enable = enable;
@ -189,11 +196,11 @@ class SchedulerManager {
print('');
print("Scheduler '$alias' has been $activate.");
print('');
await _checkStartup();
await _checkProcess();
await _startProcess();
exit(0);
} else {
return throw Exception("There is no scheduler called '$alias'.");
@ -202,7 +209,7 @@ class SchedulerManager {
Future terminate() async {
await _checkProcess();
if(_currentScheduler != null) {
if (_currentScheduler != null) {
Process.killPid(_currentScheduler!.pid);
print('Scheduler operation stopped.');
}
@ -210,7 +217,7 @@ class SchedulerManager {
}
Future _checkTerminate() async {
if(_schedulers.isEmpty) {
if (_schedulers.isEmpty) {
await _unregistStartup();
await terminate();
}
@ -219,12 +226,16 @@ class SchedulerManager {
Future _startProcess() async {
//Launchd로
if(_currentScheduler == null) {
if (_currentScheduler == null) {
var script = isDebug ? ' $scriptPath' : '';
var shell = StringBuffer();
shell.writeln('nohup $executablePath$script scheduler -s &');
shell.writeln('disown');
ProcessExecutor.run(shell, workspace: Directory.systemTemp.path, printStdout: false);
// shell.writeln('disown');
print(shell.toString());
ProcessExecutor.run(shell,
workspace: Directory.systemTemp.path,
printStdout: false,
logHandler: (p0, p1) => print(p0));
await _checkProcess();
}
return simpleFuture;
@ -233,9 +244,10 @@ class SchedulerManager {
Future _checkProcess() async {
//process check
var processes = await findProcess('scheduler -s');
for(var process in processes) {
for (var process in processes) {
var processName = process.name;
if(processName.contains('main.dart scheduler -s') || processName.contains('$appName scheduler -s')) {
if (processName.contains('main.dart scheduler -s') ||
processName.contains('$appName scheduler -s')) {
_currentScheduler = process;
print('Scheduler is running on pid [${_currentScheduler!.pid}].');
break;
@ -245,30 +257,24 @@ class SchedulerManager {
}
Future _checkStartup() async {
if(!await OSStartup.isRegistedStartup(_startupID)) {
if (!await OSStartup.isRegistedStartup(_startupID)) {
List<String> param = [];
var exe = Platform.resolvedExecutable;
if(isDebug) {
if (isDebug) {
param.add(scriptPath);
} else {
//homebrew로
if(exe.startsWith('/usr/local')) {
//intel mac
exe = '/usr/local/bin/${path.basenameWithoutExtension(exe)}';
} else if(exe.startsWith('/opt/homebrew')) {
//sillicon mac
exe = '/opt/homebrew/bin/${path.basenameWithoutExtension(exe)}';
}
exe = exePath;
}
param.add('scheduler');
param.add('-s');
await OSStartup.registStartup(exe, _startupID, arguments: param, logErrorFilePath: '$_schedulerPath/launch_err.log');
await OSStartup.registStartup(exe, _startupID,
arguments: param, logErrorFilePath: '$_schedulerPath/launch_err.log');
}
return simpleFuture;
}
Future _unregistStartup() async {
if(await OSStartup.isRegistedStartup(_startupID)) {
if (await OSStartup.isRegistedStartup(_startupID)) {
await OSStartup.unregistStartup(_startupID);
}
return simpleFuture;
@ -277,20 +283,22 @@ class SchedulerManager {
//======================== other process ========================//
Future start() async {
_log('Scheduler is running on pid [$pid].');
while(true) {
while (true) {
//
await Future.delayed(Duration(seconds: 1));
var settings = _localData.map;
for(var alias in _schedulers) {
var enable = settings.containsKey(alias) ? settings[alias]!.enable : true;
if(!_map.containsKey(alias) && enable) {
for (var alias in _schedulers) {
var enable =
settings.containsKey(alias) ? settings[alias]!.enable : true;
if (!_map.containsKey(alias) && enable) {
_log('Schduler found: $alias');
var handler = IsolateManager.create(IsolateScheduler({'alias': alias, 'root': _schedulerPath, 'logs': _logsPath}));
handler.addListener('terminated', _onTerminated );
var handler = IsolateManager.create(IsolateScheduler(
{'alias': alias, 'root': _schedulerPath, 'logs': _logsPath}));
handler.addListener('terminated', _onTerminated);
handler.addListener('log', _onLog);
_map[alias] = handler;
}
if(_map.containsKey(alias) && !enable) {
if (_map.containsKey(alias) && !enable) {
_removeHandler(alias);
}
}
@ -308,7 +316,7 @@ class SchedulerManager {
var type = map['type'] as String;
var message = map['message'] as String;
_removeHandler(alias);
switch(type) {
switch (type) {
case 'error':
_log('[Error] $message');
break;
@ -316,15 +324,15 @@ class SchedulerManager {
var local = _localData;
var list = _schedulers;
if(list.isEmpty) {
if (list.isEmpty) {
_log('Scheduler operation stopped.');
if(local.map.containsKey(alias)) {
if (local.map.containsKey(alias)) {
local.map.remove(alias);
}
} else {
list.contains(alias);
SchedulerData data = SchedulerData();
if(local.map.containsKey(alias)) {
if (local.map.containsKey(alias)) {
data = local.map[alias]!;
}
data.alias = alias;
@ -340,10 +348,11 @@ class SchedulerManager {
}
void _log(String message) {
logFile.writeAsStringSync('[${getDates()}] $message\n', mode: FileMode.append, flush: true);
logFile.writeAsStringSync('[${getDates()}] $message\n',
mode: FileMode.append, flush: true);
}
void _logError(Exception e, StackTrace stacktace) {
_log('[${e.toString()}]\n${stacktace.toString()}');
}
}
}

View file

@ -1,5 +1,20 @@
import 'dart:io';
import 'package:oto_cli/cli/commands/scheduler/scheduler_manager.dart';
import 'package:path/path.dart' as path;
class SchedulerOsx extends SchedulerManager {
}
@override
String get exePath {
var exe = Platform.resolvedExecutable;
//homebrew로
if (exe.startsWith('/usr/local')) {
//intel mac
exe = '/usr/local/bin/${path.basenameWithoutExtension(exe)}';
} else if (exe.startsWith('/opt/homebrew')) {
//sillicon mac
exe = '/opt/homebrew/bin/${path.basenameWithoutExtension(exe)}';
}
return exe;
}
}

View file

@ -546,7 +546,7 @@ class DataJiraUser extends DataParam {
//Zip
@JsonSerializable()
class DataZip extends DataParam {
class DataZip extends DataFile {
DataZip();
late String zipFile;