IPC_ARCHITECTURE.md raw

ORLY IPC Architecture

ORLY implements a modular Inter-Process Communication (IPC) architecture where core functionality runs as independent gRPC services. This design provides resource isolation, fault tolerance, and flexible deployment options.

Overview

┌─────────────────────────────────────────────────────────────────────────────────┐
│                                orly-launcher                                     │
│                     (Process Supervisor & Lifecycle Manager)                     │
│                                                                                  │
│  Responsibilities:                                                               │
│  - Start services in dependency order                                            │
│  - Monitor process health and restart on failure                                 │
│  - Graceful shutdown in reverse order                                            │
│  - Pass environment configuration to child processes                             │
└─────────────────────────────────────────────────────────────────────────────────┘
                                        │
        ┌───────────────────────────────┼───────────────────────────────┐
        │                               │                               │
        ▼                               ▼                               ▼
┌───────────────────┐       ┌───────────────────┐       ┌───────────────────────────┐
│    orly-db        │       │    orly-acl       │       │     Sync Services         │
│  (gRPC :50051)    │       │  (gRPC :50052)    │       │  (gRPC :50061-50064)      │
│                   │       │                   │       │                           │
│ Core Database:    │       │ Access Control:   │       │ orly-sync-distributed     │
│ ├─ Event storage  │       │ ├─ Permission     │       │ ├─ Peer-to-peer sync      │
│ ├─ Query engine   │       │ │   checks        │       │ └─ Serial-based polling   │
│ ├─ Index mgmt     │       │ ├─ Follow lists   │       │                           │
│ ├─ Serial counter │       │ ├─ Admin/owner    │       │ orly-sync-cluster         │
│ └─ Export/import  │       │ │   management    │       │ ├─ HA replication         │
│                   │       │ └─ Policy hooks   │       │ └─ Membership events      │
│ Backends:         │       │                   │       │                           │
│ ├─ Badger (SSD)   │       │ Modes:            │       │ orly-sync-relaygroup      │
│ ├─ Neo4j (graph)  │       │ ├─ none (open)    │       │ ├─ Kind 39105 config      │
│ └─ WasmDB (wasm)  │       │ ├─ follows        │       │ └─ Dynamic peer lists     │
│                   │       │ ├─ managed        │       │                           │
│                   │       │ └─ curating       │       │ orly-sync-negentropy      │
│                   │       │                   │       │ ├─ NIP-77 WebSocket       │
│                   │       │                   │       │ └─ Set reconciliation     │
└───────────────────┘       └───────────────────┘       └───────────────────────────┘
        │                           │                               │
        │                           │                               │
        └───────────────────────────┼───────────────────────────────┘
                                    │
                                    ▼
                        ┌───────────────────────┐
                        │        orly           │
                        │    (Main Relay)       │
                        │                       │
                        │ Client-Facing:        │
                        │ ├─ WebSocket server   │
                        │ ├─ NIP handling       │
                        │ ├─ REQ/EVENT/AUTH     │
                        │ ├─ NEG-* (NIP-77)     │
                        │ └─ HTTP API           │
                        │                       │
                        │ Internal:             │
                        │ ├─ gRPC DB client     │
                        │ ├─ gRPC ACL client    │
                        │ └─ gRPC sync clients  │
                        └───────────────────────┘
                                    │
                                    ▼
                            ┌───────────────┐
                            │    Caddy      │
                            │ (TLS Proxy)   │
                            └───────────────┘
                                    │
                                    ▼
                              Internet

Service Ports

ServiceDefault PortDescription
orly-db50051Database server (Badger/Neo4j/WasmDB)
orly-acl50052Access control server
orly-sync-distributed50061Peer-to-peer sync
orly-sync-cluster50062Cluster replication
orly-sync-relaygroup50063Relay group config
orly-sync-negentropy50064NIP-77 negentropy
orly3334Main relay (WebSocket/HTTP)

Startup Sequence

The launcher starts services in strict dependency order:

1. orly-db          ──────► Wait for gRPC ready
                              │
2. orly-acl         ──────► Wait for gRPC ready (depends on DB)
                              │
3. Sync Services    ──────► Start in parallel, wait for all ready
   ├─ orly-sync-distributed     (depends on DB)
   ├─ orly-sync-cluster         (depends on DB)
   ├─ orly-sync-relaygroup      (depends on DB)
   └─ orly-sync-negentropy      (depends on DB)
                              │
4. orly             ──────► Connects to all services via gRPC

Shutdown happens in reverse order: relay → sync services → ACL → database.

Benefits of IPC Architecture

1. Resource Isolation

2. Fault Tolerance

3. Independent Scaling

4. Flexible Deployment

Core Services

1. Database Service (orly-db)

The database service handles all event storage, indexing, and querying.

Variants

gRPC API

service DatabaseService {
  // Readiness
  rpc Ready(Empty) returns (ReadyResponse);

  // Event operations
  rpc SaveEvent(SaveEventRequest) returns (SaveEventResponse);
  rpc QueryEvents(QueryEventsRequest) returns (QueryEventsResponse);
  rpc CountEvents(CountEventsRequest) returns (CountEventsResponse);
  rpc DeleteEvent(DeleteEventRequest) returns (DeleteEventResponse);
  rpc QueryAllVersions(QueryEventsRequest) returns (QueryEventsResponse);

  // Special queries
  rpc GetSerials(GetSerialsRequest) returns (GetSerialsResponse);
  rpc GetLastSerial(Empty) returns (GetLastSerialResponse);
  rpc CheckForDeleted(CheckDeletedRequest) returns (CheckDeletedResponse);

  // Admin operations
  rpc Export(ExportRequest, stream ExportResponse);
  rpc Import(stream ImportRequest) returns (ImportResponse);
}

