mirror of
https://relay.ngit.dev/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit-grasp.git
synced 2026-10-05 15:08:24 +00:00
12 KiB
12 KiB
ngit-grasp vs ngit-relay Comparison
High-Level Comparison
| Aspect | ngit-relay (Reference) | ngit-grasp (This Project) |
|---|---|---|
| Language | Go | Rust |
| Architecture | Multi-process (nginx, git-http-backend, hooks, relay) | Single integrated process |
| Authorization | Git pre-receive hook | Inline HTTP handler |
| Packaging | Docker + supervisord | Single binary or Docker |
| Configuration | Multiple config files | Environment variables |
| Deployment | Docker Compose | Binary or Docker |
| Testing | Go tests + shell scripts | Rust unit + integration tests |
Component Breakdown
ngit-relay (Go)
┌─────────────────────────────────────────────────┐
│ Docker Container │
├─────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌─────────────────────┐ │
│ │ nginx │────────▶│ git-http-backend │ │
│ │ :80 │ │ (C binary) │ │
│ └──────────┘ └──────────┬──────────┘ │
│ │ │ │
│ │ ▼ │
│ │ ┌─────────────────┐ │
│ │ │ Git Repo │ │
│ │ │ + Hooks │ │
│ │ └────────┬────────┘ │
│ │ │ │
│ │ ▼ │
│ │ ┌─────────────────┐ │
│ │ │ pre-receive │ │
│ │ │ (Go binary) │ │
│ │ └────────┬────────┘ │
│ │ │ │
│ │ │ WebSocket │
│ │ ▼ │
│ │ ┌─────────────────┐ │
│ └─────────────────▶│ Khatru Relay │ │
│ │ (Go) │ │
│ └─────────────────┘ │
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ supervisord │ │
│ │ - nginx │ │
│ │ - khatru │ │
│ │ - proactive-sync │ │
│ └──────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────┘
ngit-grasp (Rust)
┌─────────────────────────────────────────────────┐
│ ngit-grasp (Single Binary) │
├─────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ actix-web HTTP Server │ │
│ │ :8080 │ │
│ └───────┬──────────────────────┬────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────────┐ │
│ │ Git Handlers │ │ Nostr Relay │ │
│ │ │ │ (relay-builder) │ │
│ │ - upload-pk │ │ │ │
│ │ - receive-pk │◀─────│ - Policies │ │
│ │ + inline │ query│ - Event store │ │
│ │ validation │ │ - WebSocket │ │
│ └──────┬───────┘ └──────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ Git Repos │ │
│ │ (spawned │ │
│ │ git cmds) │ │
│ └──────────────┘ │
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ Shared State (Arc<AppState>) │ │
│ │ - RepositoryManager │ │
│ │ - NostrClient │ │
│ │ - StateCache │ │
│ └──────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────┘
Detailed Feature Comparison
Git Protocol Handling
| Feature | ngit-relay | ngit-grasp |
|---|---|---|
| Implementation | git-http-backend (C) | git-http-backend (Rust crate) |
| Process model | nginx → C binary | actix-web → Rust handler |
| Upload pack | Passthrough | Passthrough with validation |
| Receive pack | Hook-based auth | Inline validation |
| Error handling | Hook stderr | HTTP response |
| CORS | nginx config | actix-cors middleware |
Nostr Relay
| Feature | ngit-relay | ngit-grasp |
|---|---|---|
| Implementation | Khatru (Go) | nostr-relay-builder (Rust) |
| Event store | Badger (Go) | LMDB or NDB (Rust) |
| Policies | Go functions | Rust traits |
| WebSocket | Khatru built-in | nostr-relay-builder |
| NIP-11 | Manual JSON | Built-in support |
Authorization Logic
| Feature | ngit-relay | ngit-grasp |
|---|---|---|
| Location | pre-receive hook | HTTP handler |
| Language | Go | Rust |
| State query | WebSocket to localhost:3334 | In-process function call |
| Error reporting | stderr → git client | HTTP response body |
| Ref validation | Line-by-line stdin | Parsed from request body |
| Maintainer resolution | Recursive Go function | Recursive Rust function |
| State caching | Per-request | Shared cache with TTL |
Repository Management
| Feature | ngit-relay | ngit-grasp |
|---|---|---|
| Creation | Event hook + shell commands | Event hook + tokio::process |
| Configuration | git config via shell | git config via tokio::process |
| Hook installation | Symlinks | Not needed (inline auth) |
| Permissions | chown nginx:nginx | tokio::fs permissions |
| Path structure | <npub>/<id>.git |
<npub>/<id>.git (same) |
Deployment
| Feature | ngit-relay | ngit-grasp |
|---|---|---|
| Dependencies | nginx, git, Go runtime | git, Rust binary (no runtime) |
| Process management | supervisord | Single process (tokio) |
| Configuration | Multiple files + .env | .env only |
| Docker image size | ~500MB (Alpine + tools) | ~50MB (scratch + binary + git) |
| Startup time | ~2-5 seconds | ~0.5 seconds |
| Memory usage | ~100-200MB (multiple processes) | ~50-100MB (single process) |
Development Experience
| Feature | ngit-relay | ngit-grasp |
|---|---|---|
| Build time | Fast (Go) | Medium (Rust first build, then fast) |
| Type safety | Go (good) | Rust (excellent) |
| Testing | Go test + shell | Rust test (unit + integration) |
| Debugging | Multiple processes | Single process |
| Hot reload | Manual | cargo-watch |
| IDE support | Good (Go) | Excellent (rust-analyzer) |
Performance Comparison (Estimated)
| Metric | ngit-relay | ngit-grasp | Notes |
|---|---|---|---|
| Startup | ~2-5s | ~0.5s | Fewer processes |
| Memory | ~150MB | ~75MB | Single process, no GC |
| CPU (idle) | ~1-2% | ~0.5% | Fewer processes |
| Push latency | +50-100ms | +10-20ms | No hook spawn overhead |
| Clone latency | ~same | ~same | Both passthrough to Git |
| Concurrent pushes | Good | Excellent | Tokio async vs goroutines |
| Event ingestion | Good | Excellent | Rust async + zero-copy |
Note: These are estimates. Actual performance depends on workload and hardware.
Code Complexity
Lines of Code (Estimated)
| Component | ngit-relay | ngit-grasp |
|---|---|---|
| Main server | ~150 | ~200 |
| Git handlers | ~0 (C binary) | ~500 |
| Auth logic | ~200 | ~300 |
| Nostr relay | ~500 | ~100 (using library) |
| Shared utils | ~300 | ~200 |
| Config/setup | ~200 | ~100 |
| Total | ~1,350 | ~1,400 |
Similar complexity, but ngit-grasp has:
- More Git protocol code (we implement it)
- Less Nostr relay code (using library)
- Less deployment code (no hooks/supervisord)
Migration Path
For users of ngit-relay, migration to ngit-grasp would involve:
- Export data from Badger to LMDB/NDB
- Copy Git repositories (same structure)
- Update environment variables (mostly compatible)
- Change deployment from Docker Compose to binary/Docker
- Update URLs if domain changes
The Nostr events and Git data are compatible - only the server changes.
When to Choose Each
Choose ngit-relay (Reference) if:
- ✅ You need a proven, production-tested implementation
- ✅ You're already familiar with Go
- ✅ You want to stay close to the reference
- ✅ You need to deploy immediately
- ✅ You prefer Docker Compose workflows
Choose ngit-grasp (This Project) if:
- ✅ You want better performance and lower resource usage
- ✅ You prefer Rust's type safety and ecosystem
- ✅ You want simpler deployment (single binary)
- ✅ You want to contribute to a modern codebase
- ✅ You're building on top of the GRASP protocol
- ✅ You want inline authorization over hooks
- ✅ You need better integration testing
Future Roadmap Comparison
ngit-relay (Reference)
- ✅ GRASP-01 complete
- 🔄 GRASP-02 in progress
- ⏭️ GRASP-05 planned
- ⏭️ NIP-42 auth-to-read
- ⏭️ NIP-70 protected events
- ⏭️ Spam prevention
ngit-grasp (This Project)
- 🔄 GRASP-01 in development
- ⏭️ GRASP-02 planned (easier with Rust async)
- ⏭️ GRASP-05 planned
- ⏭️ Advanced caching strategies
- ⏭️ Metrics and observability
- ⏭️ Plugin system for custom policies
Conclusion
Both implementations are valid approaches to GRASP:
- ngit-relay is the mature, proven reference implementation
- ngit-grasp is a modern, performant alternative with better DX
The choice depends on your priorities: stability vs. performance, familiarity vs. innovation, proven vs. cutting-edge.
For new deployments where performance and simplicity matter, ngit-grasp is the recommended choice. For production systems requiring maximum stability, ngit-relay is the safer bet until ngit-grasp reaches maturity.