vigil
Vigil
A process supervision and inter-process communication library for Zig, designed for building reliable distributed systems and concurrent applications. Inspired by Erlang/OTP.
Installation
zig fetch --save "git+https://github.com/ooyeku/vigil"
Add as a dependency in your build.zig:
const vigil = b.dependency("vigil", .{
.target = target,
.optimize = optimize,
});
exe.root_module.addImport("vigil", vigil.module("vigil"));
Quick Start
Simple Worker Application
const std = @import("std");
const vigil = @import("vigil");
fn worker() void {
std.debug.print("Worker running\n", .{});
std.Thread.sleep(100 * std.time.ns_per_ms);
}
pub fn main() !void {
var gpa: std.heap.DebugAllocator(.{}) = .init;
defer _ = gpa.deinit();
const allocator = gpa.allocator();
var app = try vigil.app(allocator);
_ = try app.worker("task1", worker);
_ = try app.workerPool("pool", worker, 4);
try app.start();
defer app.shutdown();
}
Channel-Like Message Passing
var inbox = try vigil.inbox(allocator);
defer inbox.close();
try inbox.send("hello");
if (try inbox.recvTimeout(1000)) |msg| {
defer msg.deinit();
std.debug.print("Received: {s}\n", .{msg.payload.?});
}
Circuit Breaker for Resilience
var breaker = try vigil.CircuitBreaker.init(allocator, "api", .{
.failure_threshold = 5,
.reset_timeout_ms = 30000,
});
defer breaker.deinit();
if (breaker.getState() == .open) {
// Service unavailable, fail fast
}
Rate Limiting
var limiter = vigil.RateLimiter.init(100); // 100 ops/sec
if (limiter.allow()) {
// Process request
} else {
// Rate limited
}
Process Groups
var group = try vigil.ProcessGroup.init(allocator, "workers");
defer group.deinit();
try group.add("worker1", inbox1);
try group.add("worker2", inbox2);
try group.broadcast("message"); // Send to all
try group.roundRobin("message"); // Load balance
Features
Core
- Process Supervision - Automatic restart strategies (one_for_one, one_for_all, rest_for_one)
- Message Passing - Thread-safe inboxes with priority queues
- Fluent Builders - Intuitive API with sensible defaults
- Configuration Presets - Production, development, HA, and testing modes
Resilience
- Circuit Breaker - Protect services from cascading failures
- Rate Limiting - Token bucket algorithm for flow control
- Backpressure - Strategies for handling overload (drop_oldest, drop_newest, block, error)
Messaging
- Pub/Sub - Topic-based messaging with wildcard support
- Process Groups - Manage related processes with broadcast/round-robin routing
- Request/Reply - Synchronous messaging with correlation IDs
Observability
- Telemetry - Event hooks for monitoring (process, message, supervisor, circuit events)
- Testing Utilities - Mock inboxes, mock supervisors, time control
Advanced
- Graceful Shutdown - Coordinated cleanup with shutdown hooks
- State Checkpointing - Persist and recover process state
- Distributed Registry - Cross-process name resolution
Configuration Presets
// Production: conservative restarts, monitoring enabled
var app = try vigil.appWithPreset(allocator, .production);
// Development: verbose logging, quick restarts
var app = try vigil.appWithPreset(allocator, .development);
// High availability: intensive health checks
var app = try vigil.appWithPreset(allocator, .high_availability);
// Testing: minimal restarts, fast health checks
var app = try vigil.appWithPreset(allocator, .testing);
Examples
See examples/vigilant_server for a complete TCP server with:
- Circuit breaker protection
- Rate limiting
- Telemetry integration
- Graceful shutdown
cd examples/vigilant_server
zig build
./zig-out/bin/vigilant_server
Documentation
See docs/api.md for comprehensive API documentation.
Running Tests
zig build test
Requirements
- Zig 0.16.x
- POSIX-compliant operating system
License
MIT - see the LICENSE file for details.