Skip to content

Lifecycle

This document defines the lifecycle contract for BotFlux components. All rules described below are mandatory for component and infrastructure implementations.


Control Model

The BotFlux lifecycle follows a directed control model:

  • control commands flow top-down (start(), stop())
  • state events flow bottom-up via subscription (addListener(Status, Throwable))

Lifecycle commands are initiated exclusively by the component owner. Components must not manage the lifecycle of other components and must not invoke start() or stop() on external objects.

Lifecycle events are intended solely for observation, logging, and orchestration.


Lifecycle States

Each lifecycle-enabled component is always in exactly one of the following states:

  • NEW — the component is created
  • STARTING — the component is performing initialization
  • ACTIVE — the component is fully started and operational
  • STOPPING — the component is performing a graceful shutdown
  • TERMINATED — the component is fully stopped
  • FAILED — execution has failed; the state is accompanied by a Throwable

The FAILED and TERMINATED states are terminal.


Single-Use Components

All BotFlux components with a lifecycle are single-use:

  • start() may be invoked only once
  • stop() may be invoked only once
  • re-entry into the STARTING state is not permitted

After transitioning to TERMINATED or FAILED, restarting the component is forbidden by contract. A new lifecycle requires a new component instance.


Allowed State Transitions

stateDiagram-v2
    New --> Starting
    New --> Active
    New --> Stopping
    New --> Terminated
    New --> Failed
    Starting --> Active
    Starting --> Stopping
    Starting --> Terminated
    Starting --> Failed
    Active --> Stopping
    Active --> Terminated
    Active --> Failed
    Stopping --> Terminated
    Stopping --> Failed
    Stopping --> Terminated
    Stopping --> Failed

The diagram defines the full set of allowed state transitions. Transitions outside this graph are rejected by the lifecycle implementation and cannot be initiated by components.


Lifecycle Events

A component must support listener registration:

addListener(BiConsumer<Status, Throwable>)

Listeners are invoked after a state transition has been committed.

Rules:

  • when transitioning to FAILED, the corresponding Throwable is provided
  • for normal transitions, Throwable is null
  • listeners must not throw exceptions
  • listeners must not block the execution thread

Listeners are not intended to control component lifecycles.


BotFlux Lifecycle

Startup Order

Invocation:

botFlux.start();

initiates system startup in the following order:

  1. Startup of BotFluxContext
  2. Startup of components registered in the context
  3. Startup of DispatcherManager
  4. Startup of dispatchers

Each step is executed only after the previous one has completed successfully.


BotFluxContext

BotFluxContext owns all registered components.

During context startup:

  1. The context transitions to STARTING
  2. All components are started in a defined order
  3. If any component fails, the context transitions to FAILED
  4. After all components have started successfully, the context transitions to ACTIVE

DispatcherManager

DispatcherManager is started only after the context has transitioned to ACTIVE.

During startup:

  1. The manager transitions to STARTING
  2. Dispatchers are created and started
  3. After all dispatchers have started successfully, the manager transitions to ACTIVE

Dispatchers

Each dispatcher:

  • is a lifecycle-enabled component
  • follows the common state transition rules
  • is started and stopped by the dispatcher manager

System Shutdown

BotFlux shutdown is performed in the reverse order of startup:

  1. Dispatchers are stopped
  2. DispatcherManager is stopped
  3. BotFluxContext is stopped
  4. All context components are stopped

The stop() method is idempotent and guarantees a transition to TERMINATED.


Lifecycle Propagation Diagram

flowchart TD
    S@{shape: circle, label: "Control"}
    BF[BotFlux]
    BF[BotFlux]
    BFC[BotFluxContext]
    BC@{shape: procs, label: "BotComponent"}
    BDM[BotDispatcherManager]
    BD@{shape: procs, label: "BotDispatcher"}
    BG[BotGateway]

    S --> |Command| BF
    BF --> |Event| S

    BF --> |Command| BFC
    BFC --> |Event| BF

    BF --> |Command| BDM
    BDM --> |Event| BF

    BFC --> |Command| BC
    BC --> |Event| BFC

    BDM --> |Command| BD
    BD --> |Event| BDM

    BD --> |Command| BG
    BG --> |Event| BD