Skip to the content.

The Batch Processor handles scheduled jobs, data maintenance, reporting, and automated business processes for the Modern Reservation System.

๐ŸŽฏ Overview

Property Value
Service Name batch-processor
Port 8085
Health Check /actuator/health
API Base URL http://localhost:8085/api/v1/batch
OpenAPI Spec /v3/api-docs
Swagger UI /swagger-ui.html

๐Ÿš€ Quick Start

Start the Service

# Via dev script
./dev.sh start batch-processor

# Via Maven
cd apps/backend/java-services/business-services/batch-processor
mvn spring-boot:run

Health Check

curl http://localhost:8085/actuator/health

โš™๏ธ Core Features

Scheduled Jobs

Data Processing

Automated Operations

๐Ÿ”Œ API Endpoints

List All Jobs

GET /api/v1/batch/jobs
Authorization: Bearer <jwt-token>
X-Tenant-ID: <tenant-id>

Response:

{
  "jobs": [
    {
      "jobId": "daily-revenue-report",
      "name": "Daily Revenue Report",
      "description": "Generate daily revenue and occupancy reports",
      "schedule": "0 6 * * *",
      "status": "ACTIVE",
      "lastRun": "2025-10-10T06:00:00Z",
      "nextRun": "2025-10-11T06:00:00Z",
      "executionTime": "45s",
      "successRate": 99.2
    },
    {
      "jobId": "data-cleanup",
      "name": "Data Cleanup",
      "description": "Archive old records and optimize database",
      "schedule": "0 2 * * 0",
      "status": "ACTIVE",
      "lastRun": "2025-10-06T02:00:00Z",
      "nextRun": "2025-10-13T02:00:00Z",
      "executionTime": "2m 15s",
      "successRate": 100.0
    },
    {
      "jobId": "rate-sync",
      "name": "Rate Synchronization",
      "description": "Sync rates with external channel managers",
      "schedule": "0 */4 * * *",
      "status": "ACTIVE",
      "lastRun": "2025-10-10T12:00:00Z",
      "nextRun": "2025-10-10T16:00:00Z",
      "executionTime": "1m 30s",
      "successRate": 98.5
    }
  ],
  "summary": {
    "totalJobs": 15,
    "activeJobs": 12,
    "pausedJobs": 2,
    "failedJobs": 1,
    "avgExecutionTime": "1m 25s"
  }
}

Get Job Details

GET /api/v1/batch/jobs/{jobId}
Authorization: Bearer <jwt-token>
X-Tenant-ID: <tenant-id>

Response:

{
  "jobId": "daily-revenue-report",
  "name": "Daily Revenue Report",
  "description": "Generate comprehensive daily revenue and occupancy reports for all properties",
  "category": "REPORTING",
  "schedule": {
    "cron": "0 6 * * *",
    "timezone": "America/New_York",
    "description": "Daily at 6:00 AM EST"
  },
  "configuration": {
    "properties": ["ALL"],
    "reportTypes": ["REVENUE", "OCCUPANCY", "ADR", "REVPAR"],
    "outputFormat": "PDF",
    "emailRecipients": [
      "revenue@hotel.com",
      "management@hotel.com"
    ],
    "archiveLocation": "s3://reports/daily/"
  },
  "status": "ACTIVE",
  "execution": {
    "lastRun": "2025-10-10T06:00:00Z",
    "nextRun": "2025-10-11T06:00:00Z",
    "avgExecutionTime": "45s",
    "successRate": 99.2,
    "totalRuns": 365,
    "successfulRuns": 362,
    "failedRuns": 3
  },
  "dependencies": [
    "reservation-engine",
    "payment-processor",
    "analytics-engine"
  ],
  "monitoring": {
    "alertsEnabled": true,
    "alertThreshold": "2m",
    "notificationChannels": ["email", "slack"]
  }
}

Trigger Job Manually

POST /api/v1/batch/jobs/{jobId}/execute
Authorization: Bearer <jwt-token>
X-Tenant-ID: <tenant-id>
Content-Type: application/json

Request Body:

{
  "parameters": {
    "date": "2025-10-10",
    "properties": ["prop-123", "prop-456"],
    "reportType": "DETAILED"
  },
  "priority": "HIGH",
  "triggeredBy": "admin-user",
  "reason": "Manual execution for specific date range"
}

Response:

{
  "executionId": "exec-789012",
  "jobId": "daily-revenue-report",
  "status": "RUNNING",
  "startTime": "2025-10-10T14:30:00Z",
  "estimatedCompletion": "2025-10-10T14:31:00Z",
  "parameters": {
    "date": "2025-10-10",
    "properties": ["prop-123", "prop-456"],
    "reportType": "DETAILED"
  },
  "progress": {
    "percentage": 0,
    "currentStep": "Initializing",
    "totalSteps": 5
  }
}

Get Job Execution Status

GET /api/v1/batch/executions/{executionId}
Authorization: Bearer <jwt-token>
X-Tenant-ID: <tenant-id>

Response:

{
  "executionId": "exec-789012",
  "jobId": "daily-revenue-report",
  "status": "COMPLETED",
  "startTime": "2025-10-10T14:30:00Z",
  "endTime": "2025-10-10T14:30:47Z",
  "duration": "47s",
  "progress": {
    "percentage": 100,
    "currentStep": "Completed",
    "totalSteps": 5,
    "stepsCompleted": [
      {
        "step": "Data Collection",
        "duration": "15s",
        "status": "SUCCESS",
        "recordsProcessed": 1250
      },
      {
        "step": "Revenue Calculation",
        "duration": "20s",
        "status": "SUCCESS",
        "calculations": 850
      },
      {
        "step": "Report Generation",
        "duration": "10s",
        "status": "SUCCESS",
        "pages": 12
      },
      {
        "step": "Email Distribution",
        "duration": "2s",
        "status": "SUCCESS",
        "emailsSent": 5
      }
    ]
  },
  "output": {
    "reportUrl": "https://reports.example.com/daily-revenue-2025-10-10.pdf",
    "recordsProcessed": 1250,
    "outputSize": "2.3 MB",
    "checksum": "sha256:abc123..."
  },
  "logs": {
    "logLevel": "INFO",
    "logUrl": "https://logs.example.com/exec-789012.log",
    "errorCount": 0,
    "warningCount": 2
  }
}

Schedule New Job

POST /api/v1/batch/jobs
Authorization: Bearer <jwt-token>
X-Tenant-ID: <tenant-id>
Content-Type: application/json

Request Body:

{
  "name": "Weekly Guest Satisfaction Survey",
  "description": "Send satisfaction surveys to guests who checked out in the past week",
  "category": "COMMUNICATION",
  "schedule": {
    "cron": "0 10 * * 1",
    "timezone": "America/New_York"
  },
  "configuration": {
    "surveyTemplate": "post-stay-satisfaction",
    "targetAudience": "CHECKED_OUT_LAST_7_DAYS",
    "emailTemplate": "survey-invitation",
    "excludeRecent": true,
    "maxRecipients": 1000
  },
  "dependencies": [
    "guest-service"
  ],
  "monitoring": {
    "alertsEnabled": true,
    "alertThreshold": "5m",
    "notificationChannels": ["email"]
  },
  "retryPolicy": {
    "maxRetries": 3,
    "retryDelay": "5m",
    "backoffMultiplier": 2
  }
}

Response:

{
  "jobId": "weekly-guest-survey",
  "name": "Weekly Guest Satisfaction Survey",
  "status": "ACTIVE",
  "schedule": {
    "cron": "0 10 * * 1",
    "nextRun": "2025-10-14T10:00:00Z"
  },
  "createdAt": "2025-10-10T15:00:00Z",
  "createdBy": "admin-user"
}

Pause/Resume Job

PUT /api/v1/batch/jobs/{jobId}/status
Authorization: Bearer <jwt-token>
X-Tenant-ID: <tenant-id>
Content-Type: application/json

Request Body:

{
  "status": "PAUSED",
  "reason": "Maintenance window",
  "pausedBy": "admin-user"
}

Response:

{
  "jobId": "daily-revenue-report",
  "previousStatus": "ACTIVE",
  "currentStatus": "PAUSED",
  "changedAt": "2025-10-10T15:30:00Z",
  "changedBy": "admin-user",
  "reason": "Maintenance window",
  "nextScheduledRun": null
}

Get Job Execution History

GET /api/v1/batch/jobs/{jobId}/executions?limit=50&offset=0
Authorization: Bearer <jwt-token>
X-Tenant-ID: <tenant-id>

Response:

{
  "executions": [
    {
      "executionId": "exec-789012",
      "startTime": "2025-10-10T06:00:00Z",
      "endTime": "2025-10-10T06:00:45Z",
      "duration": "45s",
      "status": "COMPLETED",
      "recordsProcessed": 1250,
      "triggeredBy": "SCHEDULER"
    },
    {
      "executionId": "exec-789011",
      "startTime": "2025-10-09T06:00:00Z",
      "endTime": "2025-10-09T06:00:42Z",
      "duration": "42s",
      "status": "COMPLETED",
      "recordsProcessed": 1180,
      "triggeredBy": "SCHEDULER"
    },
    {
      "executionId": "exec-789010",
      "startTime": "2025-10-08T06:00:00Z",
      "endTime": null,
      "duration": null,
      "status": "FAILED",
      "error": "Database connection timeout",
      "triggeredBy": "SCHEDULER"
    }
  ],
  "pagination": {
    "limit": 50,
    "offset": 0,
    "total": 365,
    "hasMore": true
  },
  "summary": {
    "successRate": 99.2,
    "avgDuration": "43s",
    "totalExecutions": 365,
    "recentFailures": 1
  }
}

๐Ÿ“Š Predefined Job Categories

Reporting Jobs

daily-revenue-report:
  schedule: "0 6 * * *"
  description: "Daily revenue and occupancy analysis"

weekly-performance-summary:
  schedule: "0 7 * * 1"
  description: "Weekly KPI and performance metrics"

monthly-financial-report:
  schedule: "0 8 1 * *"
  description: "Monthly P&L and financial analysis"

guest-satisfaction-analytics:
  schedule: "0 9 * * 1"
  description: "Weekly guest feedback and satisfaction trends"

Maintenance Jobs

data-cleanup:
  schedule: "0 2 * * 0"
  description: "Archive old data and optimize database"

log-rotation:
  schedule: "0 3 * * *"
  description: "Rotate and compress application logs"

cache-refresh:
  schedule: "0 4 * * *"
  description: "Refresh cached data and clear expired entries"

health-check-aggregation:
  schedule: "*/15 * * * *"
  description: "Aggregate system health metrics"

Business Process Jobs

rate-sync:
  schedule: "0 */4 * * *"
  description: "Synchronize rates with channel managers"

inventory-update:
  schedule: "0 */2 * * *"
  description: "Update room inventory across all channels"

loyalty-points-processing:
  schedule: "0 23 * * *"
  description: "Process loyalty points and tier updates"

automated-confirmations:
  schedule: "*/30 * * * *"
  description: "Send automated booking confirmations"

Communication Jobs

reminder-emails:
  schedule: "0 8 * * *"
  description: "Send check-in reminders to arriving guests"

feedback-requests:
  schedule: "0 10 * * *"
  description: "Send feedback requests to departed guests"

promotional-campaigns:
  schedule: "0 12 * * *"
  description: "Send targeted promotional emails"

birthday-greetings:
  schedule: "0 9 * * *"
  description: "Send birthday greetings to loyalty members"

๐Ÿ”ง Configuration

Application Properties

# Batch Processor Configuration
batch-processor:
  scheduler:
    pool-size: 10
    max-pool-size: 20
    queue-capacity: 100

  job-execution:
    timeout: 1800s  # 30 minutes
    retry:
      max-attempts: 3
      delay: 300s   # 5 minutes
      backoff-multiplier: 2

  monitoring:
    metrics-enabled: true
    health-check-interval: 60s
    alert-threshold: 300s  # 5 minutes

  storage:
    output-location: "s3://batch-outputs/"
    log-location: "s3://batch-logs/"
    retention-days: 90

  notifications:
    email-enabled: true
    slack-enabled: true
    webhook-enabled: false

# Database Configuration
spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/batch_jobs
    username: batch_user
    password: ${BATCH_DB_PASSWORD}

  quartz:
    job-store-type: jdbc
    jdbc:
      initialize-schema: embedded
    properties:
      org:
        quartz:
          jobStore:
            driverDelegateClass: org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
            useProperties: false
            misfireThreshold: 60000

Environment Variables

# Database
BATCH_DB_PASSWORD=secure_batch_password

# External Services
RESERVATION_ENGINE_URL=http://localhost:8084
PAYMENT_PROCESSOR_URL=http://localhost:8082
ANALYTICS_ENGINE_URL=http://localhost:8086

# Storage
AWS_ACCESS_KEY_ID=your_access_key
AWS_SECRET_ACCESS_KEY=your_secret_key
AWS_REGION=us-east-1
S3_BUCKET_OUTPUTS=batch-outputs
S3_BUCKET_LOGS=batch-logs

# Notifications
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USERNAME=batch@hotel.com
SMTP_PASSWORD=email_password

SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...

# Monitoring
OTEL_SERVICE_NAME=batch-processor
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317

๐Ÿ“ˆ Performance & Monitoring

Performance Metrics

Business Metrics

# Job execution metrics
batch_jobs_executed_total{job="daily-revenue-report",status="success"}
batch_jobs_duration_seconds{job="data-cleanup"}
batch_jobs_records_processed_total{job="rate-sync"}

# System metrics
batch_scheduler_active_jobs
batch_executor_queue_size
batch_executor_thread_pool_active

# Business impact metrics
batch_reports_generated_total
batch_data_processed_bytes
batch_notifications_sent_total

