Batch API Guide - Visual Learning Edition

šŸ“š A comprehensive visual guide to using the Batch Compilation API

This guide provides detailed explanations and diagrams for working with batch compilations in the adblock-compiler API. Perfect for visual learners!

Table of Contents


Overview

The Batch API allows you to compile multiple filter lists in a single request. Behind the scenes, it uses Cloudflare Queues for reliable, scalable processing.

Key Benefits

graph TB
    subgraph "Why Use Batch API?"
        A[Batch API] --> B[šŸš€ Parallel Processing]
        A --> C[⚔ Efficient Resource Use]
        A --> D[šŸ”„ Automatic Retries]
        A --> E[šŸ“Š Progress Tracking]
        A --> F[šŸ’° Cost Effective]
    end
    
    style A fill:#667eea,stroke:#333,stroke-width:3px,color:#fff
    style B fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style C fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style D fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style E fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style F fill:#10b981,stroke:#333,stroke-width:2px,color:#fff

Architecture Diagrams

High-Level System Architecture

graph LR
    subgraph "Client Layer"
        Client[šŸ‘¤ Your Application]
    end
    
    subgraph "API Layer"
        API[🌐 Worker API<br/>POST /compile/batch]
        AAPI[🌐 Async API<br/>POST /compile/batch/async]
    end
    
    subgraph "Processing Layer"
        Compiler[āš™ļø Batch Compiler<br/>Parallel Processing]
        Queue[šŸ“¬ Cloudflare Queue<br/>Message Broker]
        Consumer[šŸ”„ Queue Consumer<br/>Background Worker]
    end
    
    subgraph "Storage Layer"
        Cache[šŸ’¾ KV Cache<br/>Results Storage]
        R2[šŸ“¦ R2 Storage<br/>Large Results]
    end
    
    Client -->|Sync Request| API
    Client -->|Async Request| AAPI
    
    API --> Compiler
    AAPI --> Queue
    Queue --> Consumer
    Consumer --> Compiler
    
    Compiler --> Cache
    Compiler --> R2
    Cache -.->|Cached Result| Client
    R2 -.->|Large Result| Client
    
    style Client fill:#667eea,stroke:#333,stroke-width:2px,color:#fff
    style API fill:#f59e0b,stroke:#333,stroke-width:2px,color:#fff
    style AAPI fill:#f59e0b,stroke:#333,stroke-width:2px,color:#fff
    style Compiler fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style Queue fill:#8b5cf6,stroke:#333,stroke-width:2px,color:#fff
    style Consumer fill:#8b5cf6,stroke:#333,stroke-width:2px,color:#fff
    style Cache fill:#3b82f6,stroke:#333,stroke-width:2px,color:#fff
    style R2 fill:#3b82f6,stroke:#333,stroke-width:2px,color:#fff

Queue Processing Pipeline

graph TB
    subgraph "Input"
        REQ[šŸ“ Batch Request<br/>Max 10 items]
    end
    
    subgraph "Validation"
        VAL{āœ… Validate<br/>Request}
        ERR1[āŒ Error:<br/>Too many items]
        ERR2[āŒ Error:<br/>Invalid config]
    end
    
    subgraph "Queue Selection"
        PRIORITY{šŸŽÆ Priority?}
        HPQ[⚔ High Priority Queue<br/>Faster processing]
        SPQ[šŸ“‹ Standard Queue<br/>Normal processing]
    end
    
    subgraph "Processing"
        BATCH[šŸ“¦ Batch Messages<br/>Group by priority]
        PROCESS[āš™ļø Compile Each Item<br/>Parallel execution]
    end
    
    subgraph "Storage"
        CACHE[šŸ’¾ Cache Results<br/>1 hour TTL]
        METRICS[šŸ“Š Update Metrics<br/>Track performance]
    end
    
    subgraph "Output"
        RESPONSE[āœ… Success Response<br/>With request ID]
        NOTIFY[šŸ”” Optional Webhook<br/>Completion notification]
    end
    
    REQ --> VAL
    VAL -->|Valid| PRIORITY
    VAL -->|Invalid| ERR1
    VAL -->|Bad Config| ERR2
    
    PRIORITY -->|High| HPQ
    PRIORITY -->|Standard| SPQ
    
    HPQ --> BATCH
    SPQ --> BATCH
    BATCH --> PROCESS
    PROCESS --> CACHE
    PROCESS --> METRICS
    CACHE --> RESPONSE
    METRICS --> NOTIFY
    
    style REQ fill:#667eea,stroke:#333,stroke-width:2px,color:#fff
    style VAL fill:#f59e0b,stroke:#333,stroke-width:2px,color:#000
    style PRIORITY fill:#f59e0b,stroke:#333,stroke-width:2px,color:#000
    style HPQ fill:#ef4444,stroke:#333,stroke-width:2px,color:#fff
    style SPQ fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style BATCH fill:#8b5cf6,stroke:#333,stroke-width:2px,color:#fff
    style PROCESS fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style CACHE fill:#3b82f6,stroke:#333,stroke-width:2px,color:#fff
    style RESPONSE fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style ERR1 fill:#ef4444,stroke:#333,stroke-width:2px,color:#fff
    style ERR2 fill:#ef4444,stroke:#333,stroke-width:2px,color:#fff

Batch Types

Synchronous vs Asynchronous Comparison

graph TB
    subgraph "Synchronous Batch"
        SYNC_REQ[šŸ“¤ POST /compile/batch]
        SYNC_WAIT[ā³ Wait for completion<br/>Max 30 seconds]
        SYNC_RESP[šŸ“„ Immediate response<br/>With all results]
        
        SYNC_REQ --> SYNC_WAIT --> SYNC_RESP
    end
    
    subgraph "Asynchronous Batch"
        ASYNC_REQ[šŸ“¤ POST /compile/batch/async]
        ASYNC_ACK[⚔ Immediate acknowledgment<br/>202 Accepted]
        ASYNC_QUEUE[šŸ“¬ Background processing<br/>No time limit]
        ASYNC_CHECK[šŸ” GET /queue/results/:id<br/>Check status]
        ASYNC_RESP[šŸ“„ Get results when ready]
        
        ASYNC_REQ --> ASYNC_ACK
        ASYNC_ACK --> ASYNC_QUEUE
        ASYNC_QUEUE --> ASYNC_CHECK
        ASYNC_CHECK --> ASYNC_RESP
    end
    
    style SYNC_REQ fill:#f59e0b,stroke:#333,stroke-width:2px,color:#fff
    style SYNC_WAIT fill:#ef4444,stroke:#333,stroke-width:2px,color:#fff
    style SYNC_RESP fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style ASYNC_REQ fill:#f59e0b,stroke:#333,stroke-width:2px,color:#fff
    style ASYNC_ACK fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style ASYNC_QUEUE fill:#8b5cf6,stroke:#333,stroke-width:2px,color:#fff
    style ASYNC_CHECK fill:#3b82f6,stroke:#333,stroke-width:2px,color:#fff
    style ASYNC_RESP fill:#10b981,stroke:#333,stroke-width:2px,color:#fff

When to Use Each Type

mindmap
    root((Batch API<br/>Decision))
        Synchronous
            Small batches ≤ 3 items
            Fast filter lists
            Need immediate results
            Low complexity transformations
            User waiting for response
        Asynchronous
            Large batches 4-10 items
            Slow/large filter lists
            Can poll for results
            Complex transformations
            Background processing
            Webhook notifications

API Endpoints

Endpoint Overview

graph LR
    subgraph "Batch Endpoints"
        direction TB
        E1[šŸ“ POST /compile/batch<br/>Synchronous]
        E2[šŸ“ POST /compile/batch/async<br/>Asynchronous]
        E3[šŸ“ GET /queue/results/:id<br/>Get async results]
        E4[šŸ“ GET /queue/stats<br/>Queue statistics]
    end
    
    subgraph "Use Cases"
        direction TB
        U1[šŸŽÆ Quick batch compilation]
        U2[ā±ļø Long-running compilations]
        U3[šŸ“Š Check completion status]
        U4[šŸ“ˆ Monitor queue health]
    end
    
    E1 -.-> U1
    E2 -.-> U2
    E3 -.-> U3
    E4 -.-> U4
    
    style E1 fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style E2 fill:#8b5cf6,stroke:#333,stroke-width:2px,color:#fff
    style E3 fill:#3b82f6,stroke:#333,stroke-width:2px,color:#fff
    style E4 fill:#f59e0b,stroke:#333,stroke-width:2px,color:#fff
    style U1 fill:#dbeafe,stroke:#333,stroke-width:1px
    style U2 fill:#ede9fe,stroke:#333,stroke-width:1px
    style U3 fill:#dbeafe,stroke:#333,stroke-width:1px
    style U4 fill:#fef3c7,stroke:#333,stroke-width:1px

Request Structure Diagram

graph TB
    subgraph "Batch Request Structure"
        ROOT[šŸ”· Root Object]
        REQUESTS[šŸ“‹ requests array<br/>Min: 1, Max: 10]
        
        ROOT --> REQUESTS
        
        REQUESTS --> ITEM1[Item 1]
        REQUESTS --> ITEM2[Item 2]
        REQUESTS --> ITEMN[Item N...]
        
        ITEM1 --> ID1[id: string<br/>unique identifier]
        ITEM1 --> CFG1[configuration: object<br/>compilation config]
        ITEM1 --> PRE1[preFetchedContent?: object<br/>optional pre-fetched data]
        ITEM1 --> BMK1[benchmark?: boolean<br/>enable metrics]
        
        CFG1 --> NAME[name: string<br/>list name]
        CFG1 --> SOURCES[sources: array<br/>filter list sources]
        CFG1 --> TRANS[transformations?: array<br/>processing steps]
        
        SOURCES --> SRC1[Source 1<br/>URL or key]
        SOURCES --> SRC2[Source 2<br/>URL or key]
    end
    
    style ROOT fill:#667eea,stroke:#333,stroke-width:3px,color:#fff
    style REQUESTS fill:#8b5cf6,stroke:#333,stroke-width:2px,color:#fff
    style ITEM1 fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style ITEM2 fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style ITEMN fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style CFG1 fill:#3b82f6,stroke:#333,stroke-width:2px,color:#fff

