dkron Agent Skills & AI Rules

GitHub

Dkron - Distributed, fault tolerant job scheduling system

4,740 stars Go Go 98 files ยท ~61,604 tokens #cron#distributed-systems#fault-tolerance#scheduled-jobs
RAW Rules
11 Discovered Rules โ€ข ~4,025 Estimated Tokens
Quick:
Loading skill content...

AI Agent Protocol & Instructions

AGENTS.md root-instruction ~1,573 tokens
Raw
# AGENTS instructions

This file provides guidance to agents when working with code in this repository.

## Project Overview

Dkron is a distributed, fault-tolerant job scheduling system (distributed cron) written in Go. It uses:
- **Raft protocol** (HashiCorp Raft) for consensus and leader election
- **Serf** (HashiCorp) for cluster membership and failure detection via gossip protocol
- **BuntDB** for embedded storage
- **gRPC** for inter-node communication
- **Gin** for HTTP/REST API
- **React Admin** for the web UI

The system is inspired by Google's "Reliable Cron across the Planet" whitepaper and Airbnb's Chronos.

## Development Commands

### Building
```bash
# Build the main binary (requires UI to be built first)
make main

# Build main binary manually
go build main.go

# Install built-in plugins (executors and processors)
GOBIN=`pwd` go install ./builtin/...

# Clean build artifacts
make clean
```

### Testing
```bash
# Run full test suite in Docker
make test

# Run tests locally
make localtest
# Or directly:
go test -v ./...

# Run specific test
go test -v ./dkron -run TestJobName
```

### Frontend Development
```bash
# Install dependencies (uses Bun)
cd ui && bun install

# Start development server
cd ui && npm start

# Build UI for production (outputs to dkron/ui-dist)
cd ui && yarn build --out-dir ../dkron/ui-dist
# Or use make:
make ui
```

### Docker Development
```bash
# Start development cluster with live reload
docker compose -f docker-compose.dev.yml up

# Start production-like cluster
docker compose up -d

# Scale the cluster
docker compose up -d --scale dkron-server=4
docker compose up -d --scale dkron-agent=10

# Access UI at http://localhost:8080/ui
```

### Protocol Buffers
```bash
# Generate Go code from proto files
make proto
# Or manually:
protoc -I proto/ --go_out=types --go_opt=paths=source_relative \
  --go-grpc_out=types --go-grpc_opt=paths=source_relative proto/dkron.proto
```

### Code Generation
```bash
# Generate API client from OpenAPI spec
make client
```

## Architecture

### Core Components

**Agent** (`dkron/agent.go`)
- Main orchestrator that combines all subsystems
- Manages both server (Raft leader/follower) and agent (execution) roles
- Contains: Serf cluster, Raft consensus, gRPC server/client, HTTP API, scheduler, storage, plugins

**Storage** (`dkron/store.go`)
- Interface: `Storage` defines operations (Get/SetJob, Get/SetExecution, etc.)
- Implementation: `Store` uses BuntDB (embedded key-value store)
- Stores jobs and executions with max 100 executions per job
- Key prefixes: `jobs/` and `executions/`

**Leader Election** (`dkron/leader.go`)
- Raft-based leader election
- Only the leader schedules jobs (prevents duplicate executions)
- Leader runs the `Scheduler` which manages cron timers

**Job Scheduling** (`dkron/scheduler.go`, `dkron/job.go`)
- Cron-based scheduling using `robfig/cron/v3`
- Extended cron syntax support via `extcron/` package
- Jobs can have parent-child dependencies
- Concurrency policies: `allow` or `forbid`
- Hash symbol (`~`) in schedules is replaced with hash of job name for distribution

**Execution** (`dkron/run.go`, `dkron/execution.go`)
- Leader determines target nodes based on job tags
- Nodes execute jobs via executor plugins
- Results streamed back to leader via gRPC
- Execution status: success, failed, running, partially_failed

**Cluster Communication**
- `dkron/serf.go`: Serf for membership, failure detection, and event propagation
- `dkron/grpc.go`: gRPC server for job execution coordination
- `dkron/grpc_client.go`: gRPC client for communicating with other nodes
- `dkron/api.go`: REST API using Gin framework

**Plugin System** (`plugin/`)
- Two plugin types: **Executors** (run jobs) and **Processors** (process outputs)
- Uses HashiCorp go-plugin for RPC-based plugins
- Built-in executors: shell, http, grpc, kafka, nats, rabbitmq, gcppubsub
- Built-in processors: log, files, syslog, fluent
- Plugins live in `builtin/bins/`

### Key Data Structures

**Job** (`dkron/job.go`)
- Name (unique ID), Schedule (cron expression), Timezone
- Executor and ExecutorConfig
- Parent job for dependencies
- Tags for targeting specific nodes
- Concurrency policy, retries, timeout

**Execution** (`dkron/execution.go`)
- Links to Job, records start/finish times
- NodeName (where it ran), Output, Success/Error status

### Configuration

Config loaded via Viper from:
- Config files: `/etc/dkron/dkron.yaml`, `$HOME/.dkron/dkron.yaml`, `./config/dkron.yaml`
- Environment variables: `DKRON_*` (e.g., `DKRON_NODE_NAME`)
- CLI flags (via Cobra in `cmd/`)

Key settings: `node-name`, `bind-addr`, `server`, `bootstrap-expect`, `data-dir`, `tags`

### Module Structure

- `cmd/`: CLI commands (agent, keygen, version, etc.)
- `dkron/`: Core library (agent, storage, API, scheduler, clustering)
- `builtin/bins/`: Built-in executor and processor plugin binaries
- `plugin/`: Plugin interfaces and serving logic
- `proto/`, `types/`: Protobuf definitions and generated code
- `extcron/`: Extended cron parser supporting simple syntax
- `ntime/`: Nullable time type
- `logging/`: Custom logging setup
- `client/`: Auto-generated API client
- `ui/`: React Admin frontend (TypeScript/Vite)

## Code Patterns

### Working with Storage
Always use the `Storage` interface. Wrap operations in context and check for `buntdb.ErrNotFound` when getting jobs/executions.

### Leader Operations
Check `a.IsLeader()` before performing leader-only operations like job scheduling or applying Raft logs.

### gRPC Communication
Use `GRPCClient.ExecutionDone()` to report execution results to the leader. The leader uses `AgentRun()` to trigger job execution on target nodes.

### Plugin Development
Implement `plugin.Executor` or `plugin.Processor` interfaces. Use `plugin.Serve()` to serve the plugin. See existing plugins in `builtin/bins/` for examples.

## Important Notes

- The system uses both Raft (for consistency) and Serf (for membership)
- Jobs are only scheduled by the leader to avoid duplicates
- Executions are tracked with a sliding window (max 100 per job)
- The UI is embedded in the binary via Go embed (`dkron/ui-dist`)
- Plugin communication uses HashiCorp's go-plugin over gRPC
- Module path is `github.com/distribworks/dkron/v4` (note the v4 major version)