Runner Microservice
The Runner microservice executes scripts for digital twins in the DTaaS platform. It accepts HTTP requests to run pre-configured commands and returns the execution status and logs to the caller.
Package Structure
Architecture and Design
The microservice is built with the NestJS framework and runs commands
with the execa library. A queue holds the execution requests, and a
factory creates the runner instances.
Core Components
classDiagram
class AppController {
-manager: ExecaManager
+getHistory(): ExecuteCommandDto[]
+newCommand(dto): void
+cmdStatus(): CommandStatus
}
class ExecaManager {
-commandQueue: Queue
-config: Config
+newCommand(name): [boolean, Map]
+checkStatus(): CommandStatus
+checkHistory(): ExecuteCommandDto[]
}
class Queue {
-queue: Command[]
+enqueue(command): void
+checkHistory(): ExecuteCommandDto[]
+activeCommand(): Command
}
class RunnerFactory {
+create(command): Runner
}
class ExecaRunner {
-command: string
-stdout: string
-stderr: string
+run(): Promise~boolean~
+checkLogs(): Map
}
class Config {
-configValues: ConfigValues
+loadConfig(options): void
+permitCommands(): string[]
+getPort(): number
+getLocation(): string
}
AppController --> ExecaManager : uses
ExecaManager --> Queue : uses
ExecaManager --> Config : uses
ExecaManager --> RunnerFactory : uses
RunnerFactory --> ExecaRunner : creates
Main Components
REST API Controller
The AppController exposes three endpoints:
| Endpoint | Method | Purpose |
|---|---|---|
/ |
POST | Submit a new command for execution |
/ |
GET | Get status of the current command |
/history |
GET | Retrieve execution history |
Execution Manager
The ExecaManager service runs each command in these steps:
- Adds the command to the queue, marked
invalid. - Checks the command against the list of permitted commands.
- For a permitted command, creates a runner through the factory and runs the script from the configured location.
- Marks the command
validif the script succeeds, and returns the status and logs.
Command Queue
The Queue service keeps the execution history and tracks the active
command. Each command is stored with its execution status (valid or
invalid).
Runner Interface
The Runner interface defines the contract for command executors:
Configuration
The service reads its configuration from a YAML file
(see config/runner.yaml.sample) with these settings:
| Setting | Purpose |
|---|---|
port |
HTTP server port |
location |
Base directory for executable scripts |
commands |
Allowlist of permitted command names |
Security Considerations
The runner only executes commands that are listed in the configuration
file. A request for any other command is recorded as invalid and not
run, which prevents arbitrary command execution.