Skip to content

Commit 195726f

Browse files
author
Andrey Petrov
committed
Release 0.2.0
0 parents  commit 195726f

35 files changed

Lines changed: 5913 additions & 0 deletions

.github/workflows/test.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Go Test
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Checkout code
14+
uses: actions/checkout@v4
15+
16+
- name: Set up Go
17+
uses: actions/setup-go@v5
18+
with:
19+
go-version: '1.25'
20+
21+
- name: Install etcd
22+
run: |
23+
ETCD_VER=v3.6.12
24+
DOWNLOAD_URL=https://github.com/etcd-io/etcd/releases/download
25+
curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o /tmp/etcd.tar.gz
26+
mkdir -p /tmp/etcd-download
27+
tar -xvf /tmp/etcd.tar.gz -C /tmp/etcd-download --strip-components=1
28+
sudo cp /tmp/etcd-download/etcd /usr/local/bin/
29+
sudo cp /tmp/etcd-download/etcdctl /usr/local/bin/
30+
etcd --version
31+
32+
- name: Build
33+
run: CGO_ENABLED=0 go build -ldflags="-s -w" -o conch cmd/conch/main.go
34+
35+
- name: Run unit & integration tests
36+
run: go test -v -race ./...
37+
38+
- name: Run cluster chaos tests
39+
run: ./test-cluster-chaos.sh

.gitignore

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Conch local build and test artifacts
2+
/conch
3+
*.log
4+
*.pid
5+
tmp-node*.etcd/
6+
/default.etcd/
7+
8+
# Go binary and build files
9+
*.exe
10+
*.exe~
11+
*.dll
12+
*.so
13+
*.dylib
14+
*.test
15+
*.out
16+
bin/
17+
dist/
18+
19+
# Go workspaces
20+
go.work
21+
go.work.sum
22+
23+
# IDE and OS metadata
24+
.idea/
25+
.vscode/
26+
*.swp
27+
*.swo
28+
.DS_Store

README.md

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# conch
2+
3+
Distributed coordination wrapper for Linux processes, built on etcd v3. Provides leader election, counting semaphores, and distributed cron without requiring application-level etcd integration.
4+
5+
## Install
6+
7+
Pre-built binaries (amd64, arm64) are available on the [releases page](https://github.com/alien43/conch/releases).
8+
9+
```bash
10+
sudo curl -fsSL "https://github.com/alien43/conch/releases/latest/download/conch-$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')" \
11+
-o /usr/local/bin/conch && sudo chmod +x /usr/local/bin/conch
12+
```
13+
14+
NixOS: use `pkgs.conch` from the flake.
15+
16+
## Build
17+
18+
Using [just](https://github.com/casey/just):
19+
```bash
20+
just build
21+
```
22+
23+
Or manually:
24+
```bash
25+
CGO_ENABLED=0 go build -ldflags="-s -w" -o conch cmd/conch/main.go
26+
```
27+
28+
## Global options
29+
30+
```
31+
CONCH_ENDPOINTS etcd endpoints, comma-separated (default: localhost:2379)
32+
CONCH_DIAL_TIMEOUT dial timeout (default: 5s)
33+
CONCH_TTL lease TTL (default: 10s)
34+
```
35+
36+
Can also be passed as flags.
37+
38+
---
39+
40+
## elect
41+
42+
Run a command under a cluster-wide leader lease. Blocks until the office is vacant, then spawns the command. If the lease is lost, the child process is killed.
43+
44+
```bash
45+
conch elect <office> [flags] -- <cmd...>
46+
```
47+
48+
| Flag | Default | Description |
49+
|---|---|---|
50+
| `--restart` | off | re-campaign after child exits |
51+
| `--kill-after` | 5s | grace period before SIGKILL |
52+
| `--wait` | forever | give up after this duration |
53+
| `--nonblock` | off | exit 75 immediately if office is held |
54+
| `--on-acquire` || shell command run on winning the office |
55+
| `--on-lose` || shell command run on losing the office |
56+
| `--hook-timeout` | 30s | timeout for hook commands |
57+
58+
```bash
59+
# Run a daemon, restart on failure
60+
conch elect api-leader --restart -- /usr/local/bin/api-server
61+
62+
# Promote/demote postgres on leadership change
63+
conch elect db-primary --on-acquire "pg_ctl promote" --on-lose "pg_ctl demote" --restart -- postgres
64+
65+
# Check who holds the office
66+
conch elect api-leader --who
67+
conch elect api-leader --watch
68+
69+
# Assert this host holds the office (exit 0 yes, 1 no, 69 etcd unreachable)
70+
conch elect api-leader --assert
71+
```
72+
73+
---
74+
75+
## sema
76+
77+
Limit concurrent execution to N slots across the cluster.
78+
79+
```bash
80+
conch sema <name> --max N [flags] -- <cmd...>
81+
```
82+
83+
| Flag | Default | Description |
84+
|---|---|---|
85+
| `--max` | required | max concurrent holders |
86+
| `--spread` | off | at most 1 slot per hostname |
87+
| `--wait` | forever | give up after this duration |
88+
| `--nonblock` | off | exit 75 immediately if no slot available |
89+
90+
```bash
91+
# At most 3 nodes run this at once
92+
conch sema heavy-jobs --max 3 -- /usr/local/bin/process-video.sh
93+
94+
# One slot per host, 5 total
95+
conch sema ingest --max 5 --spread -- /usr/local/bin/ingest
96+
97+
# Check who holds slots
98+
conch sema heavy-jobs --max 3 --who
99+
```
100+
101+
---
102+
103+
## cron
104+
105+
Register and manage distributed cron jobs. Each tick runs exactly once across the cluster.
106+
107+
```bash
108+
# Register a job
109+
conch cron add <name> --schedule '<expr>' [--run-ttl 10m] -- <cmd...>
110+
111+
# Remove a job
112+
conch cron rm <name>
113+
114+
# List jobs
115+
conch cron ls [--last] [--json]
116+
```
117+
118+
```bash
119+
# Run conchd on each cluster node to execute scheduled jobs
120+
conch conchd
121+
```
122+
123+
---
124+
125+
## Exit codes
126+
127+
| Code | Meaning |
128+
|---|---|
129+
| 0 | success |
130+
| 1–63 | child exit code (passed through) |
131+
| 64 | usage error |
132+
| 69 | etcd unreachable at startup |
133+
| 70 | lease lost during run; child was killed |
134+
| 75 | `--nonblock` or `--wait` expired |
135+
136+
---
137+
138+
## Test
139+
140+
Using [just](https://github.com/casey/just):
141+
```bash
142+
just test
143+
just test-chaos
144+
```
145+
146+
Or manually:
147+
```bash
148+
go test -v -race ./...
149+
./test-cluster-chaos.sh
150+
```
151+
152+
---
153+
154+
## Docs
155+
156+
- [docs/00_design.md](docs/00_design.md) — motivation and primitives
157+
- [docs/02_core.md](docs/02_core.md) — process supervision and lease spec
158+
- [docs/03_elect.md](docs/03_elect.md) — leader election spec
159+
- [docs/04_sema.md](docs/04_sema.md) — semaphore spec
160+
- [docs/05_cron.md](docs/05_cron.md) — distributed scheduler spec

0 commit comments

Comments
 (0)