PHPackages                             menumbing/graceful-process - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. menumbing/graceful-process

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

menumbing/graceful-process
==========================

Graceful shutdown component for Hyperf processes

0187↑450%PHP

Since Apr 27Pushed 1mo agoCompare

[ Source](https://github.com/menumbing/graceful-process)[ Packagist](https://packagist.org/packages/menumbing/graceful-process)[ RSS](/packages/menumbing-graceful-process/feed)WikiDiscussions master Synced 1w ago

READMEChangelogDependenciesVersions (1)Used By (0)

Graceful Process for Hyperf
===========================

[](#graceful-process-for-hyperf)

Process-completion-aware graceful shutdown for [Hyperf](https://hyperf.io) applications running on Swoole.

Instead of relying on fixed timeouts, this package monitors actual process and request completion. The server exits as soon as all in-flight work is done — custom processes finish their current job, and HTTP workers finish serving active requests.

Features
--------

[](#features)

- **Non-invasive** — works with existing custom processes without code changes; blocking operations (sleep, I/O, message consumption) complete naturally
- **HTTP request protection** — in-flight requests complete normally; new requests are rejected during shutdown
- **Process-aware shutdown** — tracks custom processes and HTTP workers via shared-memory counters; exits immediately when all are done
- **Dual signal support** — handles both SIGTERM (Docker/Kubernetes) and SIGINT (Ctrl+C)
- **Dual mode support** — works with both SWOOLE\_BASE and SWOOLE\_PROCESS modes
- **Zero configuration** — works out of the box with sensible defaults

Requirements
------------

[](#requirements)

- PHP &gt;= 8.1
- Hyperf &gt;= 3.1
- Swoole (SWOOLE\_BASE or SWOOLE\_PROCESS mode)
- ext-ffi (recommended, for clean process exit and inherited socket cleanup)

Installation
------------

[](#installation)

```
composer require menumbing/graceful-process
```

Publish the configuration file:

```
php bin/hyperf.php vendor:publish menumbing/graceful-process
```

Configuration
-------------

[](#configuration)

```
// config/autoload/graceful_process.php

return [
    /*
     * Safety-net timeout in seconds for the overall shutdown.
     *
     * This should be set to at least the longest expected blocking operation
     * duration in your custom processes.
     *
     * Docker's stop_grace_period (or Kubernetes terminationGracePeriodSeconds)
     * must be >= this value.
     *
     * Default: 300 seconds (5 minutes)
     */
    'timeout' => (int) env('GRACEFUL_PROCESS_TIMEOUT', 300),

    /*
     * Maximum time in seconds that HTTP workers wait for in-flight
     * requests to complete before force-stopping.
     *
     * Set this to at least your longest expected HTTP request duration.
     *
     * Defaults to 'timeout' if not set.
     */
    'max_wait_time' => (int) env('GRACEFUL_PROCESS_MAX_WAIT_TIME', 30),
];
```

### Docker / Kubernetes

[](#docker--kubernetes)

Make sure the container's grace period is at least as long as `timeout`:

```
# docker-compose.yml
services:
  app:
    stop_grace_period: 5m   # must be >= graceful_process.timeout
    init: true               # recommended: uses tini for proper signal forwarding
```

```
# Kubernetes
spec:
  terminationGracePeriodSeconds: 300  # must be >= graceful_process.timeout
```

Usage
-----

[](#usage)

### HTTP Requests

[](#http-requests)

HTTP requests are protected automatically — no code changes needed.

When SIGTERM or SIGINT arrives:

1. In-flight requests continue and complete normally
2. New requests are rejected:
    - **SWOOLE\_BASE**: listening sockets closed — `connection refused` at TCP level
    - **SWOOLE\_PROCESS**: `503 Service Unavailable` with `Retry-After: 5` header
3. Workers exit as soon as all active requests finish

### Custom Processes

[](#custom-processes)

Custom processes work out of the box **without any code changes**. When shutdown is triggered:

1. `ProcessManager::isRunning()` returns `false` on the next loop check
2. The current blocking operation (sleep, I/O, message consumption) finishes naturally
3. The process exits cleanly

```
