Enhance the reliability and observability of the task execution engine by introducing retry mechanisms, idempotency, and structured progress tracking. - Implement centralized retry logic with exponential backoff support in `JobLifecycle`. - Add `retry_task` API endpoint and `TaskManager` method for manual task restarts. - Introduce task idempotency using `_idempotency_key` to prevent duplicate executions. - Add `retry_count`, `max_retries`, `last_error`, and `progress` fields to the `Task` model and ensure persistence via `TaskPersistenceService`. - Upgrade `SchedulerService` to use differential synchronization with the persistent `SQLAlchemyJobStore` for better job durability. - Implement structured heartbeat logging to support real-time progress updates. - Update project documentation and ADRs to reflect the new plugin runtime and task resilience patterns. - Add comprehensive unit and integration tests for the new task lifecycle features.
2.1 KiB
2.1 KiB
[DEF:ADR-0016:ADR]
@STATUS ACCEPTED
@PURPOSE Define the implemented plugin discovery and execution boundary.
@RELATION SUPERSEDES -> [ADR-0004:ADR]
@RELATION BINDS_TO -> [backend/src/core/plugin_loader.py]
@RELATION BINDS_TO -> [backend/src/core/plugin_base.py]
@RATIONALE The repository already contains first-party plugins that share the application runtime, configuration, database access patterns, and async Task Manager. The executable contract is PluginBase, not an unimplemented manifest or subprocess protocol.
@REJECTED plugin.toml manifests and a mandatory subprocess executor — rejected as the current architecture because neither is the runtime contract implemented by the repository.
@REJECTED Treating dynamic discovery as a sandbox — rejected because imported plugin code runs in the backend process and has the same process privileges.
Decision
First-party plugins live in backend/src/plugins/. PluginLoader discovers Python
modules and package __init__.py files in that directory, imports them under the
src.plugins package, instantiates subclasses of PluginBase, and exposes their
validated PluginConfig metadata.
Every discoverable plugin must implement the abstract PluginBase contract:
- stable
id,name,description, andversionproperties; get_schema()returning an input schema;- asynchronous
execute(params); - optional
ui_routeand a permission derived fromrequired_permission.
Plugins are trusted, versioned source in this repository. They are not third-party sandboxed extensions. A future marketplace or untrusted-plugin feature requires a new ADR that specifies its isolation, permission, resource, and failure model.
Consequences
- Plugin failures during discovery are logged and do not stop discovery of other modules, but execution remains subject to normal backend failure handling.
- Plugin dependencies must be compatible with the backend runtime.
- Adding a plugin requires tests for discovery and its public execution contract;
it does not require a
plugin.tomlmanifest.