Pruner Service API Reference
Overview
The Pruner service is a standalone microservice responsible for UTXO data pruning operations. This document provides technical API reference for the Pruner service.
Service Information:
- gRPC Port: 8096 (default)
- Protocol: gRPC with Protocol Buffers
- API Version: v1
- Proto File:
/services/pruner/pruner_api/pruner_api.proto
gRPC API
Health Check API
HealthGRPC
Checks the health status of the Pruner service.
Request:
message EmptyMessage {}
Response:
message HealthResponse {
bool ok = 1; // true if service is healthy
string details = 2; // Additional health information
}
Example:
grpcurl -plaintext localhost:8096 pruner.PrunerAPI/HealthGRPC
Response:
{
"ok": true,
"details": ""
}
Health Checks Performed:
- gRPC server listening
- Block Assembly client health
- Blockchain client health + FSM state
- UTXO store health
Status Codes:
ok: true- Service is healthy and readyok: false- Service has issues (seedetailsfield)
Prometheus Metrics
Service-Level Metrics
Located in /services/pruner/metrics.go:
pruner_duration_seconds
Type: Histogram
Description: Time taken to complete pruning operations
Labels:
operation: Operation typepreserve_parents- Phase 1: Parent preservationdah_pruner- Phase 2: DAH pruning
Example:
pruner_duration_seconds{operation="preserve_parents"} 1.234
pruner_duration_seconds{operation="dah_pruner"} 5.678
pruner_skipped_total
Type: Counter
Description: Count of pruning operations skipped
Labels:
reason: Reason for skippingnot_running- Block Assembly not in RUNNING stateno_new_height- No new block height to processalready_in_progress- Pruning already running
Example:
pruner_skipped_total{reason="not_running"} 42
pruner_skipped_total{reason="already_in_progress"} 10
pruner_processed_total
Type: Counter
Description: Total number of pruning operations completed successfully
Example:
pruner_processed_total 1000
pruner_errors_total
Type: Counter
Description: Total number of pruning errors encountered
Labels:
operation: Operation where error occurredpreserve_parents- Error during parent preservationdah_pruner- Error during DAH pruningstate_check- Error checking Block Assembly state
Example:
pruner_errors_total{operation="preserve_parents"} 0
pruner_errors_total{operation="dah_pruner"} 2
pruner_errors_total{operation="state_check"} 0
Store-Level Metrics
Located in /stores/utxo/aerospike/pruner/:
utxo_cleanup_batch_duration_seconds
Type: Histogram
Description: Time taken to process pruning batches in Aerospike
Note: Aerospike-specific metric
Example:
utxo_cleanup_batch_duration_seconds 0.123
Internal Interfaces
Service Interface
Located in /stores/pruner/interfaces.go:
type Service interface {
// Start begins the pruner service
Start(ctx context.Context)
// UpdateBlockHeight triggers pruning for the given block height
// Optional doneCh allows waiting for job completion
UpdateBlockHeight(height uint32, doneCh ...chan string) error
// SetPersistedHeightGetter sets the function to get persisted height
// from Block Persister for coordination
SetPersistedHeightGetter(getter func() uint32)
}
Provider Interface
type PrunerServiceProvider interface {
// GetPrunerService returns the store-specific pruner implementation
GetPrunerService() (Service, error)
}
Event Subscriptions
The Pruner service subscribes to the following blockchain events:
BlockPersisted Notification
Source: Block Persister service via Blockchain service
Trigger: After Block Persister completes persisting a block
Payload:
type BlockNotification struct {
BlockHash *chainhash.Hash
BlockHeight uint32
// ... other fields
}
Handler: Updates lastPersistedHeight and triggers pruning
Block Notification (Fallback)
Source: Blockchain service
Trigger: When block is set to mined
Condition: Only processed if lastPersistedHeight == 0 (Block Persister not running)
Payload:
type BlockNotification struct {
BlockHash *chainhash.Hash
Block *wire.Block
MinedSet bool // Must be true
// ... other fields
}
Handler: Triggers pruning if mined_set == true
Job Status API
While not exposed via gRPC, the internal job status can be queried programmatically:
type JobStatus int
const (
JobStatusPending JobStatus = iota
JobStatusRunning
JobStatusCompleted
JobStatusFailed
JobStatusCancelled
)
type Job struct {
ID string
Height uint32
Status JobStatus
CreatedAt time.Time
StartedAt *time.Time
CompletedAt *time.Time
Error error
}
Error Codes
Phase 1 Errors (Critical)
| Error | Description | Action |
|---|---|---|
PreserveParentsFailed |
Failed to update parent PreserveUntil | Abort entire pruning |
QueryUnminedFailed |
Failed to query old unmined transactions | Abort entire pruning |
Phase 2 Errors (Non-Critical)
| Error | Description | Action |
|---|---|---|
DAHQueryFailed |
Failed to query records for deletion | Retry job |
DeleteRecordFailed |
Failed to delete UTXO record | Log error, continue |
ExternalStorageDeleteFailed |
Failed to delete .tx file | Log error, continue |
State Check Errors
| Error | Description | Action |
|---|---|---|
BlockAssemblyNotRunning |
Block Assembly in non-RUNNING state | Skip pruning, retry later |
ClientHealthCheckFailed |
Service client unhealthy | Skip pruning, retry later |
Configuration via Environment
While settings are primarily in settings.conf, environment variables can override:
# Override gRPC port
export PRUNER_GRPCPORT=8097
# Disable pruner
export STARTPRUNER=false
# Set job timeout
export PRUNER_JOBTIMEOUT=15m
Logging
Log Prefixes
[Pruner]- Service-level logs[PreserveParents]- Phase 1 logs[AerospikeCleanupService]- Aerospike store logs[SQLCleanupService]- SQL store logs
Log Levels
- DEBUG: Queue operations, deduplication, job lifecycle
- INFO: Phase start/completion, height updates, successful operations
- WARN: Timeouts (non-errors), skipped operations
- ERROR: Critical failures, Phase 1 errors (abort pruning)
Example Logs
INFO [Pruner] Service initialized successfully
INFO [Pruner] Subscribed to BlockPersisted notifications
INFO [Pruner] Subscribed to Block notifications (fallback)
DEBUG [Pruner] Received BlockPersisted notification for height 12345
INFO [PreserveParents] Starting parent preservation for height 12345
INFO [PreserveParents] Preserved 42 parent transactions
INFO [AerospikeCleanupService] Starting DAH pruning for height 12345
INFO [AerospikeCleanupService] Deleted 1000 UTXO records
INFO [Pruner] Pruning completed successfully for height 12345
WARN [Pruner] Pruning skipped: Block Assembly not running
ERROR [PreserveParents] Failed to preserve parent transaction: CRITICAL - aborting pruning
Performance Considerations
Worker Pool Sizing
Aerospike:
- Default: 4 workers
- Increase for high-throughput nodes
- Limited by
prunerMaxConcurrentOperations
SQL:
- Default: 2 workers
- Increase cautiously (connection pool limits)
Job Timeout
- Default: 10 minutes
- On timeout: Job continues in background
-
Adjust based on:
- Database size
- Network latency
- Worker pool size
Channel Buffering
- Buffer size: 1 (non-blocking)
- Prevents queue buildup during catchup
- LIFO pattern ensures latest height processed
Secondary Index (Aerospike)
- Required: Index on
DeleteAtHeightfield - Index Name:
pruner_dah_index(default) - Impact: Query performance critical for DAH pruning
- Creation: Automatic on service start via index waiter
Troubleshooting
Service Not Starting
-
Check port availability:
lsof -i :8096 -
Verify UTXO store connection:
# Check UTXO store health grpcurl -plaintext localhost:8090 asset.AssetAPI/HealthGRPC -
Check logs for initialization errors:
grep "\[Pruner\].*error" teranode.log
No Pruning Activity
-
Verify service enabled:
startPruner = true -
Check Block Assembly state:
# Should be in RUNNING state curl http://localhost:8087/api/blockchain/status -
Verify event subscriptions:
grep "Subscribed to.*notifications" teranode.log -
Check metrics:
curl http://localhost:8096/metrics | grep pruner_skipped_total
High Error Rate
-
Check
pruner_errors_totalby operation:pruner_errors_total{operation="preserve_parents"} pruner_errors_total{operation="dah_pruner"} -
Review error logs:
grep "\[Pruner\].*ERROR" teranode.log -
Verify database connectivity:
- Aerospike: Check cluster health
- SQL: Check connection pool
Slow Pruning
-
Check
pruner_duration_secondshistogram:curl http://localhost:8096/metrics | grep pruner_duration_seconds -
Increase worker pool:
utxostore_prunerMaxConcurrentOperations = 8 # Aerospike -
Verify secondary index exists (Aerospike):
asadm -e "show indexes" # Should show: pruner_dah_index