Skip to content

Daemon Threads Sample Application

Build an app with a supervised background daemon that watches an inbox directory and processes new files as they arrive. You use the #[DaemonThread] annotation on a ServerWorkerProcess subclass. The framework starts the daemon with your app and restarts it if it crashes, so you never wire up your own process supervisor.

Use a daemon for work that must always be running — watching a directory, polling a queue, or tailing a stream. Use scheduled tasks instead when the work runs on a fixed cadence.

You need PHP 8.5 or later with the swoole and pcntl extensions. No external services are needed.

The sample uses this layout:

daemon/
├── bin/
│ └── application.php # Application entry point
├── config/
│ └── application.yml # Winter Boot application config
├── src/
│ ├── DaemonSampleApplication.php # Main application class
│ └── daemon/
│ └── InboxWatcherDaemon.php # Daemon thread implementation
└── composer.json # Dependencies

Require the framework package:

Terminal window
composer require suvera/winter-boot

Switch between the source files. Each tab shows the exact file from the sample.

The single entry point. It points Winter Boot at the config directory and at the sample namespace.

<?php
namespace dev\example;
use dev\winterframework\stereotype\WinterBootApplication;
#[WinterBootApplication(
configDirectory: [__DIR__ . "/../config"],
scanNamespaces: [
['dev\\example', __DIR__ . '']
]
)]
class DaemonSampleApplication {
public static function main(): void {
$winterApp = new \dev\winterframework\core\app\WinterWebSwooleApplication();
$winterApp->run(self::class);
}
}

No module is needed — the daemon is a core framework feature. The full sample application.yml sets only the server and app identity:

server:
port: 8080
address: 0.0.0.0
context-path: /
winter:
application:
name: Daemon Threads Sample Application
id: daemon-sample-app
version: 1.0.0

See Configuration for every application.yml key.

Start the app, drop a file into the inbox, and watch the daemon process it.

1. Start the application:

Terminal window
composer install
php bin/application.php

The daemon creates /tmp/inbox and /tmp/processed on startup and begins scanning.

2. Drop a file into the inbox:

Terminal window
echo -e "line one\nline two\nline three" > /tmp/inbox/report.txt

3. Verify processing:

Terminal window
ls /tmp/processed

You see report.txt in the processed directory within 5 seconds, and the app log shows the line count:

Processing report.txt: 3 lines
Moved report.txt to processed
  • Read Daemon Threads for process types, coreSize scaling, and supervision details.
  • Read the Scheduler example when your work runs on a fixed cadence instead of continuously.