# Queue & Cron Setup

> Simple setup: MailTrixy needs just ONE cron job to handle everything — email sync, campaigns, AI replies, workflows, and queue processing. No separate queue worker needed.

This page explains how to set up the single cron job and optional Supervisor for VPS users.

## Why Background Processing Matters

MailTrixy handles email sync, AI replies, campaigns, workflows, and scheduled tasks in the background. Without the cron job, none of these will work automatically.

> Important: You must set up the cron job below. Without it, emails will not sync, campaigns will not send, and AI replies will not generate.

## How It Works

MailTrixy uses Laravel's scheduler to handle everything with a single command. The scheduler automatically:

- Processes pending queue jobs (email sync, AI replies, campaigns, workflows)
- Syncs email accounts every 2 minutes
- Refreshes OAuth tokens every 30 minutes
- Processes drip sequences every minute
- Sends scheduled emails every minute
- Runs daily cleanup and backups

No separate queue worker is needed. The scheduler includes a built-in queue processor that runs every minute and processes all pending jobs.

Environment | Command | How It Runs
--- | --- | ---
Local Development | `php artisan schedule:work` | Keeps running in terminal, auto-repeats every minute
Server / Hosting | `* * * * * php artisan schedule:run` | Cron triggers it every minute, runs once and exits

## Cron Setup (Shared Hosting)

### cPanel

1. Log in to cPanel
2. Go to Cron Jobs (under Advanced)
3. Set the schedule to Once Per Minute (`* * * * *`)
4. Enter the command:

    cd /home/YOUR_USERNAME/public_html && php artisan schedule:run >> /dev/null 2>&1

Replace `/home/YOUR_USERNAME/public_html` with the actual path to your MailTrixy installation. You can find this path in File Manager by navigating to your project root.

### Hostinger (hPanel)

1. Log in to hPanel
2. Go to Advanced → Cron Jobs
3. Select Custom and enter `* * * * *` for every minute
4. Enter the command:

    cd /home/u123456789/domains/yourdomain.com/public_html && php artisan schedule:run >> /dev/null 2>&1

### Plesk

1. Go to Scheduled Tasks in Plesk
2. Add a new task with cron syntax `* * * * *`
3. Enter the command with the full path to your PHP binary and project

    /usr/bin/php /var/www/vhosts/yourdomain.com/httpdocs/artisan schedule:run >> /dev/null 2>&1

> Verify it works: After setting up the cron job, wait 2–3 minutes, then check Admin → System Settings → Queue Monitor to confirm jobs are being processed.

## Supervisor Setup (VPS)

For VPS/dedicated servers, use Supervisor to run persistent queue workers that process jobs instantly.

### Install Supervisor

    # Ubuntu / Debian
    sudo apt-get install supervisor

    # CentOS / AlmaLinux
    sudo yum install supervisor
    sudo systemctl enable supervisord
    sudo systemctl start supervisord

### Create Supervisor Configuration

Create a new configuration file for MailTrixy:

    sudo nano /etc/supervisor/conf.d/mailtrixy-worker.conf

Add the following configuration:

    [program:mailtrixy-worker]
    process_name=%(program_name)s_%(process_num)02d
    command=php /var/www/mailtrixy/artisan queue:work database --queue=high,default,low --tries=3 --timeout=300 --memory=256 --sleep=3
    autostart=true
    autorestart=true
    stopasgroup=true
    killasgroup=true
    user=www-data
    numprocs=2
    redirect_stderr=true
    stdout_logfile=/var/www/mailtrixy/storage/logs/worker.log
    stopwaitsecs=3600

Configuration options explained:

- `--queue=high,default,low` – Process queues in priority order
- `--tries=3` – Retry failed jobs up to 3 times
- `--timeout=300` – Kill jobs that run longer than 5 minutes
- `--memory=256` – Restart worker if memory exceeds 256 MB
- `--sleep=3` – Wait 3 seconds between checking for new jobs
- `numprocs=2` – Run 2 parallel workers (increase for high volume)
- `stopwaitsecs=3600` – Allow up to 1 hour for long-running jobs to finish during restart

### Start the Workers

    # Read the new configuration
    sudo supervisorctl reread

    # Apply changes
    sudo supervisorctl update

    # Start the workers
    sudo supervisorctl start mailtrixy-worker:*

    # Check status
    sudo supervisorctl status

> Remember: Even with Supervisor running queue workers, you still need the cron job for the Laravel scheduler. The scheduler handles time-based tasks like email sync schedules, campaign scheduling, and subscription renewals.

    # Add to crontab (crontab -e)
    * * * * * cd /var/www/mailtrixy && php artisan schedule:run >> /dev/null 2>&1

## Queue Configuration

MailTrixy uses three priority queues to ensure critical tasks are processed first:

Queue | Priority | Jobs
--- | --- | ---
`high` | Highest | Webhook processing, real-time channel messages, payment webhooks
`default` | Normal | Email sync, AI replies, workflow execution, notifications
`low` | Lowest | Analytics aggregation, cleanup tasks, report generation

The `.env` configuration:

    # Database driver (works everywhere, no Redis needed)
    QUEUE_CONNECTION=database

    # OR Redis driver (faster, requires Redis server)
    QUEUE_CONNECTION=redis

## All Queue Jobs

MailTrixy dispatches the following 13 job types to the background queue:

