Embedding
Wakeplane is designed to be embedded as a library in Go applications. This lets you run the full scheduling control plane inside your process without deploying a separate daemon.
Operator warning: embedding does not change the network boundary. The HTTP API still has no auth or RBAC. Bind it to localhost, a trusted subnet, VPN, Tailscale, or a reverse-proxied private network.
Construction
Section titled “Construction”cfg := config.FromEnv("embed-example")service, err := app.NewWithOptions(ctx, cfg, app.WithWorkflowHandler("sync.customers", func(ctx context.Context, input map[string]any) (map[string]any, error) { return map[string]any{ "status": "completed", "source": input["source"], }, nil }),)NewWithOptions opens the SQLite database, runs migrations, and wires the planner, dispatcher, and executor registry. It does not start background loops.
Lifecycle
Section titled “Lifecycle”Starting
Section titled “Starting”go func() { if err := service.Run(ctx); err != nil && err != context.Canceled { log.Printf("service run: %v", err) stop() }}()Stopping
Section titled “Stopping”ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)defer cancel()err := service.CloseContext(ctx)If CloseContext exceeds its deadline, it returns context.DeadlineExceeded, leaves the store open, and relies on lease-expiry recovery at the next startup.
HTTP Server Coordination
Section titled “HTTP Server Coordination”Wakeplane does not manage its own HTTP listener. You wire it with api.NewMux(service) and coordinate shutdown with your root context.
See examples/embedded/main.go for the complete working example.
Workflow Handler Contract
Section titled “Workflow Handler Contract”type WorkflowHandler func(ctx context.Context, input map[string]any) (map[string]any, error)The handler receives a context with timeout and cancellation plus the schedule’s target.input map.
Recovery Guarantees
Section titled “Recovery Guarantees”| Crash point | DB state | Recovery action |
|---|---|---|
| After claim, before mark-running | claimed, lease exists | Lease expires -> reset to pending |
| After mark-running, before finish | running, lease exists | Lease expires -> mark failed, retry scheduled |
| After finish, before retry insert | failed, no retry | Retry can be lost |
| Retry scheduled, before dispatch | retry_scheduled | Picked up by next dispatcher tick |
The retry-insert gap is a known current limitation.