Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Service Discovery Bundle Laravel Package

coka/service-discovery-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install via Composer

    composer require coka/service-discovery-bundle
    

    Add the bundle to config/bundles.php in a Symfony project (or equivalent Laravel service provider registration).

  2. Configure Services Define your services in config/packages/oka_service_discovery.yaml (Symfony) or equivalent Laravel config:

    oka_service_discovery:
        services:
            - name: "user-service"
              url: "http://user-service:8000"
              healthy: true
            - name: "order-service"
              url: "http://order-service:8000"
              healthy: false
    
  3. First Use Case: Service Discovery Inject the ServiceDiscovery class and fetch a service:

    use Oka\ServiceDiscoveryBundle\ServiceDiscovery;
    
    $discovery = $this->container->get('oka_service_discovery');
    $userServiceUrl = $discovery->getServiceUrl('user-service');
    

Laravel Equivalent (Manual Setup)

For Laravel, create a service provider:

// app/Providers/ServiceDiscoveryProvider.php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Oka\ServiceDiscoveryBundle\ServiceDiscovery;

class ServiceDiscoveryProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->singleton('service.discovery', function () {
            $config = config('service_discovery.services', []);
            return new ServiceDiscovery($config);
        });
    }
}

Register in config/app.php and define config in config/service_discovery.php:

'service_discovery' => [
    'services' => [
        [
            'name' => 'user-service',
            'url' => 'http://user-service:8000',
            'healthy' => true,
        ],
    ],
],

Implementation Patterns

Core Workflows

  1. Dynamic Service Resolution Use the bundle to resolve service URLs at runtime (e.g., in controllers or services):

    $serviceUrl = app('service.discovery')->getServiceUrl('order-service');
    $client = new \GuzzleHttp\Client(['base_uri' => $serviceUrl]);
    
  2. Health-Checked Requests Skip unhealthy services automatically:

    if (app('service.discovery')->isServiceHealthy('user-service')) {
        // Proceed with request
    }
    
  3. Service Registration Extend the bundle to register services dynamically (e.g., from a database):

    $discovery = app('service.discovery');
    $discovery->addService([
        'name' => 'payment-service',
        'url' => 'http://payment-service:8000',
        'healthy' => false,
    ]);
    

Integration Tips

  1. HTTP Client Integration Combine with Laravel's HTTP client for seamless requests:

    $response = \Http::baseUrl(app('service.discovery')->getServiceUrl('user-service'))
        ->get('/api/users');
    
  2. Service Discovery Middleware Create middleware to inject service URLs into requests:

    // app/Http/Middleware/ServiceDiscoveryMiddleware.php
    public function handle($request, Closure $next)
    {
        $request->merge([
            'service_url' => app('service.discovery')->getServiceUrl('order-service'),
        ]);
        return $next($request);
    }
    
  3. Caching Service URLs Cache resolved URLs to avoid repeated lookups:

    $url = Cache::remember('service.user-service.url', now()->addHours(1), function () {
        return app('service.discovery')->getServiceUrl('user-service');
    });
    
  4. Event-Driven Updates Listen for service health changes (if the bundle supports events) to trigger recaching or retries.


Gotchas and Tips

Pitfalls

  1. No Built-in Service Discovery Protocol The bundle assumes services are pre-configured. For dynamic discovery (e.g., Consul, Eureka), integrate with a dedicated service mesh or SDK.

  2. Health Check Logic The healthy flag is static. For real-time checks, extend the bundle or use a separate health-check endpoint.

  3. Lack of Load Balancing The bundle does not support load balancing across multiple instances of a service. Use a dedicated load balancer (e.g., Laravel Horizon, Envoy) or integrate with a service mesh.

  4. No Circuit Breaker Missing automatic retries or failover logic. Combine with libraries like Spatie Circuit Breaker.


Debugging

  1. Verify Configuration Ensure config/service_discovery.php is correctly loaded and services are defined:

    dd(config('service_discovery.services'));
    
  2. Check Service Resolution Debug service URL resolution:

    $discovery = app('service.discovery');
    dd($discovery->getServiceUrl('non-existent-service')); // Should return null or throw exception
    
  3. Health Check Logic If services appear unhealthy unexpectedly, verify the healthy flag or extend the bundle to implement custom health checks.


Extension Points

  1. Custom Service Providers Extend the bundle to support additional service providers (e.g., Docker, Kubernetes):

    // Extend ServiceDiscovery class
    class ExtendedServiceDiscovery extends ServiceDiscovery
    {
        public function discoverFromKubernetes(): array
        {
            // Custom logic to fetch services from Kubernetes
        }
    }
    
  2. Dynamic Configuration Load services from environment variables or a database:

    $services = collect(config('service_discovery.services'))
        ->merge($this->getServicesFromDatabase())
        ->toArray();
    
  3. Add Metadata Extend service definitions to include metadata (e.g., timeout, retry_policy):

    services:
        - name: "user-service"
          url: "http://user-service:8000"
          healthy: true
          timeout: 5
    
  4. Event Dispatching Trigger events when services are added/removed or health status changes:

    // Example: Dispatch event after adding a service
    event(new ServiceAdded($service));
    

Laravel-Specific Tips

  1. Service Container Binding Bind the discovery service to the container for easier dependency injection:

    $this->app->bind('service.discovery', function () {
        return new ServiceDiscovery(config('service_discovery.services'));
    });
    
  2. Artisan Commands Create an Artisan command to manage services:

    // app/Console/Commands/ListServices.php
    public function handle()
    {
        $services = app('service.discovery')->getServices();
        foreach ($services as $service) {
            $this->info($service['name'] . ' (' . ($service['healthy'] ? '✅' : '❌') . ')');
        }
    }
    
  3. Testing Mock the service discovery in tests:

    $this->app->instance('service.discovery', Mockery::mock(ServiceDiscovery::class));
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager