Skip to content
edgesync Changes To Leaf Agent
Login

Changes To Leaf Agent

Initial version of "Leaf Agent"


































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 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