Environment Variables

VariableDefaultDescription
ORLY_DB_LISTEN127.0.0.1:50051gRPC listen address
ORLY_DATA_DIR~/.local/share/ORLYDatabase storage path
ORLY_DB_LOG_LEVELinfoLogging level
ORLY_DB_BLOCK_CACHE_MB1024Badger block cache
ORLY_DB_INDEX_CACHE_MB512Badger index cache
ORLY_DB_ZSTD_LEVEL3Compression level (0-9)

2. ACL Service (orly-acl)

The ACL service handles access control decisions for all relay operations.

Variants

gRPC API

service ACLService {
  // Readiness
  rpc Ready(Empty) returns (ReadyResponse);

  // Access checks
  rpc CheckAccess(CheckAccessRequest) returns (CheckAccessResponse);
  rpc GetAccessLevel(GetAccessLevelRequest) returns (GetAccessLevelResponse);
  rpc CheckPolicy(CheckPolicyRequest) returns (CheckPolicyResponse);

  // Admin operations
  rpc Configure(ConfigureRequest) returns (ConfigureResponse);
  rpc GetType(Empty) returns (TypeResponse);
}

Environment Variables

VariableDefaultDescription
ORLY_ACL_LISTEN127.0.0.1:50052gRPC listen address
ORLY_ACL_MODEfollowsACL mode
ORLY_ACL_DB_TYPEgrpcDatabase backend
ORLY_ACL_GRPC_DB_SERVER127.0.0.1:50051Database server
ORLY_ACL_LOG_LEVELinfoLogging level

3. Main Relay (orly)

The main relay handles all client-facing operations.

Responsibilities

Connection Modes

Local mode (default):

ORLY_DB_TYPE=badger
ORLY_ACL_TYPE=local

gRPC mode (IPC):

ORLY_DB_TYPE=grpc
ORLY_GRPC_SERVER=127.0.0.1:50051
ORLY_ACL_TYPE=grpc
ORLY_GRPC_ACL_SERVER=127.0.0.1:50052
ORLY_NEGENTROPY_ENABLED=true
ORLY_GRPC_SYNC_NEGENTROPY=127.0.0.1:50064

Sync Services

See IPC_SYNC_SERVICES.md for detailed sync service documentation.

Quick Reference

ServicePortPurpose
orly-sync-distributed50061Serial-based peer sync
orly-sync-cluster50062HA cluster replication
orly-sync-relaygroup50063Kind 39105 relay groups
orly-sync-negentropy50064NIP-77 set reconciliation

Deployment Examples

Minimal IPC (Database + Relay)

# Start database
ORLY_DB_LISTEN=127.0.0.1:50051 ./orly-db-badger &

# Start relay with gRPC database
ORLY_DB_TYPE=grpc \
ORLY_GRPC_SERVER=127.0.0.1:50051 \
./orly

Full IPC with ACL

# Use launcher for automatic management
ORLY_LAUNCHER_DB_BACKEND=badger \
ORLY_LAUNCHER_ACL_ENABLED=true \
ORLY_ACL_MODE=follows \
./orly-launcher

Full IPC with Negentropy

# Enable NIP-77 support
ORLY_LAUNCHER_DB_BACKEND=badger \
ORLY_LAUNCHER_ACL_ENABLED=true \
ORLY_LAUNCHER_SYNC_NEGENTROPY_ENABLED=true \
ORLY_NEGENTROPY_ENABLED=true \
./orly-launcher

systemd Service

See the example at /etc/systemd/system/orly.service on relay.orly.dev for a production configuration.

Building Binaries

# Build all IPC binaries
make all-acl   # Builds orly-db-*, orly-acl-*, orly-launcher

# Build sync services
go build -o orly-sync-distributed ./cmd/orly-sync-distributed
go build -o orly-sync-cluster ./cmd/orly-sync-cluster
go build -o orly-sync-relaygroup ./cmd/orly-sync-relaygroup
go build -o orly-sync-negentropy ./cmd/orly-sync-negentropy

# Cross-compile for ARM64
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o orly-sync-negentropy ./cmd/orly-sync-negentropy

Monitoring

Health Checks

Each gRPC service implements a Ready RPC that returns when the service is accepting requests.

Logs

All services log to stdout/stderr. Use journalctl for systemd deployments:

# Follow all ORLY logs
journalctl -u orly -f

# Filter by process
journalctl -u orly | grep "orly-db"
journalctl -u orly | grep "orly-sync-negentropy"

pprof

Enable HTTP pprof for profiling:

ORLY_PPROF_HTTP=true ./orly-launcher
# Access at http://localhost:6060/debug/pprof/

Troubleshooting

Service won't start

  1. Check if port is in use: ss -tlnp | grep 5005
  2. Verify binary exists and is executable
  3. Check logs: journalctl -u orly -n 100

Database connection timeout

  1. Ensure database started first
  2. Check ORLY_LAUNCHER_DB_READY_TIMEOUT (default 30s)
  3. Verify network connectivity

Negentropy not working

  1. Verify ORLY_NEGENTROPY_ENABLED=true in relay config
  2. Check negentropy service is running: ps aux | grep negentropy
  3. Verify gRPC connection: ORLY_GRPC_SYNC_NEGENTROPY=127.0.0.1:50064