Skip to content
Contents

Extending Background

Background is designed with extensibility in mind, allowing you to create custom implementations tailored to your specific requirements.

Core Design Principles

Background follows object-oriented design principles. When extending its functionality, it's recommended to maintain these principles in your custom implementations.

Key OOP Concepts

To effectively extend Background, familiarity with these concepts is essential:

  • Inheritance: Creating new classes based on existing ones
  • Polymorphism: Implementing interfaces with various concrete implementations
  • Encapsulation: Controlling access to class components through access modifiers

The JobQueue Class

The JobQueue class serves as the foundation for all queue implementations in Background. When creating custom queues, you'll extend this class and work with its:

  • Protected properties
  • Protected methods
  • Storage implementation patterns

The class interacts with storage implementations that follow the JobStorage interface.

JobStorage Interface

typescript
export interface JobStorage {
  saveJob(job: Job): Promise<void>;
  getJob(id: string): Promise<Job | null>;
  getJobsByStatus(status: JobStatus): Promise<Job[]>;
  updateJob(job: Job): Promise<void>;
  acquireNextJob(): Promise<Job | null>;
  completeJob(jobId: string, result: any): Promise<void>;
  failJob(jobId: string, error: string): Promise<void>;
}

Extending the Storage Interface

You can extend the base JobStorage interface to add specialized functionality:

typescript
export interface RedisStorage extends JobStorage {
  // Atomic job acquisition with optional time-to-live
  acquireNextJob(ttl?: number): Promise<Job | null>;
  
  // Retrieve jobs by priority level
  getJobsByPriority(priority: number): Promise<Job[]>;
  
  // Get scheduled jobs within a specified time range
  getScheduledJobs(startTime: Date, endTime?: Date): Promise<Job[]>;
  
  // Remove all jobs from storage
  clear(): Promise<void>;
}

Creating Custom Queues

Implementation Steps

  1. Create a class that extends JobQueue
  2. Initialize storage and configuration in the constructor
  3. Call the parent constructor using super()
  4. Override key methods to customize behavior

Required Overrides

At minimum, you'll typically need to override these methods:

typescript
protected async processNextBatch(): Promise<void>
protected async processJob(job: Job): Promise<void>

Implement additional private methods as needed for your specific implementation.

Job Interface Reference

Here's the complete Job interface for reference:

typescript
// Job status types
export type JobStatus = "pending" | "processing" | "completed" | "failed";

// Job interface
export interface Job<T = any> {
  id: string;
  name: string;
  data: T;
  status: JobStatus;
  createdAt: Date;
  scheduledAt?: Date;
  startedAt?: Date;
  completedAt?: Date;
  error?: string;
  priority?: number;
  result?: any;
  retryCount?: number;
  repeat?: {
    every?: number;
    unit?: "seconds" | "minutes" | "hours" | "days" | "weeks" | "months";
    startDate?: Date;
    endDate?: Date;
    limit?: number;
  };
}

// Job handler type
export type JobHandler<T = any, R = any> = (data: T) => Promise<R>;

Best Practices

  • Review the source code before implementing custom extensions
  • Maintain consistent error handling patterns
  • Follow the existing architectural patterns where possible
  • Document custom implementations thoroughly

Source Code Reference

For a deeper understanding of Background internals, refer to the GitHub Repository.