Main Menu
Sub Menu

Cron Jobs & Background Processing in WPDM

WordPress Download Manager 7.0.1 introduces a powerful cron job system for handling background tasks like sending emails, cleaning up expired files, and processing bulk operations. This guide covers everything from basic usage to the developer API.

Overview

The cron job system consists of two main components:

  • CronJobs - Scheduler that registers WordPress cron events and handles external triggers
  • CronJob - Job manager that dispatches, executes, and tracks individual jobs

Admin Interface

Access the cron jobs settings via Downloads → Settings → Cron Jobs. The interface shows:

  • Stats Dashboard - Total, pending, running, completed, and failed job counts
  • External Cron URL - URL for triggering job processing from external cron services
  • Scheduled Events - WordPress cron events and their next run times
  • Recent Jobs - List of recent jobs with status and actions

Job Actions

  • Run - Execute a pending job immediately
  • Cancel - Cancel a pending job
  • Retry - Retry a failed job
  • Delete - Remove a job from the queue

Built-in Job Types

1. CleanupJob

Cleans up expired sessions, cache files, and optionally download statistics.

CronJob::dispatch(\WPDM\__\Jobs\CleanupJob::class) 
    ->withData([ 'cleanup_stats' => false, 'note' => 'Scheduled cleanup' ]) 
    ->onQueue('maintenance') 
    ->create();

2. DeleteExpiredJob

Moves expired packages to trash based on their expiration date.

CronJob::dispatch(\WPDM\__\Jobs\DeleteExpiredJob::class) 
    ->withData([ 'permanent_delete' => false, 'notify_admin' => true ]) 
    ->onQueue('maintenance') 
    ->create();

3. SendEmailJob

Sends emails asynchronously using wp_mail or WPDM Email templates.

CronJob::dispatch(\WPDM\__\Jobs\SendEmailJob::class) 
    ->withData([ 'to' => 'user@example.com', 'subject' => 'Your Download is Ready', 'message' => '<h2>Hello!</h2><p>Your file is ready.</p>', 'template' => 'download-ready' ]) 
    ->onQueue('emails') 
    ->create();

Developer API

The CronJob class provides a fluent builder API for dispatching jobs.

Dispatching Jobs

use WPDM\__\CronJob;

// Basic dispatch
$jobId = CronJob::dispatch(MyCustomJob::class)
    ->withData(['param1' => 'value1'])
    ->create();

// Full options
$jobId = CronJob::dispatch(MyCustomJob::class)
    ->withData($payload)          // Job data/parameters
    ->onQueue('my-queue')         // Queue name for grouping
    ->priority(5)                 // 1-10, higher = sooner
    ->delay(3600)                 // Delay in seconds
    ->attempts(3)                 // Max retry attempts
    ->unique('job-key-123')       // Prevent duplicates
    ->create();

Creating Custom Jobs

Create a job class that extends the base Job class:

namespace MyPlugin\Jobs;

use WPDM\__\Jobs\Job;

class ProcessFileJob extends Job
{
    /**
     * Execute the job
     *
     * @param object|array $data Job payload
     * @return bool Success status
     */
    public function handle($data): bool
    {
        $fileId = $this->get('file_id');
        $action = $this->get('action', 'default');

        $this->log("Processing file #{$fileId}");

        // Your processing logic here
        $result = $this->processFile($fileId, $action);

        if (!$result) {
            $this->log('Processing failed', 'error');
            return false;
        }

        $this->log('File processed successfully');
        return true;
    }

    /**
     * Handle job failure
     */
    public function failed(\Throwable $e, $data): void
    {
        parent::failed($e, $data);
        // Send admin notification, log to external service, etc.
    }

    public static function getName(): string
    {
        return 'Process File';
    }

    public static function getDescription(): string
    {
        return 'Processes uploaded files asynchronously';
    }
}

Static Methods

// Get job counts by status
$counts = CronJob::getCounts();
// Returns: ['total' => 100, 'pending' => 5, ...]

// Get all jobs with filtering
$jobs = CronJob::getAll([
    'limit' => 50,
    'status' => 'pending',
    'queue' => 'emails',
    'orderby' => 'created_at',
    'order' => 'DESC',
]);

// Job management
CronJob::retry($jobId);      // Retry failed job
CronJob::cancel($jobId);     // Cancel pending job
CronJob::delete($jobId);     // Delete job
CronJob::cleanup(30);        // Delete completed jobs older than 30 days
CronJob::releaseStale(30);   // Release locks on stale jobs

Use Cases

1. Async Email Notifications

// Instead of blocking the request
add_action('wpdm_after_download', function($package_id, $user_id) {
    CronJob::dispatch(SendEmailJob::class)
        ->withData([
            'to' => get_userdata($user_id)->user_email,
            'subject' => 'Thank you for your download',
            'message' => 'Your download of ' . get_the_title($package_id) . ' was successful.',
        ])
        ->onQueue('emails')
        ->create();
}, 10, 2);

2. Scheduled Cleanup

// Schedule daily cleanup at midnight
add_action('wpdm_scheduled_tasks', function() {
    CronJob::dispatch(CleanupJob::class)
        ->withData(['cleanup_stats' => false])
        ->onQueue('maintenance')
        ->unique('daily_cleanup_' . date('Y-m-d'))
        ->create();
});

3. Bulk File Processing

// Process multiple files without timeout
function schedule_bulk_processing($file_ids) {
    foreach ($file_ids as $index => $file_id) {
        CronJob::dispatch(ProcessFileJob::class)
            ->withData(['file_id' => $file_id])
            ->onQueue('file-processing')
            ->delay($index * 5) // Stagger by 5 seconds
            ->priority(3)
            ->create();
    }
}

External Cron Setup

If DISABLE_WP_CRON is set to true, you need to trigger job processing externally:

Server Crontab

# Run every 5 minutes
*/5 * * * * curl -s "https://yoursite.com/?wpdm_cron=1&cronkey=YOUR_KEY" > /dev/null 2>&1

Using EasyCron or Similar Service

Copy the External Cron URL from Settings → Cron Jobs and add it to your cron service with a 5-minute interval.

Database Schema

Jobs are stored in the wp_ahm_cron_jobs table:

Column Type Description
ID bigint Auto-increment primary key
code varchar(255) Unique job identifier
type varchar(255) Job class name
data longtext Serialized job payload
queue varchar(100) Queue name
priority tinyint 1-10 priority level
status varchar(20) pending/running/completed/failed
attempts int Current attempt count
max_attempts int Maximum retry attempts
execute_at int Unix timestamp for delayed execution
locked_at int Lock timestamp (prevents double processing)
created_at datetime Job creation time
updated_at datetime Last update time

Best Practices

  1. Use queues - Group related jobs (emails, maintenance, processing) for better organization
  2. Set appropriate priorities - Use higher priority for time-sensitive jobs
  3. Use unique codes - Prevent duplicate jobs with unique identifiers
  4. Handle failures gracefully - Implement the failed() method for error handling
  5. Keep jobs small - Break large tasks into smaller, manageable jobs
  6. Log important events - Use $this->log() for debugging and monitoring

Troubleshooting

Jobs Not Running

  • Check if DISABLE_WP_CRON is set - you may need external cron
  • Verify the __wpdm_process_jobs event is scheduled
  • Check PHP error logs for exceptions

Jobs Stuck in Running

  • Use "Run Job Queue Now" button to process stale jobs
  • Jobs locked for more than 30 minutes are automatically released
  • Check if the job handler is throwing uncaught exceptions

Too Many Failed Jobs

  • Review the job data for invalid parameters
  • Check external service connectivity (for email jobs)
  • Increase max_attempts if failures are transient

Last updated on Jan 6, 2026

Need More Clarification?

For any technical issue, if you are already using pro version please post in pro forum and free version users please post in free forum. Otherwise, if you have any pre-sale or order related query please contact live chat support team. For technical support.

Need Customization?

If you need additional customization on WordPress Download Manager or any type of custom support on WordPress you may contact our customization service.