# | Job | Queue | Description
--- | --- | --- | ---
1 | `SyncInboxEmails` | default | Fetches new emails from connected IMAP/OAuth accounts and stores them in the database. Runs on a configurable schedule (default: every 5 minutes).
2 | `SendCampaignBatch` | default | Sends a batch of campaign emails (typically 50–100 per batch) with throttling to respect SMTP rate limits. Tracks delivery status per recipient.
3 | `ExecuteWorkflow` | default | Processes a workflow step for a contact — evaluates conditions, executes actions (send email, add tag, update field, wait), and advances to the next step.
4 | `GenerateAIReply` | default | Sends the email conversation context to the configured AI provider and generates a draft reply. Includes knowledge base context if RAG is enabled.
5 | `ProcessWebhook` | high | Handles incoming webhooks from payment gateways (Stripe, PayPal, etc.), updating subscription status, recording payments, and triggering related events.
6 | `ProcessChannelMessage` | high | Processes incoming messages from WhatsApp, Telegram, Slack, and SMS. Routes the message to the correct conversation thread and notifies assigned team members.
7 | `SendChannelReply` | high | Sends an outgoing reply via WhatsApp, Telegram, Slack, or SMS through the respective API.
8 | `ImportContacts` | default | Processes CSV/Excel contact imports in chunks. Validates data, deduplicates by email, and creates or updates contact records with tags and custom fields.
9 | `ExportData` | low | Generates CSV/Excel exports for contacts, campaigns, or analytics data. Stores the file and sends a download notification to the user.
10 | `ProcessSubscription` | high | Handles subscription lifecycle events: creation, renewal, upgrade, downgrade, cancellation, and grace period expiry.
11 | `AggregateAnalytics` | low | Aggregates daily email metrics (open rates, click rates, bounce rates) and workspace-level statistics for the analytics dashboard.
12 | `SendNotification` | default | Sends email and in-app notifications for events like new replies, deal stage changes, workflow completions, and subscription alerts.
13 | `CleanupExpiredData` | low | Purges expired sessions, old queue job records, temporary files, and soft-deleted records past their retention period. Runs daily via the scheduler.

## Scheduled Tasks

The Laravel scheduler (triggered by the cron job) runs the following tasks automatically:

Task | Frequency | Description
--- | --- | ---
Email Sync | Every 5 minutes | Dispatches SyncInboxEmails jobs for all connected accounts
Workflow Scheduler | Every minute | Checks for workflow steps with expired wait timers and dispatches them
Campaign Scheduler | Every minute | Launches scheduled campaigns that have reached their send time
Subscription Check | Every hour | Checks for expired subscriptions, grace periods, and trial expirations
Analytics Aggregation | Daily at 2:00 AM | Aggregates previous day's email and campaign metrics
Queue Cleanup | Daily at 3:00 AM | Prunes completed/failed job records older than 7 days
Data Cleanup | Daily at 4:00 AM | Purges expired sessions, temporary files, and soft-deleted records

## Troubleshooting Queue Issues

### Jobs Not Processing

Symptom: Emails not syncing, campaigns stuck in “Sending”, workflows not executing.

- Check cron is running: Visit Admin → System Settings → Queue Monitor. If the “Last Run” timestamp is stale (more than 2 minutes old), the cron job is not configured correctly.
- Check the cron path: Ensure the path in the cron command matches your actual project directory. Use your hosting File Manager to verify the full path.
- Check PHP version in cron: Some hosts have multiple PHP versions. Use the full PHP path: `/usr/bin/php8.2` instead of just `php`.

    # Find the correct PHP path on your server
    which php
    # or
    which php8.2

### Failed Jobs

Symptom: Some jobs appear in the “Failed” tab of the Queue Monitor.

- Check the error message in the failed job details (Admin → Queue Monitor → Failed Jobs)
- Common causes: expired API keys, SMTP authentication failures, rate limiting, insufficient memory
- Retry failed jobs from the admin panel, or via CLI:

    # Retry all failed jobs
    php artisan queue:retry all

    # Retry a specific job
    php artisan queue:retry [job-id]

    # Clear all failed jobs
    php artisan queue:flush

### Slow Processing

Symptom: Jobs are processing but taking too long.

- Shared hosting: Upgrade from middleware mode (Mode 1) to cron mode (Mode 2)
- VPS: Increase the `numprocs` in your Supervisor config to run more parallel workers
- Redis: Switch from `database` to `redis` queue driver for significantly faster job dispatch and retrieval
- Memory: Increase `--memory` flag in the queue worker command if workers are restarting frequently due to memory limits

### Supervisor Worker Keeps Dying

Symptom: Workers restart frequently or stop unexpectedly.

- Check the worker log: `tail -f /var/www/mailtrixy/storage/logs/worker.log`
- Increase `--memory` if you see “memory limit exceeded” messages
- Increase `--timeout` if jobs are being killed before completion
- Ensure `stopwaitsecs` is high enough for long-running jobs to complete during worker restart

### Restarting Workers After Deployment

After updating MailTrixy code, restart the queue workers to pick up changes:

    # Graceful restart (finishes current jobs, then restarts)
    php artisan queue:restart

    # OR via Supervisor
    sudo supervisorctl restart mailtrixy-worker:*

> Note: `php artisan queue:restart` signals workers to exit after completing their current job. Supervisor then automatically restarts them with the new code.