Skip to content

Implement Entity Status and Restart (lifecycle control) endpoints #207

@bburda

Description

@bburda

Summary

Entity status and restart endpoints allow clients to monitor the lifecycle state of entities (whether they are operational or not) and to control their lifecycle (start, stop, restart). Not all entities support all lifecycle operations - the response dynamically advertises which transitions are available.


Proposed solution

1. GET /api/v1/{entity-path}/status

Read the current lifecycle status of an entity.

Applies to entity types: Components, Apps

Path parameters:

Parameter Type Required Description
{entity-path} URL segment Yes e.g., apps/temp_sensor or components/engine_ecu

Response 200 OK:

{
  "status": "ready",
  "start": "/api/v1/apps/temp_sensor/status/start",
  "restart": "/api/v1/apps/temp_sensor/status/restart",
  "force-restart": "/api/v1/apps/temp_sensor/status/force-restart",
  "shutdown": "/api/v1/apps/temp_sensor/status/shutdown",
  "force-shutdown": "/api/v1/apps/temp_sensor/status/force-shutdown"
}
Field Type Required Description
status string Yes Current status: ready or notReady
start string (URI) No URI to start the entity (only present if entity is stopped and supports start)
restart string (URI) No URI for graceful restart (only if supported)
force-restart string (URI) No URI for forced restart (only if supported)
shutdown string (URI) No URI for graceful shutdown (only if supported)
force-shutdown string (URI) No URI for forced shutdown (only if supported)

Status values:

Status Description
ready Entity is operational and responding
notReady Entity is not operational (stopped, restarting, crashed, or unreachable)

Key behavior: The URI fields are only present if the entity supports that transition. If an entity doesn't support lifecycle management, only status is returned.

Error: 404 if entity doesn't exist.


2. PUT /api/v1/{entity-path}/status/start

Start a stopped entity.

Request body: None

Response 202 Accepted - the start operation has been initiated. Poll GET /{entity-path}/status to track progress.

The Location header points to the status resource.

Error responses:

Status Error Code When
403 forbidden Client lacks permission to start this entity
409 invalid-request Entity is already running, or start is not a valid transition from current state

3. PUT /api/v1/{entity-path}/status/restart

Perform a graceful restart - the entity shuts down cleanly, then starts again.

Response 202 Accepted

Errors: Same as start (403, 409).


4. PUT /api/v1/{entity-path}/status/force-restart

Perform a forced restart - immediately terminate and restart without graceful shutdown.

Response 202 Accepted

Errors: Same as start (403, 409).


5. PUT /api/v1/{entity-path}/status/shutdown

Perform a graceful shutdown - the entity cleanly finishes current work and stops.

Response 202 Accepted

Errors: 403, 409 (entity is already stopped).


6. PUT /api/v1/{entity-path}/status/force-shutdown

Immediately terminate the entity without graceful shutdown.

Response 202 Accepted

Errors: 403, 409.


Additional context

ROS 2 mapping

Status detection:

  • Check if the App's ROS 2 node is visible in the graph via DiscoveryManager - if present → ready, if absent → notReady
  • The App.is_online field already tracks this for runtime-discovered nodes

Lifecycle control (depends on node type):

Node Type Approach
Lifecycle nodes (rclcpp_lifecycle) Call ChangeState service: configure, activate, deactivate, shutdown
Standard nodes No native stop/restart API. Options: return 501 for control endpoints, or use an external process manager
Launch-managed nodes Interact with the launch system (complex integration)

Recommended initial implementation:

  1. Always implement GET /status - use is_online to determine ready/notReady
  2. For lifecycle nodes: implement restart/shutdown via lifecycle service calls
  3. For non-lifecycle nodes: return 501 Not Implemented or omit the control URIs from the status response

Detecting lifecycle node support

At discovery time, check if the node provides lifecycle services:

  • /{node}/change_state (service type: lifecycle_msgs/srv/ChangeState)
  • /{node}/get_state (service type: lifecycle_msgs/srv/GetState)

If these services exist, the entity supports lifecycle control.

Route registration

srv->Get((api_path("/apps") + R"(/([^/]+)/status$)"), handler);
srv->Put((api_path("/apps") + R"(/([^/]+)/status/start$)"), handler);
srv->Put((api_path("/apps") + R"(/([^/]+)/status/restart$)"), handler);
srv->Put((api_path("/apps") + R"(/([^/]+)/status/force-restart$)"), handler);
srv->Put((api_path("/apps") + R"(/([^/]+)/status/shutdown$)"), handler);
srv->Put((api_path("/apps") + R"(/([^/]+)/status/force-shutdown$)"), handler);
// Same for /components/

Important: Register specific status sub-routes (/status/start, /status/restart, etc.) before the generic /status$ route.

Tests

  • Unit test: GET status for online app → ready with available transitions
  • Unit test: GET status for offline app → notReady
  • Unit test: restart lifecycle node → 202, status transitions
  • Unit test: restart non-lifecycle node → 501
  • Unit test: start already running entity → 409
  • Unit test: shutdown already stopped entity → 409
  • Integration test: GET status for demo nodes

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions