⭐ Start here if you're new to LedgerQ!
This example demonstrates the core operations: open, enqueue, dequeue, and stats.
- Opening a queue with default configuration
- Enqueuing messages (writing to queue)
- Dequeuing messages (reading from queue)
- Checking queue statistics
- Proper cleanup with defer
go run main.goLedgerQ Simple Example
======================
✓ Queue opened at: /tmp/ledgerq-simple-example
Enqueuing messages:
1. Enqueued at offset 64: Hello, World!
2. Enqueued at offset 107: This is LedgerQ
3. Enqueued at offset 152: A persistent message queue
4. Enqueued at offset 208: Written in Go
Queue Stats:
Total messages: 4
Pending messages: 4
Segments: 1
Dequeuing messages:
1. [ID:1] Hello, World!
2. [ID:2] This is LedgerQ
3. [ID:3] A persistent message queue
4. [ID:4] Written in Go
Final Stats:
Total messages: 4
Pending messages: 0
✓ Example completed successfully!
q, err := ledgerq.Open("/path/to/queue", nil)
if err != nil {
log.Fatal(err)
}
defer q.Close() // Always close when done- First argument: directory path (created if doesn't exist)
- Second argument:
niluses default options - Always close the queue with
deferfor proper cleanup
offset, err := q.Enqueue([]byte("Hello, World!"))- Takes
[]bytepayload (convert strings with[]byte()) - Returns offset (unique ID for this message)
- Thread-safe - multiple goroutines can enqueue simultaneously
msg, err := q.Dequeue()
fmt.Printf("[ID:%d] %s\n", msg.ID, msg.Payload)- Returns next unread message (FIFO order)
msg.ID: Unique message identifiermsg.Payload: Your data as[]byte- Read position persists across restarts
stats := q.Stats()
fmt.Printf("Total: %d, Pending: %d\n",
stats.TotalMessages, stats.PendingMessages)TotalMessages: All messages ever enqueuedPendingMessages: Unread messages waitingSegmentCount: Number of storage files
┌─────────────┐
│ Enqueue() │ → Write to disk → Append-only log
└─────────────┘ ↓
[msg1][msg2][msg3][msg4]
↑
┌─────────────┐ │
│ Dequeue() │ ← Read from disk ←┘
└─────────────┘
- Messages written sequentially to disk (append-only)
- Each message gets unique monotonic ID
- Read position tracks what's been consumed
- Crash-safe: power loss won't lose data
Try these examples next:
- producer-consumer - Multiple goroutines
- ttl - Message expiration
- headers - Message metadata
msg, err := q.Dequeue()
if err != nil {
if err == ledgerq.ErrNoMessages {
// Queue is empty - wait or retry
time.Sleep(100 * time.Millisecond)
} else {
log.Fatal(err)
}
}// Enqueue multiple messages at once (faster)
payloads := [][]byte{
[]byte("msg1"),
[]byte("msg2"),
[]byte("msg3"),
}
offsets, err := q.EnqueueBatch(payloads)
// Dequeue up to 10 messages
messages, err := q.DequeueBatch(10)// Auto-cleanup on exit
queueDir := "/tmp/myqueue"
defer os.RemoveAll(queueDir)
q, _ := ledgerq.Open(queueDir, nil)
defer q.Close()Queue won't open?
- Check directory permissions (needs write access)
- Verify path is valid
- Ensure disk space available
No messages when dequeuing?
- Queue might be empty (
err == ledgerq.ErrNoMessages) - Check
stats.PendingMessagescount
Want to reset?
- Close queue and delete directory:
rm -rf /path/to/queue - Reopening will create fresh queue
This example uses defaults. For custom config:
opts := ledgerq.DefaultOptions("/path/to/queue")
opts.AutoSync = true // Sync after each write (safer, slower)
opts.MaxSegmentSize = 100 * 1024 * 1024 // 100MB segments
q, err := ledgerq.Open("/path/to/queue", opts)See docs/USAGE.md for all options.
Difficulty: 🟢 Beginner | Time: 2 minutes | Lines of Code: ~40