diff --git a/README.md b/README.md index 94a4338..e40b4b8 100644 --- a/README.md +++ b/README.md @@ -65,12 +65,15 @@ Using a POST HTTP request to start up a new process. `name` is the task name. One task is a group of same processes. In this example, we will start up two process to run `sleep 5`. -`once` means that the processes in this task will only be executed once. And there are three values of `type` field: +`once` means that the processes in this task will only be executed once. And there are four values of `type` field: - `once` means this task will only be executed once even if it exits unexpectedly. - `daemon` means this task is a daemon, so if this process exits in any reason, it will be restarted. - `cron` means this task is a cron job, it will contain a field named `cron` in task JSON. -- `user` indicates the user of the new process. Please make sure that Meproc has the permission to do this. `user` and `group` are NOT working on Windows. +- `coroutine` means that this task is a melang coroutine task. It will start a melang coroutine based on the provided script file path. + + +`user` indicates the user of the new process. Please make sure that Meproc has the permission to do this. `user` and `group` are NOT working on Windows. diff --git a/controllers/proc.m b/controllers/proc.m index af9743c..e337748 100644 --- a/controllers/proc.m +++ b/controllers/proc.m @@ -16,7 +16,7 @@ 'body': [ ['field': 'name', 'type': 'string', 'required': true], ['field': 'cmd', 'type': 'string', 'required': true], - ['field': 'type', 'type': 'string', 'required': true, 'in': ['once', 'daemon', 'cron']], + ['field': 'type', 'type': 'string', 'required': true, 'in': ['once', 'daemon', 'cron', 'coroutine']], ['field': 'cron', 'type': 'string', 'required': false, 'default': '* * * * *'], ['field': 'user', 'type': 'string', 'required': false,], ['field': 'group', 'type': 'string', 'required': false,], @@ -112,8 +112,18 @@ fi data[keys[i]] = Tasks[keys[i]]; } + co = Eval(); + run = S.exec(); + n = S.size(co); + for (i = 0; i < n; ++i) { + run[] = [ + 'command': '', + 'pid': '', + 'alias': co[i], + ]; + } return J.encode(['code': 200, 'msg': 'OK', 'data': [ - 'running': S.exec(), + 'running': run, 'tasks': data, ]]); } @@ -134,6 +144,10 @@ R['code'] = 400; return J.encode(['code': 400, 'msg': 'Invalid JSON field']); } fi + if (body['name'] == '__coroutine__') { + R['code'] = 400; + return J.encode(['code': 400, 'msg': "name '" + body['name'] + "' is reserved"]); + } fi if (S.int(body['interval']) <= 0) { R['code'] = 400; return J.encode(['code': 400, 'msg': "Interval must be a positive integer'"]); @@ -256,6 +270,9 @@ Log('info', 'Task ' + prog['name'] + ' stopped'); for (i = 0; i < n; ++i) { Kill(name + ':' + i); + if (prog['type'] == 'coroutine') { + Kill('__' + prog['type'] + '__:' + name + ':' + i); + } fi } } diff --git a/coroutines/task.m b/coroutines/task.m index da68e70..52fcff3 100644 --- a/coroutines/task.m +++ b/coroutines/task.m @@ -17,7 +17,20 @@ process_start_event = data; -s.exec(cmd, -1, data['pid'], conf['user'], conf['group'], alias); +if (type != 'coroutine') { + s.exec(cmd, -1, data['pid'], conf['user'], conf['group'], alias); +} else { + name = '__' + type + '__:' + alias; + Eval(cmd, EVAL_DATA, false, name); + + while (true) { + list = Eval(); + if (!s.has(list, name)) + break; + fi + s.msleep(1000); + } +} process_stop_event = data; diff --git a/web/index.html b/web/index.html index afc3d04..38d8802 100644 --- a/web/index.html +++ b/web/index.html @@ -37,6 +37,7 @@