bluefly/alternative_services

Service abstraction layer for flexible dependency injection and service swapping

v1.0.3 2025-07-14 10:47 UTC

This package is auto-updated.

Last update: 2025-07-14 10:53:18 UTC


README

Simple service discovery and configuration management using native Drupal patterns.

Overview

The Alternative Services module provides a unified interface for managing external services, APIs, and development tools in Drupal. It offers intelligent service discovery, health monitoring, and automatic failover capabilities, making it easier to build resilient applications that can adapt to service availability.

Features

  • Service Registry: Centralized configuration for all external services
  • Health Monitoring: Real-time availability checks with configurable intervals
  • Intelligent Failover: Automatic switching to alternative services when primary fails
  • DDEV Integration: Native UI for managing DDEV addons and services
  • AI-Powered Discovery: Automatically discover compatible services in your environment
  • Multi-Service Support: Cache, search, queue, storage, and development tools
  • Performance Tracking: Monitor service response times and reliability
  • Event System: React to service status changes in real-time

Requirements

  • Drupal 10.4 or higher / Drupal 11
  • PHP 8.1 or higher

Suggested Modules

  • Redis (drupal/redis) - For Redis cache backend
  • Memcache (drupal/memcache) - For Memcache integration
  • Queue UI (drupal/queue_ui) - For queue service monitoring
  • Devel (drupal/devel) - For development tools integration

Installation

  1. Install via Composer:

    composer require bluefly/alternative_services
    
  2. Enable the module:

    drush en alternative_services
    
  3. Configure services at /admin/config/development/alternative-services

Service Types

Cache Services

Configure multiple cache backends with automatic failover:

  • Redis (primary)
  • Memcache (fallback)
  • Database (emergency)
  • Varnish (HTTP cache)

Search Services

Manage search providers with health monitoring:

  • Elasticsearch
  • Apache Solr
  • Meilisearch
  • Database fallback

Queue Services

Queue backend management:

  • RabbitMQ
  • Beanstalkd
  • AWS SQS
  • Database queues

Storage Services

External storage configuration:

  • Amazon S3
  • MinIO
  • Local filesystem
  • FTP/SFTP

Development Tools

DDEV addon management and debugging services:

  • Mailhog
  • phpMyAdmin
  • Elasticsearch Head
  • Redis Commander

Usage

Basic Service Registration

// Get the service provider
$provider = \Drupal::service('alternative_services.provider');

// Register a cache service with alternatives
$provider->registerService('cache', [
  'primary' => [
    'type' => 'redis',
    'host' => 'redis',
    'port' => 6379,
    'password' => NULL,
  ],
  'fallback' => [
    'type' => 'memcache',
    'host' => 'memcached',
    'port' => 11211,
  ],
  'emergency' => [
    'type' => 'database',
    'table' => 'cache',
  ]
]);

Using Services with Automatic Failover

// Get a service (automatically uses first available)
$cache = \Drupal::service('alternative_services.provider')
  ->getService('cache');

// Service will automatically failover if primary fails
try {
  $cache->set('my_key', 'my_value');
} catch (ServiceUnavailableException $e) {
  // All services are down
  \Drupal::logger('alternative_services')->error('No cache service available');
}

Health Monitoring

// Check service health
$health = \Drupal::service('alternative_services.health_monitor');
$status = $health->checkService('elasticsearch');

if (!$status->isHealthy()) {
  // Service is down, failover will occur automatically
  \Drupal::logger('alternative_services')->warning(
    'Service @service is unhealthy: @reason',
    ['@service' => 'elasticsearch', '@reason' => $status->getReason()]
  );
}

DDEV Integration

The module provides a UI for DDEV addon management:

  1. Navigate to /admin/config/development/alternative-services/ddev
  2. Browse available DDEV addons
  3. Click "Install" to add services to your DDEV environment
  4. Monitor service health from the dashboard

AI-Powered Service Discovery

// Discover available services
$discovery = \Drupal::service('alternative_services.discovery');
$services = $discovery->discover(['type' => 'cache']);

foreach ($services as $service) {
  // Automatically detected services in your environment
  print $service['name'] . ' at ' . $service['host'] . ':' . $service['port'];
}

Configuration

Global Settings

Configure at /admin/config/development/alternative-services/settings:

  • Health Check Interval: How often to check service health (default: 60 seconds)
  • Connection Timeout: Maximum time to wait for service response (default: 5 seconds)
  • Retry Attempts: Number of retries before failover (default: 3)
  • Failover Strategy: Round-robin, priority, or random selection

Per-Service Configuration

Each service type can have specific settings:

# In alternative_services.settings.yml
elasticsearch:
  health_check_interval: 30
  connection_timeout: 10
  retry_attempts: 2
  failover_strategy: priority

Drush Commands

# List all configured services
drush as:list

# Check health of all services
drush as:health-check

# Check specific service
drush as:health-check --service=elasticsearch

# Discover services in environment
drush as:discover

# Discover specific service type
drush as:discover --type=cache

# Force service failover
drush as:failover cache

# Reset service to primary
drush as:reset cache

Events

The module dispatches events for service status changes:

use Drupal\alternative_services\Event\ServiceStatusEvent;

// Subscribe to service events
class MyEventSubscriber implements EventSubscriberInterface {
  
  public static function getSubscribedEvents() {
    return [
      ServiceStatusEvent::SERVICE_DOWN => 'onServiceDown',
      ServiceStatusEvent::SERVICE_UP => 'onServiceUp',
      ServiceStatusEvent::SERVICE_FAILOVER => 'onServiceFailover',
    ];
  }
  
  public function onServiceDown(ServiceStatusEvent $event) {
    // React to service going down
    $service = $event->getService();
    \Drupal::logger('my_module')->error('Service @service is down', 
      ['@service' => $service->getName()]
    );
  }
}

Extending the Module

Custom Service Types

namespace Drupal\my_module\Plugin\AlternativeService;

use Drupal\alternative_services\Plugin\AlternativeServiceBase;

/**
 * @AlternativeService(
 *   id = "my_service",
 *   label = @Translation("My Custom Service"),
 *   description = @Translation("Custom service implementation")
 * )
 */
class MyService extends AlternativeServiceBase {
  
  public function checkHealth() {
    // Implement health check
    return $this->ping($this->configuration['host']);
  }
  
  public function connect() {
    // Establish connection
  }
}

Troubleshooting

Service Not Failing Over

  1. Check health check interval isn't too long
  2. Verify fallback services are configured
  3. Check logs for connection errors
  4. Ensure service credentials are correct

DDEV Addon Installation Fails

  1. Verify DDEV is running (ddev status)
  2. Check DDEV version compatibility
  3. Review DDEV logs (ddev logs)
  4. Ensure proper permissions

Performance Considerations

  • Health checks run asynchronously to avoid blocking
  • Failed services are cached to prevent repeated connection attempts
  • Use appropriate health check intervals based on service criticality
  • Consider using local services (Redis, Memcache) for better performance

Support

License

This project is licensed under the GPL-2.0-or-later license.