Request/Response Flow

Synchronous Batch Flow (Detailed)

sequenceDiagram
    participant Client as šŸ‘¤ Client
    participant API as 🌐 API Gateway
    participant Validator as āœ… Validator
    participant Compiler as āš™ļø Batch Compiler
    participant Cache as šŸ’¾ KV Cache
    participant Sources as šŸŒ External Sources
    
    Note over Client,Sources: Synchronous Batch Compilation Flow
    
    Client->>API: POST /compile/batch
    Note right of Client: Request with 1-10 items
    
    API->>Validator: Validate request
    
    alt Invalid request
        Validator-->>API: āŒ Validation errors
        API-->>Client: 400 Bad Request
    else Valid request
        Validator-->>API: āœ… Valid
        
        API->>Compiler: Start batch compilation
        
        Note over Compiler: Process items in parallel
        
        loop For each item
            Compiler->>Cache: Check cache
            
            alt Cache hit
                Cache-->>Compiler: ⚔ Cached result
            else Cache miss
                Cache-->>Compiler: 🚫 Not cached
                
                Compiler->>Sources: Fetch filter lists
                Sources-->>Compiler: šŸ“„ Raw content
                
                Compiler->>Compiler: Apply transformations
                Compiler->>Cache: šŸ’¾ Store result
            end
        end
        
        Compiler-->>API: āœ… All results
        API-->>Client: 200 OK with results array
    end
    
    Note over Client,Sources: Total time: typically 2-30 seconds

Asynchronous Batch Flow (Detailed)

sequenceDiagram
    participant Client as šŸ‘¤ Client
    participant API as 🌐 API Gateway
    participant Queue as šŸ“¬ Cloudflare Queue
    participant Worker as šŸ”„ Queue Consumer
    participant Compiler as āš™ļø Batch Compiler
    participant Cache as šŸ’¾ KV Cache
    
    Note over Client,Cache: Asynchronous Batch Compilation Flow
    
    Client->>API: POST /compile/batch/async
    Note right of Client: Request with 1-10 items
    
    API->>API: Generate request ID
    Note right of API: requestId: req-{timestamp}-{random}
    
    API->>Queue: Enqueue batch message
    Note right of Queue: Priority: standard or high
    
    Queue-->>API: āœ… Queued successfully
    API-->>Client: 202 Accepted
    Note left of API: Response includes:<br/>- requestId<br/>- priority<br/>- status
    
    Note over Client: Client can continue other work
    
    rect rgb(240, 240, 255)
        Note over Queue,Cache: Background Processing (async)
        
        Queue->>Queue: Batch messages
        Note right of Queue: Wait for batch timeout<br/>or max batch size
        
        Queue->>Worker: Deliver message batch
        
        Worker->>Compiler: Process batch
        
        loop For each item in batch
            Compiler->>Compiler: Compile filter list
            Compiler->>Cache: Store results
        end
        
        Worker->>Cache: Mark as completed
        Worker->>Queue: Acknowledge message
    end
    
    Note over Client: Later: client checks for results
    
    Client->>API: GET /queue/results/{requestId}
    API->>Cache: Lookup results
    
    alt Results ready
        Cache-->>API: āœ… Compilation results
        API-->>Client: 200 OK with results
    else Still processing
        Cache-->>API: ā³ Not ready yet
        API-->>Client: 200 OK (status: processing)
    else Not found
        Cache-->>API: 🚫 Not found
        API-->>Client: 404 Not Found
    end

Priority Queue Routing

graph TB
    subgraph "Request Input"
        REQ[šŸ“Ø Batch Request]
        PRIO{Priority<br/>Specified?}
    end
    
    subgraph "High Priority Path"
        HPQ[⚔ High Priority Queue]
        HPC[Fast Consumer<br/>Batch: 5<br/>Timeout: 2s]
        HPP[Quick Processing]
    end
    
    subgraph "Standard Priority Path"
        SPQ[šŸ“‹ Standard Queue]
        SPC[Normal Consumer<br/>Batch: 10<br/>Timeout: 5s]
        SPP[Normal Processing]
    end
    
    subgraph "Processing Results"
        CACHE[šŸ’¾ Cache Results]
        METRICS[šŸ“Š Record Metrics]
    end
    
    REQ --> PRIO
    PRIO -->|priority: high| HPQ
    PRIO -->|priority: standard<br/>or not specified| SPQ
    
    HPQ --> HPC
    HPC --> HPP
    
    SPQ --> SPC
    SPC --> SPP
    
    HPP --> CACHE
    SPP --> CACHE
    CACHE --> METRICS
    
    style REQ fill:#667eea,stroke:#333,stroke-width:2px,color:#fff
    style PRIO fill:#f59e0b,stroke:#333,stroke-width:2px,color:#000
    style HPQ fill:#ef4444,stroke:#333,stroke-width:2px,color:#fff
    style HPC fill:#ef4444,stroke:#333,stroke-width:2px,color:#fff
    style HPP fill:#ef4444,stroke:#333,stroke-width:2px,color:#fff
    style SPQ fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style SPC fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style SPP fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style CACHE fill:#3b82f6,stroke:#333,stroke-width:2px,color:#fff
    style METRICS fill:#8b5cf6,stroke:#333,stroke-width:2px,color:#fff

Code Examples

Example 1: Simple Synchronous Batch

Scenario: Compile 3 filter lists and get immediate results

graph LR
    subgraph "Your Code"
        CODE[šŸ“ Make API Call]
    end
    
    subgraph "API Processing"
        PROC[āš™ļø Compile 3 Lists<br/>Parallel execution]
    end
    
    subgraph "Results"
        RES[āœ… 3 Compiled Lists<br/>Immediately returned]
    end
    
    CODE -->|POST request| PROC
    PROC -->|2-10 seconds| RES
    
    style CODE fill:#667eea,stroke:#333,stroke-width:2px,color:#fff
    style PROC fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style RES fill:#3b82f6,stroke:#333,stroke-width:2px,color:#fff
// JavaScript/TypeScript example
const batchRequest = {
    requests: [
        {
            id: 'adguard-dns',
            configuration: {
                name: 'AdGuard DNS Filter',
                sources: [
                    {
                        source: 'https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt',
                        transformations: ['RemoveComments', 'Validate']
                    }
                ],
                transformations: ['Deduplicate', 'RemoveEmptyLines']
            },
            benchmark: true
        },
        {
            id: 'easylist',
            configuration: {
                name: 'EasyList',
                sources: [
                    {
                        source: 'https://easylist.to/easylist/easylist.txt',
                        transformations: ['RemoveComments', 'Compress']
                    }
                ],
                transformations: ['Deduplicate']
            }
        },
        {
            id: 'custom-rules',
            configuration: {
                name: 'Custom Rules',
                sources: [
                    { source: 'my-custom-rules' }
                ]
            },
            preFetchedContent: {
                'my-custom-rules': '||ads.example.com^\n||tracking.example.com^'
            }
        }
    ]
};

// Send synchronous batch request
const response = await fetch('https://adblock-compiler.jayson-knight.workers.dev/compile/batch', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify(batchRequest)
});

const results = await response.json();

// Process results
console.log('Batch compilation complete!');
results.results.forEach(result => {
    console.log(`${result.id}: ${result.ruleCount} rules`);
    console.log(`Compilation time: ${result.metrics?.totalDurationMs}ms`);
});

Expected Response:

{
    "success": true,
    "results": [
        {
            "id": "adguard-dns",
            "success": true,
            "rules": ["||ads.com^", "||tracker.net^", "..."],
            "ruleCount": 45234,
            "metrics": {
                "totalDurationMs": 2341,
                "sourceCount": 1,
                "transformationMetrics": [...]
            },
            "compiledAt": "2026-01-14T07:30:15.123Z"
        },
        {
            "id": "easylist",
            "success": true,
            "rules": ["||ad.example.com^", "..."],
            "ruleCount": 67891,
            "metrics": {
                "totalDurationMs": 3567
            },
            "compiledAt": "2026-01-14T07:30:16.234Z"
        },
        {
            "id": "custom-rules",
            "success": true,
            "rules": ["||ads.example.com^", "||tracking.example.com^"],
            "ruleCount": 2,
            "metrics": {
                "totalDurationMs": 45
            },
            "compiledAt": "2026-01-14T07:30:15.456Z"
        }
    ]
}

Example 2: Asynchronous Batch with Polling

Scenario: Queue 10 large filter lists for background processing

sequenceDiagram
    participant Code as šŸ“ Your Code
    participant API as 🌐 API
    participant Queue as šŸ“¬ Queue
    
    Note over Code,Queue: Step 1: Queue the batch
    Code->>API: POST /compile/batch/async
    API->>Queue: Enqueue
    API-->>Code: 202 Accepted<br/>{requestId: "req-123"}
    
    Note over Code: Your code continues...<br/>Do other work
    
    Note over Queue: Background: Processing...
    
    Note over Code,Queue: Step 2: Poll for results (after 30s)
    Code->>API: GET /queue/results/req-123
    API-->>Code: 200 OK<br/>{status: "processing"}
    
    Note over Code: Wait 30 more seconds
    
    Note over Queue: Compilation complete!
    
    Note over Code,Queue: Step 3: Get final results
    Code->>API: GET /queue/results/req-123
    API-->>Code: 200 OK<br/>{status: "completed", results: [...]}
// JavaScript/TypeScript example with async/await
async function compileBatchAsync() {
    // Step 1: Queue the batch
    const batchRequest = {
        requests: [
            // ... 10 compilation requests
            { id: 'list-1', configuration: { /* ... */ } },
            { id: 'list-2', configuration: { /* ... */ } },
            { id: 'list-3', configuration: { /* ... */ } },
            // ... up to list-10
        ]
    };
    
    const queueResponse = await fetch(
        'https://adblock-compiler.jayson-knight.workers.dev/compile/batch/async',
        {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(batchRequest)
        }
    );
    
    const queueData = await queueResponse.json();
    console.log('Batch queued:', queueData.requestId);
    
    // Step 2: Poll for results
    const requestId = queueData.requestId;
    let results = null;
    let attempts = 0;
    const maxAttempts = 10;
    
    while (!results && attempts < maxAttempts) {
        // Wait 30 seconds between polls
        await new Promise(resolve => setTimeout(resolve, 30000));
        
        const statusResponse = await fetch(
            `https://adblock-compiler.jayson-knight.workers.dev/queue/results/${requestId}`
        );
        
        const statusData = await statusResponse.json();
        
        if (statusData.status === 'completed') {
            results = statusData.results;
            console.log('Batch complete! Got results for', results.length, 'items');
        } else if (statusData.status === 'failed') {
            throw new Error('Batch compilation failed: ' + statusData.error);
        } else {
            console.log('Still processing... attempt', ++attempts);
        }
    }
    
    if (!results) {
        throw new Error('Timeout waiting for results');
    }
    
    return results;
}

// Usage
try {
    const results = await compileBatchAsync();
    results.forEach(result => {
        console.log(`${result.id}: ${result.ruleCount} rules`);
    });
} catch (error) {
    console.error('Batch compilation error:', error);
}

Example 3: Python with Requests Library

import requests
import time
from typing import List, Dict

BASE_URL = 'https://adblock-compiler.jayson-knight.workers.dev'

def compile_batch_async(requests_data: List[Dict]) -> List[Dict]:
    """
    Compile multiple filter lists asynchronously
    
    Args:
        requests_data: List of compilation requests (max 10)
    
    Returns:
        List of compilation results
    """
    
    # Step 1: Queue the batch
    response = requests.post(
        f'{BASE_URL}/compile/batch/async',
        json={'requests': requests_data}
    )
    response.raise_for_status()
    
    queue_data = response.json()
    request_id = queue_data['requestId']
    print(f'šŸ“¬ Batch queued: {request_id}')
    print(f'⚔ Priority: {queue_data["priority"]}')
    
    # Step 2: Poll for results
    max_attempts = 20
    poll_interval = 30  # seconds
    
    for attempt in range(max_attempts):
        print(f'ā³ Checking status (attempt {attempt + 1}/{max_attempts})...')
        
        response = requests.get(f'{BASE_URL}/queue/results/{request_id}')
        response.raise_for_status()
        
        data = response.json()
        
        if data.get('status') == 'completed':
            print('āœ… Batch compilation complete!')
            return data['results']
        elif data.get('status') == 'failed':
            raise Exception(f'Batch failed: {data.get("error")}')
        else:
            if attempt < max_attempts - 1:
                print(f'āŒ› Still processing, waiting {poll_interval} seconds...')
                time.sleep(poll_interval)
    
    raise TimeoutError('Timeout waiting for batch completion')


# Example usage
if __name__ == '__main__':
    batch_requests = [
        {
            'id': 'adguard',
            'configuration': {
                'name': 'AdGuard DNS',
                'sources': [
                    {
                        'source': 'https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt'
                    }
                ],
                'transformations': ['Deduplicate', 'RemoveEmptyLines']
            },
            'benchmark': True
        },
        {
            'id': 'easylist',
            'configuration': {
                'name': 'EasyList',
                'sources': [
                    {
                        'source': 'https://easylist.to/easylist/easylist.txt'
                    }
                ],
                'transformations': ['Deduplicate']
            }
        }
    ]
    
    try:
        results = compile_batch_async(batch_requests)
        
        print('\nšŸ“Š Results Summary:')
        for result in results:
            print(f"  {result['id']}: {result['ruleCount']} rules")
            print(f"    Time: {result['metrics']['totalDurationMs']}ms")
    
    except Exception as e:
        print(f'āŒ Error: {e}')

Example 4: cURL Commands

# Example: Synchronous batch compilation
curl -X POST https://adblock-compiler.jayson-knight.workers.dev/compile/batch \
  -H "Content-Type: application/json" \
  -d '{
    "requests": [
      {
        "id": "test-1",
        "configuration": {
          "name": "Test List 1",
          "sources": [
            {
              "source": "my-rules-1"
            }
          ]
        },
        "preFetchedContent": {
          "my-rules-1": "||ads.com^\n||tracker.net^"
        }
      },
      {
        "id": "test-2",
        "configuration": {
          "name": "Test List 2",
          "sources": [
            {
              "source": "my-rules-2"
            }
          ]
        },
        "preFetchedContent": {
          "my-rules-2": "||spam.org^\n||malware.biz^"
        }
      }
    ]
  }'
# Example: Asynchronous batch compilation

# Step 1: Queue the batch
curl -X POST https://adblock-compiler.jayson-knight.workers.dev/compile/batch/async \
  -H "Content-Type: application/json" \
  -d '{
    "requests": [
      {
        "id": "large-list-1",
        "configuration": {
          "name": "Large Filter List",
          "sources": [
            {
              "source": "https://example.com/large-list.txt"
            }
          ],
          "transformations": ["Deduplicate", "Compress"]
        }
      }
    ]
  }'

# Response will include a requestId, e.g.:
# {
#   "success": true,
#   "requestId": "req-1704931200000-abc123",
#   "priority": "standard"
# }

# Step 2: Check status (wait 30 seconds, then run this)
curl https://adblock-compiler.jayson-knight.workers.dev/queue/results/req-1704931200000-abc123

# If still processing, you'll get:
# {
#   "success": true,
#   "status": "processing"
# }

# When complete, you'll get full results:
# {
#   "success": true,
#   "status": "completed",
#   "results": [...]
# }

Best Practices

Batch Size Optimization

graph TB
    subgraph "Batch Size Decision Tree"
        START{How many<br/>lists?}
        
        START -->|1-3 items| SMALL[Small Batch]
        START -->|4-7 items| MEDIUM[Medium Batch]
        START -->|8-10 items| LARGE[Large Batch]
        START -->|>10 items| SPLIT[Split into<br/>multiple batches]
        
        SMALL --> SYNC1[āœ… Use Sync API<br/>Fast response]
        MEDIUM --> CHOICE{Need immediate<br/>results?}
        LARGE --> ASYNC1[āœ… Use Async API<br/>Reliable processing]
        SPLIT --> ASYNC2[āœ… Use Async API<br/>Process separately]
        
        CHOICE -->|Yes| SYNC2[Use Sync API<br/>May be slower]
        CHOICE -->|No| ASYNC3[āœ… Use Async API<br/>Recommended]
    end
    
    style START fill:#667eea,stroke:#333,stroke-width:2px,color:#fff
    style SMALL fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style MEDIUM fill:#f59e0b,stroke:#333,stroke-width:2px,color:#fff
    style LARGE fill:#ef4444,stroke:#333,stroke-width:2px,color:#fff
    style SPLIT fill:#ef4444,stroke:#333,stroke-width:2px,color:#fff
    style SYNC1 fill:#3b82f6,stroke:#333,stroke-width:2px,color:#fff
    style SYNC2 fill:#3b82f6,stroke:#333,stroke-width:2px,color:#fff
    style ASYNC1 fill:#8b5cf6,stroke:#333,stroke-width:2px,color:#fff
    style ASYNC2 fill:#8b5cf6,stroke:#333,stroke-width:2px,color:#fff
    style ASYNC3 fill:#8b5cf6,stroke:#333,stroke-width:2px,color:#fff

Error Handling Strategy

graph TB
    subgraph "Error Handling Flow"
        REQ[šŸ“Ø Send Batch Request]
        
        REQ --> CHECK{Response<br/>Status?}
        
        CHECK -->|400| VAL_ERR[āŒ Validation Error]
        CHECK -->|429| RATE_ERR[āŒ Rate Limit]
        CHECK -->|500| SRV_ERR[āŒ Server Error]
        CHECK -->|200/202| SUCCESS[āœ… Success]
        
        VAL_ERR --> FIX1[Fix request format<br/>Check item count]
        RATE_ERR --> WAIT1[Wait 60 seconds<br/>Retry with backoff]
        SRV_ERR --> RETRY1[Retry with<br/>exponential backoff]
        
        SUCCESS --> PROCESS{Processing<br/>Results}
        
        PROCESS --> ITEM_ERR{Any item<br/>failed?}
        ITEM_ERR -->|Yes| LOG[Log failure<br/>Continue with successful]
        ITEM_ERR -->|No| DONE[āœ… All items<br/>successful]
    end
    
    style REQ fill:#667eea,stroke:#333,stroke-width:2px,color:#fff
    style CHECK fill:#f59e0b,stroke:#333,stroke-width:2px,color:#000
    style VAL_ERR fill:#ef4444,stroke:#333,stroke-width:2px,color:#fff
    style RATE_ERR fill:#ef4444,stroke:#333,stroke-width:2px,color:#fff
    style SRV_ERR fill:#ef4444,stroke:#333,stroke-width:2px,color:#fff
    style SUCCESS fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style DONE fill:#10b981,stroke:#333,stroke-width:2px,color:#fff

Caching Strategy

graph LR
    subgraph "How Caching Works in Batches"
        REQ[šŸ“Ø Batch Request<br/>3 items]
        
        REQ --> ITEM1[Item 1]
        REQ --> ITEM2[Item 2]
        REQ --> ITEM3[Item 3]
        
        ITEM1 --> CACHE1{Cache<br/>Hit?}
        ITEM2 --> CACHE2{Cache<br/>Hit?}
        ITEM3 --> CACHE3{Cache<br/>Hit?}
        
        CACHE1 -->|Yes| HIT1[⚔ Return cached<br/>~10ms]
        CACHE1 -->|No| COMPILE1[āš™ļø Compile<br/>~2000ms]
        
        CACHE2 -->|Yes| HIT2[⚔ Return cached<br/>~10ms]
        CACHE2 -->|No| COMPILE2[āš™ļø Compile<br/>~3000ms]
        
        CACHE3 -->|Yes| HIT3[⚔ Return cached<br/>~10ms]
        CACHE3 -->|No| COMPILE3[āš™ļø Compile<br/>~1500ms]
        
        HIT1 --> RESULT
        COMPILE1 --> STORE1[šŸ’¾ Cache for 1hr]
        STORE1 --> RESULT
        
        HIT2 --> RESULT
        COMPILE2 --> STORE2[šŸ’¾ Cache for 1hr]
        STORE2 --> RESULT
        
        HIT3 --> RESULT
        COMPILE3 --> STORE3[šŸ’¾ Cache for 1hr]
        STORE3 --> RESULT[šŸ“„ Return all results]
    end
    
    style REQ fill:#667eea,stroke:#333,stroke-width:2px,color:#fff
    style HIT1 fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style HIT2 fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style HIT3 fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style COMPILE1 fill:#f59e0b,stroke:#333,stroke-width:2px,color:#fff
    style COMPILE2 fill:#f59e0b,stroke:#333,stroke-width:2px,color:#fff
    style COMPILE3 fill:#f59e0b,stroke:#333,stroke-width:2px,color:#fff
    style RESULT fill:#3b82f6,stroke:#333,stroke-width:2px,color:#fff

Performance Tips

mindmap
    root((Performance<br/>Tips))
        Request Optimization
            Use unique IDs
            Group similar lists
            Enable benchmarking for metrics
            Reuse configurations
        Caching
            Identical configs = cache hit
            1 hour TTL
            Check X-Cache header
            Warm cache with async
        Polling Strategy
            Start with 30s intervals
            Increase to 60s after 3 attempts
            Max 10-20 attempts
            Use webhooks when available
        Error Handling
            Retry with exponential backoff
            Handle partial failures
            Log all errors
            Monitor queue stats

Troubleshooting

Common Issues and Solutions

graph TB
    subgraph "Common Problems & Solutions"
        P1[āŒ 400: Too many items]
        P2[āŒ 400: Invalid configuration]
        P3[āŒ 429: Rate limit exceeded]
        P4[āŒ 404: Results not found]
        P5[ā³ Async taking too long]
        P6[āŒ Partial failures]
        
        P1 --> S1[āœ… Split batch into<br/>multiple requests<br/>Max 10 items per batch]
        P2 --> S2[āœ… Validate JSON schema<br/>Check required fields<br/>Use OpenAPI spec]
        P3 --> S3[āœ… Wait 60 seconds<br/>Use async API<br/>Implement backoff]
        P4 --> S4[āœ… Results expired after 24h<br/>Check requestId spelling<br/>Re-run compilation]
        P5 --> S5[āœ… Large lists take time<br/>Check queue stats<br/>Use high priority]
        P6 --> S6[āœ… Check each item.success<br/>Successful items still returned<br/>Retry failed items]
    end
    
    style P1 fill:#ef4444,stroke:#333,stroke-width:2px,color:#fff
    style P2 fill:#ef4444,stroke:#333,stroke-width:2px,color:#fff
    style P3 fill:#ef4444,stroke:#333,stroke-width:2px,color:#fff
    style P4 fill:#ef4444,stroke:#333,stroke-width:2px,color:#fff
    style P5 fill:#f59e0b,stroke:#333,stroke-width:2px,color:#fff
    style P6 fill:#f59e0b,stroke:#333,stroke-width:2px,color:#fff
    style S1 fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style S2 fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style S3 fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style S4 fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style S5 fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style S6 fill:#10b981,stroke:#333,stroke-width:2px,color:#fff

Debugging Workflow

graph TB
    START[šŸ› Issue Detected]
    
    START --> STEP1{Check<br/>Response<br/>Status}
    
    STEP1 -->|4xx| CLIENT[Client Error]
    STEP1 -->|5xx| SERVER[Server Error]
    STEP1 -->|2xx| SUCCESS[Request OK]
    
    CLIENT --> CHECK_REQ[Review request body<br/>Validate against schema<br/>Check item count]
    SERVER --> CHECK_STATUS[Check queue stats<br/>Check worker health<br/>Retry request]
    SUCCESS --> CHECK_RESULTS{All items<br/>successful?}
    
    CHECK_RESULTS -->|No| PARTIAL[Partial Failure]
    CHECK_RESULTS -->|Yes| GOOD[āœ… All Good!]
    
    PARTIAL --> ANALYZE[Analyze failed items<br/>Check error messages<br/>Retry individually]
    
    CHECK_REQ --> FIX[Fix and retry]
    CHECK_STATUS --> CONTACT[Contact support<br/>if persists]
    ANALYZE --> FIX
    
    style START fill:#667eea,stroke:#333,stroke-width:3px,color:#fff
    style CLIENT fill:#ef4444,stroke:#333,stroke-width:2px,color:#fff
    style SERVER fill:#ef4444,stroke:#333,stroke-width:2px,color:#fff
    style SUCCESS fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style GOOD fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style PARTIAL fill:#f59e0b,stroke:#333,stroke-width:2px,color:#fff
    style FIX fill:#3b82f6,stroke:#333,stroke-width:2px,color:#fff

