Skip to content
edgesync Artifact [59de82bb2a]
Login

Artifact [59de82bb2a]

Artifact 59de82bb2a3352f1911378c9f56f86060975f12dc634e0a396bda3eafb249f83:

Wiki page [Leaf Agent] by dmestas on 2026-10-13 02:27:53.
D 2026-10-13T02:27:53.200
L Leaf\sAgent
N text/x-markdown
U dmestas
W 2071
# Leaf Agent

A Go daemon that sits next to a Fossil repo and keeps it synced over NATS.

## Data Flow

``` pikchr
    right
    R: cylinder "repo.fossil" color white fill 0x3a3a3a width 1.2 height 0.5 rad 3px
    move 0.2
    arrow color white thick <->
    move 0.1
    A: box "Leaf Agent" color white fill 0x2a6b3a width 1.5 height 0.5 rad 5px
    move 0.2
    arrow color white thick "sync request" above
    move 0.1
    N: cylinder "NATS" color white fill 0x2a4a6b width 1.0 height 0.5 rad 5px
    move 0.2
    arrow color white thick
    move 0.1
    B: box "Bridge" color white fill 0x6b5a2a width 1.2 height 0.5 rad 5px
    move 0.2
    arrow color white thick "HTTP" above
    move 0.1
    F: box "Fossil" color white fill 0x6b2a2a width 1.2 height 0.5 rad 5px
```

## How It Works

1. Opens a `.fossil` repo — reads project/server codes from SQLite
2. Connects to NATS
3. Polls every 5s (configurable):
   - Checks `unsent`/`unclustered` tables
   - If new artifacts found, calls `sync.Sync()` via NATS transport
4. `SIGUSR1` triggers immediate sync
5. `SIGINT`/`SIGTERM` graceful shutdown

## Usage

```
leaf-agent --repo /path/to/repo.fossil \
           --nats nats://localhost:4222 \
           --poll 5s \
           --push --pull
```

| Flag | Env Var | Default | Description |
|------|---------|---------|-------------|
| `--repo` | `LEAF_REPO` | (required) | Path to `.fossil` file |
| `--nats` | `LEAF_NATS_URL` | `nats://localhost:4222` | NATS server URL |
| `--poll` | — | `5s` | Poll interval |
| `--user` | `LEAF_USER` | `anonymous` | Sync user |
| `--password` | `LEAF_PASSWORD` | — | Sync password |
| `--push` | — | `true` | Push local artifacts |
| `--pull` | — | `true` | Pull remote artifacts |
| `--prefix` | — | `fossil` | NATS subject prefix |

## Concurrency

The poll goroutine is the sole executor of sync. `SyncNow()` sends on a buffered channel — it never calls sync directly. This avoids concurrent SQLite access.

## See Also

- [Bridge](wiki:Bridge) — the other half
- [Home](wiki:index) — architecture overview

Z 566e7eccd75703e3315e7e8bdb9d4a98