Skip to content

Commit dffb9f1

Browse files
committed
add schedule task :)
1 parent b1349c2 commit dffb9f1

File tree

2 files changed

+98
-8
lines changed

2 files changed

+98
-8
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
.idea/
22
debug.sh
33

4-
test/.pytest_cache/
4+
test/.pytest_cache/
5+
test/__pycache__/

hooks/__init__.py

Lines changed: 96 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import json
22
import os
3+
import threading
34
import time
45
from enum import Enum
56
from io import StringIO
7+
from time import sleep
68
from typing import List, Union
79

810
from mcdreforged.api.all import *
@@ -44,7 +46,13 @@ class TaskType(Enum):
4446
python_code = 'python_code'
4547

4648

47-
class Task(Serializable):
49+
class Task:
50+
def __init__(self, name, task_type, created_by, command):
51+
self.name = name
52+
self.task_type = task_type
53+
self.created_by = created_by
54+
self.command = command
55+
4856
name: str = 'undefined'
4957

5058
task_type: TaskType = TaskType.undefined
@@ -113,12 +121,55 @@ def execute_task(self, server: PluginServerInterface, hook: str, var_dict: dict
113121
if obj_dict is not None:
114122
exec(self.command, obj_dict, {})
115123
else:
116-
exec(self.command, var_dict, locals())
117-
124+
if var_dict is not None:
125+
exec(self.command, var_dict, locals())
126+
else:
127+
exec(self.command, globals(), locals())
128+
118129
server.logger.debug(f'Task finished, name: {self.name}, task_type: {self.task_type}, command: {self.command}, '
119130
f'costs {time.time() - start_time} seconds.')
120131

121132

133+
def stop_all_schedule_daemon_threads():
134+
if len(temp_config.schedule_daemon_threads) == 0:
135+
return
136+
137+
for thr in temp_config.schedule_daemon_threads:
138+
thr.break_thread()
139+
temp_config.schedule_daemon_threads.remove(thr)
140+
141+
142+
class AThread(threading.Thread):
143+
def init_thread(self):
144+
super().__init__(daemon=True)
145+
146+
147+
class ScheduleTask(Task, AThread):
148+
def __init__(self, name, task_type, created_by, command, server_inst, exec_interval):
149+
super().__init__(name, task_type, created_by, command)
150+
self.server_inst = server_inst
151+
self.exec_interval = exec_interval
152+
self.stop_event = threading.Event()
153+
super().init_thread()
154+
temp_config.schedule_daemon_threads.append(self)
155+
156+
def break_thread(self):
157+
self.stop_event.set()
158+
159+
def run(self):
160+
if self.exec_interval <= 0:
161+
self.server_inst.logger.warning(
162+
f'Schedule task {self.name} has illegal exec_interval: {self.exec_interval}')
163+
return
164+
165+
while True:
166+
for _ in range(self.exec_interval):
167+
if self.stop_event.is_set():
168+
return
169+
sleep(1.0)
170+
self.execute_task(self.server_inst, 'schedule')
171+
172+
122173
class Configuration(Serializable):
123174
def __init__(self, **kwargs):
124175
super().__init__(**kwargs)
@@ -156,6 +207,8 @@ def __init__(self):
156207
task: dict[str, Task]
157208

158209
scripts_list: dict[str, str]
210+
211+
schedule_daemon_threads: list = list()
159212

160213

161214
temp_config: TempConfig
@@ -249,7 +302,7 @@ def unmount_task(hook: str, task: str, src: CommandSource, server: PluginServerI
249302

250303

251304
def create_task(task_type: str, command: str, name: str, src: CommandSource, server: PluginServerInterface,
252-
created_by=None):
305+
is_schedule=False, exec_interval=0, created_by=None):
253306
if name in temp_config.task:
254307
src.reply(RTextMCDRTranslation('hooks.create.already_exist'))
255308
return
@@ -266,7 +319,14 @@ def create_task(task_type: str, command: str, name: str, src: CommandSource, ser
266319
if created_by is None:
267320
created_by = str(src)
268321

269-
temp_config.task[name] = Task(name=name, task_type=tsk_type, command=command, created_by=created_by)
322+
if not is_schedule:
323+
temp_config.task[name] = Task(name=name, task_type=tsk_type, command=command, created_by=created_by)
324+
else:
325+
var1 = ScheduleTask(name=name, task_type=tsk_type, command=command, created_by=created_by,
326+
server_inst=server, exec_interval=exec_interval)
327+
temp_config.task[name] = var1
328+
var1.start()
329+
var1.name = f'hooks - schedule_task_daemon({name})'
270330

271331
server.logger.info(f'Successfully created task {name}')
272332
src.reply(RTextMCDRTranslation('hooks.create.success', name))
@@ -282,6 +342,11 @@ def delete_task(name: str, src: CommandSource, server: PluginServerInterface):
282342
if tasks_in_hook == name:
283343
unmount_task(hook, name, src, server)
284344

345+
var1 = temp_config.task.get(name)
346+
if isinstance(var1, ScheduleTask):
347+
var1.break_thread()
348+
temp_config.schedule_daemon_threads.remove(var1)
349+
285350
temp_config.task.pop(name)
286351

287352
server.logger.info(f'Successfully deleted task {name}')
@@ -314,7 +379,7 @@ def list_mount(src: CommandSource):
314379
list_hooks.append(str(temp_config.hooks.get(str(hk))))
315380

316381
src.reply(RTextMCDRTranslation('hooks.list.mount', *list_hooks))
317-
382+
318383

319384
@new_thread('hooks - list')
320385
def list_scripts(src: CommandSource):
@@ -332,6 +397,8 @@ def list_scripts(src: CommandSource):
332397
def reload_config(src: CommandSource, server: PluginServerInterface):
333398
global config, temp_config
334399

400+
stop_all_schedule_daemon_threads()
401+
335402
temp_config = TempConfig()
336403
config = server.load_config_simple(target_class=Configuration)
337404

@@ -394,7 +461,7 @@ def parse_and_apply_scripts(script: str, server: PluginServerInterface):
394461
create_task(task.get('task_type'), task.get('command'), task.get('name'),
395462
server.get_plugin_command_source(),
396463
server, created_by=script)
397-
464+
398465
for hook in task.get('hooks'):
399466
# 挂载
400467
mount_task(hook, task.get('name'), server.get_plugin_command_source(), server)
@@ -464,6 +531,25 @@ def on_load(server: PluginServerInterface, old_module):
464531
)
465532
)
466533
)
534+
.then(
535+
Literal('schedule')
536+
.then(
537+
Text('name')
538+
.then(
539+
Integer('exec_interval')
540+
.then(
541+
Text('task_type')
542+
.then(
543+
GreedyText('command')
544+
.requires(lambda src: src.has_permission(3))
545+
.runs(lambda src, ctx: create_task(ctx['task_type'], ctx['command'], ctx['name'], src,
546+
server, is_schedule=True,
547+
exec_interval=ctx['exec_interval']))
548+
)
549+
)
550+
)
551+
)
552+
)
467553
.then(
468554
Literal('mount')
469555
.then(
@@ -535,6 +621,9 @@ def on_load(server: PluginServerInterface, old_module):
535621

536622
def on_unload(server: PluginServerInterface):
537623
global temp_config
624+
625+
stop_all_schedule_daemon_threads()
626+
538627
trigger_hooks(Hooks.on_plugin_unloaded, server, {'server': process_arg_server(server)})
539628

540629
server.save_config_simple(config)

0 commit comments

Comments
 (0)