Queue Status Monitoring

graph LR
    subgraph "Monitor Queue Health"
        API[🌐 GET /queue/stats]
        
        API --> METRICS[šŸ“Š Queue Metrics]
        
        METRICS --> PENDING[šŸ“‹ Pending Jobs<br/>Currently queued]
        METRICS --> PROCESSING[āš™ļø Processing Rate<br/>Jobs per minute]
        METRICS --> COMPLETED[āœ… Completed Count<br/>Success total]
        METRICS --> FAILED[āŒ Failed Count<br/>Error total]
        METRICS --> LAG[ā±ļø Queue Lag<br/>Avg wait time]
        
        PENDING --> HEALTH{Queue<br/>Health?}
        LAG --> HEALTH
        
        HEALTH -->|Good| OK[āœ… Normal Operation<br/>Lag < 5 seconds<br/>Pending < 100]
        HEALTH -->|Warning| WARN[āš ļø High Load<br/>Lag 5-30 seconds<br/>Pending 100-500]
        HEALTH -->|Critical| CRIT[🚨 Overloaded<br/>Lag > 30 seconds<br/>Pending > 500]
    end
    
    style API fill:#667eea,stroke:#333,stroke-width:2px,color:#fff
    style METRICS fill:#3b82f6,stroke:#333,stroke-width:2px,color:#fff
    style OK fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style WARN fill:#f59e0b,stroke:#333,stroke-width:2px,color:#fff
    style CRIT fill:#ef4444,stroke:#333,stroke-width:2px,color:#fff

Quick Reference

API Endpoints Summary

EndpointMethodPurposeReturns
/compile/batchPOSTSynchronous batch compilationImmediate results
/compile/batch/asyncPOSTAsynchronous batch compilationRequest ID
/queue/results/:idGETGet async resultsResults or status
/queue/statsGETQueue statisticsMetrics

Request Limits

graph LR
    subgraph "Batch API Limits"
        L1[šŸ“Š Max Items: 10<br/>per batch]
        L2[ā±ļø Sync Timeout: 30s<br/>total execution]
        L3[🚦 Rate Limit: 10<br/>requests/minute]
        L4[šŸ“¦ Max Size: 1MB<br/>request body]
        L5[šŸ’¾ Cache TTL: 1 hour<br/>result storage]
        L6[šŸ“ Result TTL: 24 hours<br/>async results]
    end
    
    style L1 fill:#667eea,stroke:#333,stroke-width:2px,color:#fff
    style L2 fill:#667eea,stroke:#333,stroke-width:2px,color:#fff
    style L3 fill:#667eea,stroke:#333,stroke-width:2px,color:#fff
    style L4 fill:#667eea,stroke:#333,stroke-width:2px,color:#fff
    style L5 fill:#667eea,stroke:#333,stroke-width:2px,color:#fff
    style L6 fill:#667eea,stroke:#333,stroke-width:2px,color:#fff

Decision Matrix

graph TB
    subgraph "Choose the Right API"
        Q1{How many<br/>filter lists?}
        Q2{Need results<br/>immediately?}
        Q3{Lists are<br/>large/slow?}
        
        Q1 -->|1| SINGLE[Use /compile]
        Q1 -->|2-10| Q2
        Q1 -->|>10| MULTI[Split into<br/>multiple batches]
        
        Q2 -->|Yes| Q3
        Q2 -->|No| ASYNC_B[āœ… /compile/batch/async]
        
        Q3 -->|Yes| ASYNC_B2[āœ… /compile/batch/async]
        Q3 -->|No| SYNC_B[āœ… /compile/batch]
    end
    
    style Q1 fill:#f59e0b,stroke:#333,stroke-width:2px,color:#000
    style Q2 fill:#f59e0b,stroke:#333,stroke-width:2px,color:#000
    style Q3 fill:#f59e0b,stroke:#333,stroke-width:2px,color:#000
    style SINGLE fill:#3b82f6,stroke:#333,stroke-width:2px,color:#fff
    style SYNC_B fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
    style ASYNC_B fill:#8b5cf6,stroke:#333,stroke-width:2px,color:#fff
    style ASYNC_B2 fill:#8b5cf6,stroke:#333,stroke-width:2px,color:#fff
    style MULTI fill:#ef4444,stroke:#333,stroke-width:2px,color:#fff


Need Help?


Last updated: 2026-01-14