mirror of
https://github.com/agentscope-ai/ReMe.git
synced 2026-10-13 04:01:35 +00:00
feat(jobs): allow disabling cron schedules independently
This commit is contained in:
parent
67135cfc57
commit
65546cb357
12 changed files with 94 additions and 5 deletions
|
|
@ -74,6 +74,19 @@ Keep secrets in `.env` or the process environment, never in committed configurat
|
|||
|
||||
`session_dir` must remain workspace-relative.
|
||||
|
||||
## Cron scheduling
|
||||
|
||||
`jobs.<name>.enable_schedule` defaults to `true` and controls automatic startup of cron jobs only.
|
||||
Set it to `false` when a host plugin owns the schedule:
|
||||
|
||||
```bash
|
||||
reme start jobs.dream_cron.enable_schedule=false
|
||||
```
|
||||
|
||||
Restart the service to apply the override. The `auto_dream` API remains available, and other jobs continue running.
|
||||
`enable_serve` separately controls service exposure; it does not disable scheduling. Disabled cron jobs retain their
|
||||
configuration but do not start their steps or background tasks. The switch has no effect on other job types.
|
||||
|
||||
## LLM
|
||||
|
||||
The default LLM uses an OpenAI-compatible interface:
|
||||
|
|
|
|||
|
|
@ -79,6 +79,17 @@ base_url: ${LLM_BASE_URL:-https://example.com/v1}
|
|||
|
||||
`session_dir` 必须保持 workspace-relative。其他 workspace 子目录也应使用清晰、稳定的相对名称。
|
||||
|
||||
## Cron 调度
|
||||
|
||||
`jobs.<name>.enable_schedule` 默认为 `true`,仅控制 cron Job 是否自动启动。由宿主插件负责调度时,可以关闭服务端对应任务:
|
||||
|
||||
```bash
|
||||
reme start jobs.dream_cron.enable_schedule=false
|
||||
```
|
||||
|
||||
重启服务后生效。`auto_dream` 接口仍可调用,其他 Job 继续运行。`enable_serve` 独立控制接口暴露,不控制调度。
|
||||
关闭的 cron 保留配置,但不启动 Steps 或后台任务;此开关对其他 Job 类型没有影响。
|
||||
|
||||
## LLM 配置
|
||||
|
||||
默认 LLM 使用 OpenAI-compatible 接口:
|
||||
|
|
|
|||
|
|
@ -41,9 +41,14 @@ host-specific plugin.
|
|||
|
||||
```bash
|
||||
reme start workspace_dir=/absolute/path/to/your/reme-workspace \
|
||||
service.host=127.0.0.1 service.port=3457
|
||||
service.host=127.0.0.1 service.port=3457 \
|
||||
jobs.dream_cron.enable_schedule=false
|
||||
```
|
||||
|
||||
The plugin owns the daily Dream schedule by default, so this disables ReMe's `dream_cron` while keeping the
|
||||
`auto_dream` API available. To use ReMe scheduling instead, omit this override and set the plugin's
|
||||
`autoDreamEnabled` to `false`. Shared services should have only one scheduler.
|
||||
|
||||
For development and screenshots, use an isolated directory outside the repository, such as `/tmp/reme-dsh-demo`. Do not write runtime memory into the repository's `.reme/` directory.
|
||||
|
||||
### 3.2 Install the DSH bundle
|
||||
|
|
|
|||
|
|
@ -40,9 +40,13 @@ ReMe HTTP 服务默认监听 `http://127.0.0.1:2333`,不使用 API Key 认证
|
|||
|
||||
```bash
|
||||
reme start workspace_dir=/absolute/path/to/your/reme-workspace \
|
||||
service.host=127.0.0.1 service.port=3457
|
||||
service.host=127.0.0.1 service.port=3457 \
|
||||
jobs.dream_cron.enable_schedule=false
|
||||
```
|
||||
|
||||
插件默认负责每日 Dream 调度,因此这里关闭 ReMe 的 `dream_cron`,保留 `auto_dream` 接口。
|
||||
若改由 ReMe 调度,省略该覆盖并将插件的 `autoDreamEnabled` 设为 `false`。多个宿主共享服务时,只启用一个调度方。
|
||||
|
||||
开发或截图测试时建议使用仓库外的独立目录,例如 `/tmp/reme-dsh-demo`,不要把运行时记忆写入 ReMe 仓库自身的 `.reme/`。
|
||||
|
||||
### 3.2 安装插件
|
||||
|
|
|
|||
|
|
@ -40,9 +40,14 @@ pip install "reme-ai[core]"
|
|||
reme start \
|
||||
workspace_dir=/absolute/path/to/reme-workspace \
|
||||
service.host=127.0.0.1 \
|
||||
service.port=3458
|
||||
service.port=3458 \
|
||||
jobs.dream_cron.enable_schedule=false
|
||||
```
|
||||
|
||||
The plugin owns the daily Dream schedule by default, so this disables ReMe's `dream_cron` while keeping the
|
||||
`auto_dream` API available. To use ReMe scheduling instead, omit this override and set the plugin's
|
||||
`autoDreamEnabled` to `false`. Shared services should have only one scheduler.
|
||||
|
||||
Verify the service without exposing configuration or credentials:
|
||||
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -37,9 +37,13 @@ pip install "reme-ai[core]"
|
|||
reme start \
|
||||
workspace_dir=/absolute/path/to/reme-workspace \
|
||||
service.host=127.0.0.1 \
|
||||
service.port=3458
|
||||
service.port=3458 \
|
||||
jobs.dream_cron.enable_schedule=false
|
||||
```
|
||||
|
||||
插件默认负责每日 Dream 调度,因此这里关闭 ReMe 的 `dream_cron`,保留 `auto_dream` 接口。
|
||||
若改由 ReMe 调度,省略该覆盖并将插件的 `autoDreamEnabled` 设为 `false`。多个宿主共享服务时,只启用一个调度方。
|
||||
|
||||
不读取或输出模型配置即可验证服务:
|
||||
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -206,6 +206,9 @@ class Application(BaseComponent):
|
|||
|
||||
async def _start_one(self, c: BaseComponent) -> None:
|
||||
"""Start one component and record it for ordered shutdown."""
|
||||
if isinstance(c, CronJob) and not c.enable_schedule:
|
||||
self.logger.info(f"Skipping disabled cron job: {c.name}")
|
||||
return
|
||||
try:
|
||||
if isinstance(c, BackgroundJob):
|
||||
self.logger.info(f"Starting background job: {c.name}")
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ class BaseJob(BaseComponent):
|
|||
enable_serve: bool = True,
|
||||
**kwargs,
|
||||
):
|
||||
kwargs.pop("enable_schedule", None)
|
||||
super().__init__(**kwargs)
|
||||
self.description = description
|
||||
self.parameters = parameters or {}
|
||||
|
|
|
|||
|
|
@ -13,9 +13,10 @@ from ...schema import Response
|
|||
class CronJob(BackgroundJob):
|
||||
"""Run this job's own steps on a cron expression."""
|
||||
|
||||
def __init__(self, cron: str, **kwargs):
|
||||
def __init__(self, cron: str, enable_schedule: bool = True, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.cron_expr = cron
|
||||
self.enable_schedule = enable_schedule
|
||||
|
||||
async def _start(self) -> None:
|
||||
from croniter import croniter
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ class JobConfig(ComponentConfig):
|
|||
parameters: dict = Field(default_factory=dict, description="Job-level parameters")
|
||||
steps: list[ComponentConfig] = Field(default_factory=list, description="Ordered step configs")
|
||||
enable_serve: bool = Field(default=True, description="Whether to expose this job through the service layer")
|
||||
enable_schedule: bool = Field(default=True, description="Whether to start automatic scheduling for a cron job")
|
||||
|
||||
|
||||
class ApplicationConfig(BaseModel):
|
||||
|
|
|
|||
|
|
@ -10,8 +10,23 @@ from reme.config.config_parser import (
|
|||
_read_config_file,
|
||||
parse_args,
|
||||
parse_dot_notation,
|
||||
parse_kwargs,
|
||||
resolve_app_config,
|
||||
)
|
||||
from reme.schema import ApplicationConfig
|
||||
|
||||
|
||||
def test_cli_disables_dream_schedule_without_disabling_manual_job():
|
||||
"""A CLI schedule override preserves callable jobs and other default schedules."""
|
||||
cfg = ApplicationConfig(
|
||||
**resolve_app_config(log_config=False, **parse_kwargs("jobs.dream_cron.enable_schedule=false")),
|
||||
)
|
||||
|
||||
assert cfg.jobs["dream_cron"].enable_schedule is False
|
||||
assert cfg.jobs["dream_cron"].backend == "cron"
|
||||
assert cfg.jobs["auto_dream"].enable_serve is True
|
||||
assert cfg.jobs["auto_dream"].steps
|
||||
assert cfg.jobs["optimize_index_cron"].enable_schedule is True
|
||||
|
||||
|
||||
def test_load_builtin_config_by_filename_with_suffix():
|
||||
|
|
|
|||
|
|
@ -384,6 +384,32 @@ def test_application_starts_jobs_base_stream_background_cron():
|
|||
asyncio.run(run())
|
||||
|
||||
|
||||
@pytest.mark.parametrize("enabled", [True, False])
|
||||
def test_application_respects_cron_schedule_switch(enabled):
|
||||
async def run():
|
||||
app = object.__new__(Application)
|
||||
app._started_components = []
|
||||
app.logger = MagicMock()
|
||||
job = CronJob(cron="0 23 * * *", enable_schedule=enabled, enable_serve=True, name="dream_cron")
|
||||
job.start = AsyncMock()
|
||||
|
||||
await app._start_one(job)
|
||||
|
||||
assert job.start.await_count == int(enabled)
|
||||
assert app._started_components == ([job] if enabled else [])
|
||||
assert job.enable_serve is False
|
||||
assert job._task is None
|
||||
|
||||
for cls in (BaseJob, StreamJob, BackgroundJob):
|
||||
other = cls(enable_schedule=False)
|
||||
other.start = AsyncMock()
|
||||
await app._start_one(other)
|
||||
other.start.assert_awaited_once()
|
||||
assert "enable_schedule" not in other.kwargs
|
||||
|
||||
asyncio.run(run())
|
||||
|
||||
|
||||
def test_application_start_failure_propagates_and_closes_started_components():
|
||||
async def run():
|
||||
class GoodComponent(BaseComponent):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue