Skip to the content.

The Availability Calculator service handles real-time room availability computation, inventory management, and booking conflict resolution for the Modern Reservation System.

๐ŸŽฏ Overview

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

๐Ÿš€ Quick Start

Start the Service

# Via dev script
./dev.sh start availability-calculator

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

Health Check

curl http://localhost:8081/actuator/health

๐Ÿจ Core Features

Real-time Availability

Inventory Management

Performance Optimization

๐Ÿ”Œ API Endpoints

Check Availability

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

Query Parameters:

Response:

{
  "availability": {
    "available": true,
    "propertyId": "prop-123",
    "checkIn": "2025-10-15",
    "checkOut": "2025-10-17",
    "nights": 2,
    "totalRooms": 50
  },
  "roomTypes": [
    {
      "typeId": "standard",
      "typeName": "Standard Room",
      "available": 15,
      "total": 30,
      "rate": {
        "baseRate": 120.00,
        "totalRate": 240.00,
        "currency": "USD"
      }
    },
    {
      "typeId": "deluxe",
      "typeName": "Deluxe Room",
      "available": 8,
      "total": 15,
      "rate": {
        "baseRate": 180.00,
        "totalRate": 360.00,
        "currency": "USD"
      }
    }
  ],
  "restrictions": {
    "minimumStay": 1,
    "maximumStay": 14,
    "closedToArrival": false,
    "closedToDeparture": false
  }
}

Bulk Availability Check

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

Request Body:

{
  "requests": [
    {
      "propertyId": "prop-123",
      "checkIn": "2025-10-15",
      "checkOut": "2025-10-17",
      "roomType": "standard",
      "rooms": 2
    },
    {
      "propertyId": "prop-124",
      "checkIn": "2025-10-20",
      "checkOut": "2025-10-22",
      "roomType": "deluxe",
      "rooms": 1
    }
  ]
}

Response:

{
  "results": [
    {
      "requestId": 0,
      "available": true,
      "availableRooms": 15,
      "rate": {
        "baseRate": 120.00,
        "totalRate": 480.00
      }
    },
    {
      "requestId": 1,
      "available": true,
      "availableRooms": 8,
      "rate": {
        "baseRate": 180.00,
        "totalRate": 360.00
      }
    }
  ],
  "processedAt": "2025-10-10T12:00:00Z"
}

Hold Inventory

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

Request Body:

{
  "propertyId": "prop-123",
  "checkIn": "2025-10-15",
  "checkOut": "2025-10-17",
  "roomType": "standard",
  "rooms": 2,
  "holdDuration": 600,
  "reservationId": "res-temp-123"
}

Response:

{
  "holdId": "hold-456",
  "propertyId": "prop-123",
  "roomType": "standard",
  "rooms": 2,
  "expiresAt": "2025-10-10T12:10:00Z",
  "status": "ACTIVE"
}

Release Hold

DELETE /api/v1/availability/hold/{holdId}
Authorization: Bearer <jwt-token>
X-Tenant-ID: <tenant-id>

Response:

{
  "holdId": "hold-456",
  "status": "RELEASED",
  "releasedAt": "2025-10-10T12:05:00Z"
}

Inventory Status

GET /api/v1/availability/inventory/{propertyId}
Authorization: Bearer <jwt-token>
X-Tenant-ID: <tenant-id>

Query Parameters:

Response:

{
  "propertyId": "prop-123",
  "period": {
    "startDate": "2025-10-15",
    "endDate": "2025-10-30"
  },
  "inventory": [
    {
      "date": "2025-10-15",
      "roomTypes": {
        "standard": {
          "total": 30,
          "available": 25,
          "occupied": 5,
          "blocked": 0,
          "held": 2
        },
        "deluxe": {
          "total": 15,
          "available": 12,
          "occupied": 3,
          "blocked": 0,
          "held": 0
        }
      }
    }
  ]
}

๐Ÿ“ก Event Processing

Kafka Event Consumers

Reservation Events

Topic: reservation.created
Handler: updateInventoryOnReservation()
Purpose: Reduce available inventory when booking is confirmed

Reservation Cancellation

Topic: reservation.cancelled
Handler: restoreInventoryOnCancellation()
Purpose: Restore inventory when booking is cancelled

Rate Updates

Topic: rate.updated
Handler: invalidateAvailabilityCache()
Purpose: Clear cached availability when rates change

Event Publishing

Availability Updated

Topic: availability.updated
Schema:
  - propertyId: string
  - date: date
  - roomType: string
  - totalRooms: integer
  - availableRooms: integer
  - updatedAt: timestamp

๐Ÿ”ง Configuration

Application Properties

# Availability Calculator Configuration
availability:
  cache:
    ttl: 300s              # Cache availability for 5 minutes
    max-entries: 10000     # Maximum cache entries

  processing:
    parallel-threads: 8    # Parallel processing threads
    batch-size: 100        # Bulk check batch size

  holds:
    default-duration: 600s # Default hold duration (10 minutes)
    max-duration: 3600s    # Maximum hold duration (1 hour)
    cleanup-interval: 60s  # Expired hold cleanup interval

  inventory:
    overbooking-limit: 5   # Overbooking percentage
    lookahead-days: 365    # Inventory lookahead period

# Database Configuration
spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/availability
    username: availability_user
    password: ${AVAILABILITY_DB_PASSWORD}

  jpa:
    hibernate:
      ddl-auto: validate
    properties:
      hibernate:
        jdbc:
          batch_size: 50
        order_inserts: true
        order_updates: true

