Distributed Locks¶
This guide explains how to use grite's distributed lock system to coordinate work across agents and team members.
Overview¶
Grite provides lease-based distributed locks stored as git refs. Locks help coordinate:
- Which agent is working on an issue
- Exclusive access to a file or directory
- Preventing duplicate work
Lock Concepts¶
Lease-Based¶
Locks have a time-to-live (TTL):
- Locks expire automatically after TTL
- Crashed processes don't hold locks forever
- Active processes must renew locks
Git-Backed¶
Locks are stored in refs/grite/locks/<hash>:
- Synced via
git fetch/push - Visible to all agents
- Survives restarts
Lock Namespaces¶
Resources are prefixed with a namespace:
| Namespace | Example | Use Case |
|---|---|---|
issue: |
issue:8057324b |
Claim an issue |
path: |
path:src/auth.rs |
File editing |
repo: |
repo:deploy |
Repository-wide operations |
Acquiring Locks¶
Basic Acquisition¶
Output:
TTL Formats¶
15m- 15 minutes1h- 1 hour30s- 30 seconds
JSON Output¶
{
"schema_version": 1,
"ok": true,
"data": {
"lock": {
"resource": "path:src/api.rs",
"owner": "64d15a2c383e2161772f9cea23e87222",
"nonce": "abc123...",
"expires_unix_ms": 1700003600000
}
}
}
Handling Conflicts¶
If the resource is already locked:
Error: Lock conflict
Resource: issue:8057324b
Owner: e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0
Expires: 2024-01-15 11:00:00 UTC
Renewing Locks¶
Extend a lock before it expires:
Warning
You can only renew locks you own. Renewing a lock held by another actor fails.
Releasing Locks¶
Explicitly release when done:
This is important for good coordination. Don't rely solely on TTL expiration.
Checking Lock Status¶
All Locks¶
Output:
JSON Output¶
{
"schema_version": 1,
"ok": true,
"data": {
"locks": [
{
"resource": "issue:8057324b",
"owner": "64d15a2c383e2161772f9cea23e87222",
"expires_unix_ms": 1700001500000
}
],
"conflicts": []
}
}
Lock Garbage Collection¶
Remove expired locks:
This cleans up refs/grite/locks/ refs that have expired.
Lock Policy¶
Configure lock behavior in .git/grite/config.toml:
| Policy | Behavior |
|---|---|
off |
No lock warnings or enforcement |
warn |
Warn when working on locked resources |
require |
Require lock before modifying resources |
Practical Examples¶
Claiming an Issue¶
# Check for existing lock
if grite lock acquire --resource "issue:$ID" --ttl 30m --json | jq -e '.ok'; then
echo "Claimed issue $ID"
# Do work...
grite issue comment $ID --body "Working on this"
# Release when done
grite issue close $ID
grite lock release --resource "issue:$ID"
else
echo "Issue already claimed"
fi
File Editing Coordination¶
# Lock file before editing
grite lock acquire --resource "path:config/settings.json" --ttl 15m
# Edit file...
# Release after commit
git add config/settings.json
git commit -m "Update settings"
grite lock release --resource "path:config/settings.json"
Long-Running Task¶
# Acquire with longer TTL
grite lock acquire --resource "repo:migration" --ttl 2h
# Periodically renew during long task
while migration_in_progress; do
sleep 300 # 5 minutes
grite lock renew --resource "repo:migration" --ttl 2h
done
grite lock release --resource "repo:migration"
Multi-Agent Coordination¶
Coordinator Pattern¶
A coordinator agent assigns work:
# Coordinator creates task and assigns
grite issue create --title "Process batch" --label "todo" --json
grite lock acquire --resource "issue:$ID" --ttl 30m
# Worker agent checks for available work
for id in $(grite issue list --label todo --json | jq -r '.data.issues[].issue_id'); do
if grite lock acquire --resource "issue:$id" --ttl 30m 2>/dev/null; then
# Got the lock, do the work
process_issue "$id"
grite lock release --resource "issue:$id"
break
fi
done
Work Stealing¶
Agents can steal expired locks:
# Lock expired? Acquire it
if ! grite lock status --json | jq -e ".data.locks[] | select(.resource == \"$RESOURCE\")"; then
grite lock acquire --resource "$RESOURCE" --ttl 30m
fi
Best Practices¶
Always Release Locks¶
# Use trap to ensure release on exit
trap 'grite lock release --resource "issue:$ID"' EXIT
grite lock acquire --resource "issue:$ID" --ttl 30m
# Do work...
Use Appropriate TTLs¶
| Task Type | Suggested TTL |
|---|---|
| Quick edit | 5-15 minutes |
| Feature work | 30-60 minutes |
| Long migration | 2-4 hours |
Renew Before Expiry¶
Set up renewal at 50% of TTL:
# 30 minute lock, renew every 15 minutes
grite lock acquire --resource "..." --ttl 30m
while working; do
sleep 900 # 15 minutes
grite lock renew --resource "..." --ttl 30m
done
Handle Lock Failures Gracefully¶
if ! grite lock acquire --resource "..." --ttl 30m; then
echo "Could not acquire lock, trying later"
exit 0 # Don't fail, just skip
fi
Next Steps¶
- Actor Identity - Understand lock ownership
- Using the Daemon - Lock behavior with daemon
- AI Agents Use Case - Lock patterns for agents