service-discovery/example-usage.ts

233 lines
6.5 KiB
TypeScript

/**
* Example usage of @lilith/service-discovery
* This demonstrates the complete API surface
*/
import { createServiceDiscovery, LoadBalanceStrategy, ServiceHealthStatus } from '@lilith/service-discovery'
async function main() {
// Create client
const client = createServiceDiscovery({
redis: 'redis://localhost:6379',
keyPrefix: 'service:discovery',
heartbeatIntervalMs: 10_000,
unhealthyThresholdMs: 30_000,
expirationMs: 60_000,
defaultLoadBalanceStrategy: LoadBalanceStrategy.ROUND_ROBIN,
debug: true,
})
const registration = client.getRegistration()
const discovery = client.getDiscovery()
// === REGISTRATION ===
// Register a service
const serviceData = await registration.register(
'platform-admin-api',
'platform-admin',
'api',
'localhost',
3011,
'http',
{
version: '1.0.0',
tags: ['public', 'admin'],
metadata: {
nodeVersion: process.version,
environment: 'development',
},
healthCheckPath: '/health',
autoHeartbeat: true, // Automatic heartbeat every 10s
},
)
console.log('Registered service:', serviceData.instanceId)
// Update metadata
await registration.updateMetadata({
responseTimeMs: 45,
activeConnections: 3,
metadata: { uptime: 12345 },
})
// Update health status
await registration.updateHealthStatus(ServiceHealthStatus.HEALTHY)
// Manual heartbeat (if autoHeartbeat is false)
await registration.heartbeat()
// === DISCOVERY ===
// Find all healthy services
const allServices = await discovery.discoverAll({
serviceName: 'platform-admin-api',
onlyHealthy: true,
})
console.log(`Found ${allServices.length} healthy instances`)
// Find services by feature
const featureServices = await discovery.discoverAll({
featureName: 'platform-admin',
})
// Find services by type
const apiServices = await discovery.discoverAll({
serviceType: 'api',
})
// Find services by tags
const publicServices = await discovery.discoverAll({
tags: ['public'],
})
// Find services with version filter
const recentServices = await discovery.discoverAll({
serviceName: 'platform-admin-api',
minVersion: '1.0.0',
})
// Find services by health status
const startingServices = await discovery.discoverAll({
healthStatus: ServiceHealthStatus.STARTING,
})
// === LOAD BALANCING ===
// Get one instance with round-robin
const instanceRR = await discovery.discoverOne({
serviceName: 'platform-admin-api',
loadBalanceStrategy: LoadBalanceStrategy.ROUND_ROBIN,
})
console.log('Round-robin instance:', instanceRR?.url)
// Get one instance with random selection
const instanceRandom = await discovery.discoverOne({
serviceName: 'platform-admin-api',
loadBalanceStrategy: LoadBalanceStrategy.RANDOM,
})
// Get one instance with least response time
const instanceLRT = await discovery.discoverOne({
serviceName: 'platform-admin-api',
loadBalanceStrategy: LoadBalanceStrategy.LEAST_RESPONSE_TIME,
})
// Get one instance with least connections
const instanceLC = await discovery.discoverOne({
serviceName: 'platform-admin-api',
loadBalanceStrategy: LoadBalanceStrategy.LEAST_CONNECTIONS,
})
// Get instance with full load balance details
const lbResult = await discovery.discoverWithLoadBalance({
serviceName: 'platform-admin-api',
loadBalanceStrategy: LoadBalanceStrategy.ROUND_ROBIN,
})
if (lbResult) {
console.log('Load balance result:', {
url: lbResult.service.url,
strategy: lbResult.strategy,
availableInstances: lbResult.availableInstances,
})
}
// Allow unhealthy instances if no healthy ones available
const fallbackInstance = await discovery.discoverOne({
serviceName: 'platform-admin-api',
allowUnhealthy: true,
})
// === SPECIFIC INSTANCE QUERIES ===
// Get specific instance by ID
const instanceId = serviceData.instanceId
const specificInstance = await discovery.getInstance(instanceId)
console.log('Specific instance:', specificInstance?.url)
// Check if instance exists
const exists = await discovery.instanceExists(instanceId)
console.log('Instance exists:', exists)
// Get all instances of a service
const serviceInstances = await discovery.getServiceInstances('platform-admin-api')
console.log(`Service has ${serviceInstances.length} instances`)
// Get all instances in a feature
const featureInstances = await discovery.getFeatureInstances('platform-admin')
console.log(`Feature has ${featureInstances.length} instances`)
// === STATISTICS ===
const stats = await discovery.getStats()
console.log('Discovery stats:', {
total: stats.totalServices,
healthy: stats.healthyServices,
unhealthy: stats.unhealthyServices,
byFeature: stats.byFeature,
byType: stats.byType,
avgResponseTime: stats.avgResponseTimeMs,
})
// === WATCHING FOR CHANGES ===
const subscription = await discovery.watch(
async (event) => {
console.log(`Service event: ${event.type}`)
console.log(` Service: ${event.service.serviceName}`)
console.log(` Instance: ${event.service.instanceId}`)
console.log(` URL: ${event.service.url}`)
console.log(` Timestamp: ${event.timestamp}`)
if (event.type === 'health-changed') {
console.log(` Previous health: ${event.previousHealthStatus}`)
console.log(` New health: ${event.service.healthStatus}`)
}
},
{
// Optional filter - only watch specific services
serviceName: 'platform-admin-api',
},
)
// Watch all services in a feature
const featureSubscription = await discovery.watch(
async (event) => {
console.log(`Feature event: ${event.type} - ${event.service.serviceName}`)
},
{ featureName: 'platform-admin' },
)
// Watch specific health status changes
const unhealthySubscription = await discovery.watch(
async (event) => {
console.error(`Unhealthy service detected: ${event.service.serviceName}`)
},
{ healthStatus: ServiceHealthStatus.UNHEALTHY },
)
// === CLEANUP ===
// Wait for some events...
await new Promise((resolve) => setTimeout(resolve, 5000))
// Unsubscribe from events
await subscription.unsubscribe()
await featureSubscription.unsubscribe()
await unhealthySubscription.unsubscribe()
// Deregister service
await registration.deregister()
// Cleanup and disconnect
await client.cleanup()
console.log('Example completed')
}
// Run example
main().catch((error) => {
console.error('Example failed:', error)
process.exit(1)
})