๐Ÿงช Testing

Unit Tests

cd apps/backend/java-services/business-services/batch-processor
mvn test

Integration Tests

mvn verify -P integration-tests

Job Testing

# Test job execution
curl -X POST http://localhost:8085/api/v1/batch/jobs/test-job/execute \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Tenant-ID: test-tenant" \
  -H "Content-Type: application/json" \
  -d '{"parameters": {"dryRun": true}}'

# Test scheduler
curl -X GET http://localhost:8085/api/v1/batch/scheduler/status \
  -H "Authorization: Bearer $TOKEN"

# Test job configuration
curl -X POST http://localhost:8085/api/v1/batch/jobs/validate \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Test Job",
    "schedule": {"cron": "0 12 * * *"},
    "configuration": {"testParam": "value"}
  }'

๐Ÿ› ๏ธ Development

Local Development

# Run with development profile
mvn spring-boot:run -Dspring-boot.run.profiles=dev

# Run with debug
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5010"

Custom Job Development

@Component
public class CustomReportJob implements Job {

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        JobDataMap dataMap = context.getJobDetail().getJobDataMap();
        String tenantId = dataMap.getString("tenantId");

        try {
            // Job implementation
            generateCustomReport(tenantId);

        } catch (Exception e) {
            throw new JobExecutionException("Job execution failed", e);
        }
    }

    private void generateCustomReport(String tenantId) {
        // Custom logic here
    }
}

@Configuration
public class JobConfiguration {

    @Bean
    public JobDetail customReportJobDetail() {
        return JobBuilder.newJob(CustomReportJob.class)
                .withIdentity("customReportJob")
                .withDescription("Generate custom reports")
                .storeDurably()
                .build();
    }

    @Bean
    public Trigger customReportTrigger() {
        return TriggerBuilder.newTrigger()
                .forJob(customReportJobDetail())
                .withIdentity("customReportTrigger")
                .withSchedule(CronScheduleBuilder.cronSchedule("0 8 * * *"))
                .build();
    }
}

Database Schema

-- Job executions table
CREATE TABLE job_executions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    job_id VARCHAR(100) NOT NULL,
    execution_id VARCHAR(100) UNIQUE NOT NULL,
    tenant_id VARCHAR(50) NOT NULL,
    status VARCHAR(20) NOT NULL,
    start_time TIMESTAMP NOT NULL,
    end_time TIMESTAMP,
    duration_seconds INTEGER,
    records_processed INTEGER,
    output_location VARCHAR(500),
    error_message TEXT,
    triggered_by VARCHAR(50),
    parameters JSONB,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Job configuration table
CREATE TABLE job_configurations (
    job_id VARCHAR(100) PRIMARY KEY,
    tenant_id VARCHAR(50) NOT NULL,
    name VARCHAR(200) NOT NULL,
    description TEXT,
    category VARCHAR(50),
    cron_expression VARCHAR(100),
    timezone VARCHAR(50),
    status VARCHAR(20) DEFAULT 'ACTIVE',
    configuration JSONB,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Job dependencies table
CREATE TABLE job_dependencies (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    job_id VARCHAR(100) REFERENCES job_configurations(job_id),
    depends_on_service VARCHAR(100) NOT NULL,
    dependency_type VARCHAR(50) DEFAULT 'SERVICE',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

๐Ÿšจ Troubleshooting

Common Issues

Job Execution Failures

# Check job status
curl -H "Authorization: Bearer $TOKEN" \
     http://localhost:8085/api/v1/batch/jobs/failed-job

# View execution logs
curl -H "Authorization: Bearer $TOKEN" \
     http://localhost:8085/api/v1/batch/executions/exec-123/logs

# Retry failed execution
curl -X POST -H "Authorization: Bearer $TOKEN" \
     http://localhost:8085/api/v1/batch/executions/exec-123/retry

Scheduler Issues

# Check scheduler health
curl http://localhost:8085/actuator/health/scheduler

# View active jobs
curl -H "Authorization: Bearer $TOKEN" \
     http://localhost:8085/api/v1/batch/scheduler/active-jobs

# Restart scheduler
curl -X POST -H "Authorization: Bearer $ADMIN_TOKEN" \
     http://localhost:8085/api/v1/admin/scheduler/restart

Performance Problems

# Check thread pool status
curl http://localhost:8085/actuator/metrics/executor.pool.size

# Monitor job queue
curl http://localhost:8085/actuator/metrics/executor.queue.remaining

# View slow executions
curl -H "Authorization: Bearer $TOKEN" \
     "http://localhost:8085/api/v1/batch/executions?status=RUNNING&duration=>300"