# Redis Configuration
spring:
  redis:
    host: localhost
    port: 6379
    database: 3
    timeout: 2000ms
    lettuce:
      pool:
        max-active: 20
        max-wait: -1ms

Environment Variables

# Database
AVAILABILITY_DB_PASSWORD=availability_secure_password
AVAILABILITY_DB_POOL_SIZE=20

# Cache
REDIS_URL=redis://localhost:6379/3
AVAILABILITY_CACHE_TTL=300

# Performance
AVAILABILITY_PARALLEL_THREADS=8
AVAILABILITY_BATCH_SIZE=100

# Monitoring
OTEL_SERVICE_NAME=availability-calculator
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317

๐Ÿ“ˆ Performance & Optimization

Performance Metrics

Optimization Strategies

Database Optimization

-- Critical indexes for performance
CREATE INDEX idx_inventory_property_date ON room_inventory(property_id, date);
CREATE INDEX idx_inventory_room_type ON room_inventory(room_type, date);
CREATE INDEX idx_holds_expiry ON inventory_holds(expires_at) WHERE status = 'ACTIVE';

Caching Strategy

// Multi-level caching
@Cacheable(value = "availability", key = "#propertyId + ':' + #checkIn + ':' + #checkOut")
public AvailabilityResult checkAvailability(String propertyId, LocalDate checkIn, LocalDate checkOut)

// Cache warming for popular properties
@Scheduled(fixedRate = 300000) // Every 5 minutes
public void warmAvailabilityCache()

Parallel Processing

// Parallel availability checks
CompletableFuture<AvailabilityResult>[] futures = requests.stream()
    .map(request -> CompletableFuture.supplyAsync(() ->
        checkSingleAvailability(request), executor))
    .toArray(CompletableFuture[]::new);

๐Ÿงช Testing

Unit Tests

cd apps/backend/java-services/business-services/availability-calculator
mvn test

Integration Tests

mvn verify -P integration-tests

Load Testing

# Test availability endpoint under load
artillery run tests/load/availability-load-test.yml

# Test bulk availability
artillery run tests/load/bulk-availability-load-test.yml

Sample Load Test Configuration:

# tests/load/availability-load-test.yml
config:
  target: 'http://localhost:8081'
  phases:
    - duration: 60   # 1 minute
      arrivalRate: 100  # 100 requests per second
scenarios:
  - name: "Check Availability"
    requests:
      - get:
          url: "/api/v1/availability/check"
          qs:
            propertyId: "prop-123"
            checkIn: "2025-10-15"
            checkOut: "2025-10-17"

๐Ÿ” Monitoring & Observability

Key Metrics

# Request metrics
http_requests_total{service="availability-calculator"}
http_request_duration_seconds{service="availability-calculator"}

# Business metrics
availability_checks_total
availability_cache_hits_total
availability_cache_misses_total
inventory_holds_active
inventory_holds_expired_total

# Performance metrics
availability_check_duration_seconds
bulk_availability_batch_size
inventory_update_duration_seconds

Health Checks

# Basic health
curl http://localhost:8081/actuator/health

# Detailed health with dependencies
curl http://localhost:8081/actuator/health/detail

# Custom availability health indicator
curl http://localhost:8081/actuator/health/availability

๐Ÿ› ๏ธ Development

Local Development

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

# Run with debug and specific configuration
mvn spring-boot:run \
  -Dspring-boot.run.profiles=dev \
  -Dspring-boot.run.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5006"

Database Schema

-- Core inventory table
CREATE TABLE room_inventory (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id VARCHAR(50) NOT NULL,
    property_id VARCHAR(50) NOT NULL,
    room_type VARCHAR(50) NOT NULL,
    date DATE NOT NULL,
    total_rooms INTEGER NOT NULL,
    available_rooms INTEGER NOT NULL,
    blocked_rooms INTEGER DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(tenant_id, property_id, room_type, date)
);

-- Inventory holds table
CREATE TABLE inventory_holds (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    hold_id VARCHAR(50) UNIQUE NOT NULL,
    tenant_id VARCHAR(50) NOT NULL,
    property_id VARCHAR(50) NOT NULL,
    room_type VARCHAR(50) NOT NULL,
    check_in DATE NOT NULL,
    check_out DATE NOT NULL,
    rooms INTEGER NOT NULL,
    reservation_id VARCHAR(50),
    status VARCHAR(20) DEFAULT 'ACTIVE',
    expires_at TIMESTAMP NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

๐Ÿšจ Troubleshooting

Common Issues

High Response Times

# Check database connection pool
curl http://localhost:8081/actuator/metrics/hikaricp.connections.active

# Monitor cache performance
curl http://localhost:8081/actuator/metrics/cache.gets

# Check parallel processing metrics
curl http://localhost:8081/actuator/metrics/executor.active

Cache Issues

# Monitor Redis connection
redis-cli -h localhost -p 6379 ping

# Check cache statistics
redis-cli -h localhost -p 6379 info stats

# Clear availability cache
redis-cli -h localhost -p 6379 flushdb

Inventory Discrepancies

# Check for expired holds
curl http://localhost:8081/actuator/metrics/availability.holds.expired

# Verify inventory consistency
./scripts/verify-inventory-consistency.sh

# Rebuild inventory cache
curl -X POST http://localhost:8081/api/v1/availability/admin/rebuild-cache