Monitoring & Alerting
Continuously poll metrics, health endpoints, or infrastructure telemetry. Fire alerts when thresholds are exceeded without adding latency to user-facing requests.
A daemon thread is a long-running background process that starts with your application and runs for as long as it does. Despite the name, it is not an OS thread — it is a child process supervised by the framework. Use one for work that must always be running: polling a queue, tailing a stream, monitoring an external system, or processing database rows in a loop. If a daemon exits unexpectedly (an unhandled exception or running out of memory), the framework restarts it, so you do not need your own process supervisor.
#[DaemonThread] AttributeApply #[DaemonThread] to a class that extends ServerWorkerProcess. The attribute accepts two optional parameters:
name string (default: Class name)
A human-readable label for the daemon process, used in logs and process tables.
coreSize int (default: 1)
Number of daemon process instances to start. Set to 0 (or any negative value) to disable the daemon entirely — useful for feature-flagging in different environments.
use dev\winterframework\stereotype\cli\DaemonThread;use dev\winterframework\io\process\ServerWorkerProcess;use dev\winterframework\io\process\ProcessType;
#[DaemonThread(name: 'my-processor', coreSize: 2)]class SomeBackendProcessing extends ServerWorkerProcess{ // …}Every daemon class must extend ServerWorkerProcess and implement three members:
| Member | Visibility | Description |
|---|---|---|
getProcessType(): int |
public abstract |
Returns a ProcessType constant identifying the process role. |
getProcessId(): string |
public abstract |
Returns a unique string identifier for this daemon instance (used by the supervisor). |
run(): void |
protected abstract |
Contains the daemon’s main loop. Called once at startup; the process lives as long as this method runs. |
getProcessType() should return one of the constants defined on the ProcessType interface. For custom daemon threads, use ProcessType::OTHER unless you are extending a built-in framework process type.
| Constant | Value | Meaning |
|---|---|---|
ProcessType::OTHER |
0 |
General-purpose background process. |
ProcessType::MASTER |
1 |
Framework master process. |
ProcessType::MANAGER |
2 |
Framework manager process. |
ProcessType::HTTP_WORKER |
3 |
HTTP request worker. |
ProcessType::TASK_WORKER |
4 |
Generic task worker. |
ProcessType::ASYNC_WORKER |
5 |
Async execution worker (see Async Tasks). |
ProcessType::SCHED_WORKER |
6 |
Scheduling worker (see Scheduling). |
ProcessType::KV_MONITOR |
7 |
Key-value store monitor. |
ProcessType::QUEUE_MONITOR |
8 |
Queue monitor. |
ProcessType::KV_SERVER |
9 |
Key-value server process. |
ProcessType::QUEUE_SERVER |
10 |
Queue server process. |
The following example polls a database table for pending rows, processes each one, and then sleeps for five seconds before repeating.
use dev\winterframework\stereotype\cli\DaemonThread;use dev\winterframework\io\process\ServerWorkerProcess;use dev\winterframework\io\process\ProcessType;use dev\winterframework\stereotype\Autowired;use dev\winterframework\pdbc\PdbcTemplate;
#[DaemonThread]class SomeBackendProcessing extends ServerWorkerProcess{ #[Autowired] protected PdbcTemplate $pdbc;
public function getProcessType(): int { return ProcessType::OTHER; }
public function getProcessId(): string { return 'my-backend-processor'; }
protected function run(): void { while (1) { $to_process = $this->pdbc->queryForList( "SELECT * FROM SOME_TABLE WHERE STATUS = 'PENDING'" );
foreach ($to_process as $row) { // process each pending row … }
// sleep for 5 seconds (Swoole coroutine-safe) \Co::sleep(5); } }}#[Autowired] works inside daemon thread classes just as it does in regular service beans. The framework performs property injection before calling run(), so any container-managed bean — database templates, configuration properties, other services — is available as soon as your loop starts.
use dev\winterframework\stereotype\cli\DaemonThread;use dev\winterframework\io\process\ServerWorkerProcess;use dev\winterframework\io\process\ProcessType;use dev\winterframework\stereotype\Autowired;use dev\winterframework\pdbc\PdbcTemplate;
#[DaemonThread(name: 'order-processor', coreSize: 1)]class OrderProcessingDaemon extends ServerWorkerProcess{ #[Autowired] private PdbcTemplate $pdbc;
#[Autowired] private NotificationService $notifier;
public function getProcessType(): int { return ProcessType::OTHER; }
public function getProcessId(): string { return 'order-processor'; }
protected function run(): void { while (1) { $orders = $this->pdbc->queryForList( "SELECT * FROM ORDERS WHERE STATUS = 'NEW' LIMIT 10" );
foreach ($orders as $order) { // Fulfill the order … $this->notifier->sendConfirmation($order['customer_email'], $order['id']); }
\Co::sleep(3); } }}The framework monitors every daemon process. If a daemon exits — an uncaught exception, running out of memory, or any other crash — it is restarted automatically. You do not need an external process manager (like Supervisor or systemd) to keep daemons alive.
Monitoring & Alerting
Continuously poll metrics, health endpoints, or infrastructure telemetry. Fire alerts when thresholds are exceeded without adding latency to user-facing requests.
Stream Processing
Consume messages from a queue, Kafka topic, or event stream in a tight loop. Process and acknowledge messages entirely outside the HTTP worker pool.
Background Jobs
Pick up pending database rows, trigger batch reports, or run data-migration steps continuously in the background without blocking API responses.
Supervision & Coordination
Coordinate other parts of the system — purging stale sessions, refreshing shared caches, or watching worker health.