linux scheduler tested
This commit is contained in:
parent
3584245979
commit
f99c3a3f1a
6 changed files with 109 additions and 73 deletions
11
.vscode/launch.json
vendored
11
.vscode/launch.json
vendored
|
|
@ -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"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()}');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -546,7 +546,7 @@ class DataJiraUser extends DataParam {
|
|||
|
||||
//Zip
|
||||
@JsonSerializable()
|
||||
class DataZip extends DataParam {
|
||||
class DataZip extends DataFile {
|
||||
DataZip();
|
||||
|
||||
late String zipFile;
|
||||
|
|
|
|||
Loading…
Reference in a new issue