← ademola.dev / writing 7 min read
share →
GoAsynqMessaging Queue

Effortless Concurrency: Unveiling the Power of Asynq Messaging Queue in Go

Asynq is a reliable distributed task queue in Go designed for asynchronous task processing. Built on Redis, it combines simplicity and scalability, making it a powerful tool for distributed systems and high-concurrent applications. · Wed, Jan 8, 2025
Effortless Concurrency: Unveiling the Power of Asynq Messaging Queue in Go

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.

thoughts on this?

Hit reply — I read every email.

hello@demola.dev →
← Previous Taming the Dependencies: Mastering Dependency Injection in Go with Uber Fx Next → Part One: Designing and Building a Microservice with Golang, Python, and Clean Architecture