https://github.com/folk-project/folk-core
Core Rust workspace for Folk: protocol, plugin API, server core, pipe and fork runtimes
https://github.com/folk-project/folk-core
application-server folk msgpack php rust unix-socket worker-pool
Last synced: 19 days ago
JSON representation
Core Rust workspace for Folk: protocol, plugin API, server core, pipe and fork runtimes
- Host: GitHub
- URL: https://github.com/folk-project/folk-core
- Owner: Folk-Project
- License: mit
- Created: 2026-05-07T23:23:20.000Z (26 days ago)
- Default Branch: develop
- Last Pushed: 2026-05-13T10:10:24.000Z (20 days ago)
- Last Synced: 2026-05-13T12:40:03.269Z (20 days ago)
- Topics: application-server, folk, msgpack, php, rust, unix-socket, worker-pool
- Language: Rust
- Size: 174 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
README
# folk-core
Rust-based application server for PHP. Long-lived workers, fork-based runtime with warm OPcache, plugin ecosystem.
> **Status:** in active development. See [folk-spec](https://github.com/Folk-Project/folk-spec) for the roadmap.
## Requirements
- Rust 1.85+
- PHP 8.2+ with `ext-msgpack`
- Unix-like OS (Linux or macOS)
## Installation
```toml
# Cargo.toml
folk-core = "0.1"
```
For most users, build a custom binary with [folk-builder](https://github.com/Folk-Project/folk-builder) instead of depending on this crate directly.
## Quick start
1. Create a minimal `folk.toml`:
```toml
[server]
runtime = "pipe"
rpc_socket = "/tmp/folk.sock"
shutdown_timeout = "30s"
[workers]
script = "vendor/bin/folk-worker"
php = "php"
count = 4
[log]
filter = "info"
format = "text"
```
2. Start the server:
```bash
folk serve --config folk.toml
```
3. Expected startup output:
```
INFO folk server starting version=0.1.0 workers=4 runtime=pipe
INFO worker pool started
INFO all plugins booted plugins=["http", "metrics"]
INFO admin RPC server listening socket=/tmp/folk.sock
```
4. Stop with `Ctrl-C` or `SIGTERM`. The server drains gracefully:
```
INFO received SIGTERM
INFO shutdown signal received; draining
INFO http shutting down
INFO metrics shutting down
INFO folk server stopped
```
## Configuration
All fields can be overridden with environment variables using the `FOLK_` prefix (e.g., `FOLK_WORKERS_COUNT=8`). Config is loaded as: defaults → `folk.toml` → environment variables.
### `[server]`
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `runtime` | `"pipe"` \| `"fork"` | `"pipe"` | Worker runtime. `pipe` spawns via execve; `fork` uses a prefork master with warm OPcache. |
| `rpc_socket` | `String` | `"/tmp/folk.sock"` | Unix socket path for the admin RPC server. |
| `shutdown_timeout` | `Duration` | `"30s"` | Maximum time to wait for graceful shutdown before forcing exit. |
### `[workers]`
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `script` | `String` | `"vendor/bin/folk-worker"` | Path to the PHP worker entry script. |
| `php` | `String` | `"php"` | PHP binary path. |
| `count` | `usize` | `4` | Number of worker processes. |
| `max_jobs` | `u64` | `1000` | Requests a worker handles before being recycled. |
| `ttl` | `Duration` | `"3600s"` | Maximum worker lifetime before recycling. |
| `max_memory_mb` | `u64` | `256` | RSS memory limit (MB) before recycling. |
| `exec_timeout` | `Duration` | `"30s"` | Per-request execution timeout. |
| `boot_timeout` | `Duration` | `"30s"` | Timeout for worker to send `control.ready`. |
### `[log]`
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `filter` | `String` | `"info"` | Log level filter. Supports per-module: `folk_core=trace`. Overridden by `RUST_LOG`. |
| `format` | `"text"` \| `"json"` \| `"pretty"` | `"text"` | Log output format. Use `json` for log aggregators. |
## How it works
Folk supervises long-lived PHP processes and dispatches HTTP requests, jobs, and gRPC calls to them over a length-prefixed MessagePack-RPC protocol on Unix sockets.
### Runtimes
**Pipe runtime** (default) — spawns each PHP worker via `execve` with a Unix socketpair. Each worker is independent and stateless. Workers communicate over two file descriptors: FD 3 (task channel) and FD 4 (control channel).
**Fork runtime** — a prefork master boots the PHP framework once, warming OPcache and autoload caches. Workers are then `fork()`-ed from the master, inheriting the warm state. This eliminates cold-start overhead per worker. Requires `ext-pcntl`.
### Worker lifecycle
Workers cycle through states: **Spawning** → **Idle** → **Busy** → back to Idle, until recycled. A worker is recycled when it exceeds `max_jobs`, `ttl`, or `max_memory_mb`. Recycled workers are replaced immediately.
### Shutdown behavior
On `SIGTERM` or `SIGINT`:
1. The shutdown signal broadcasts to all components.
2. Plugins shut down in **reverse registration order**.
3. Workers finish in-flight requests (graceful drain).
4. If drain exceeds `shutdown_timeout`, remaining tasks are aborted.
5. The admin RPC socket is removed and the process exits.
### Plugin system
Plugins are compiled into the binary via [folk-builder](https://github.com/Folk-Project/folk-builder). Each plugin depends only on [folk-api](https://github.com/Folk-Project/folk-api), not on folk-core. Plugins boot in registration order and shut down in reverse. See [folk-api](https://github.com/Folk-Project/folk-api) for the plugin authoring guide.
### Repository layout
```
crates/
├── folk-protocol/ wire format (RpcMessage, FrameCodec)
├── folk-core/ server core (worker pool, plugin registry)
├── folk-runtime-pipe/ runtime: spawn via execve + Unix socketpair
└── folk-runtime-fork/ runtime: warm OPcache via prefork
folk/ reference binary (folk serve)
```
## License
MIT