233 lines
6.5 KiB
TypeScript
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)
|
|
})
|