Asynq is a reliable and efficient distributed task queue in Go designed to handle asynchronous task processing elegantly. Asynq, which uses Redis for storage and job management, combines simplicity and scalability, making it an effective tool for distributed systems and high-concurrent applications.
Key Features and Capabilities
Asynq is a flexible library for task queueing and processing.
1. Reliability and Task Guarantees
- At-Least-Once Delivery: Tasks are guaranteed to execute at least once, improving dependability in distributed contexts.
- Retries on Failed Tasks: Built-in retry methods enable tasks to recover from temporary failures.
- Automatic recuperation: If a worker crashes, tasks are automatically requeued and retried.
2. Flexible Task Scheduling
- Task Timeout and Deadline: Tasks can be assigned specified time limitations.
- Periodical Tasks: Built-in support for periodic task scheduling makes cron-like operations easier.
- Task aggregation: Grouping jobs for batch processing improves performance on high-throughput systems.
3. Prioritization and Queue Management
- Weighted and Strict Priority Queues: Fine-grained control over task execution order.
- Pause and Resume Queues: Queues can be paused to temporarily halt task processing.
- De-duplication of Tasks: Unique tasks prevent duplicate executions.
Getting Started with Asynq
Install the package:
go get github.com/hibiken/asynq
Creating and Enqueueing Tasks
package main
import (
"log"
"github.com/hibiken/asynq"
)
func main() {
client := asynq.NewClient(asynq.RedisClientOpt{Addr: "localhost:6379"})
defer client.Close()
taskPayload := map[string]interface{}{
"file_id": "12345",
"file_path": "/uploads/myfile.pdf",
}
task := asynq.NewTask("process_file", taskPayload)
_, err := client.Enqueue(task, asynq.Queue("file_processing"), asynq.MaxRetry(5))
if err != nil {
log.Fatalf("Failed to enqueue task: %v", err)
}
log.Println("File processing task enqueued successfully!")
}
Worker to Process Files
package main
import (
"context"
"fmt"
"log"
"github.com/hibiken/asynq"
)
func main() {
server := asynq.NewServer(
asynq.RedisClientOpt{Addr: "localhost:6379"},
asynq.Config{Concurrency: 5},
)
mux := asynq.NewServeMux()
mux.HandleFunc("process_file", handleFileProcessing)
log.Println("Starting file processing server...")
if err := server.Run(mux); err != nil {
log.Fatalf("Server error: %v", err)
}
}
func handleFileProcessing(ctx context.Context, task *asynq.Task) error {
fileID, err := task.Payload.GetString("file_id")
if err != nil {
return fmt.Errorf("missing file_id: %v", err)
}
filePath, err := task.Payload.GetString("file_path")
if err != nil {
return fmt.Errorf("missing file_path: %v", err)
}
log.Printf("Processing file: ID=%s, Path=%s", fileID, filePath)
return nil
}
Why Choose Asynq?
Asynq is perfect for teams seeking a simple yet scalable solution for asynchronous task processing. With its robust feature set, flexible API, and rich ecosystem, Asynq enables developers to build distributed systems that are resilient, efficient, and easy to maintain.
Explore Asynq on GitHub.