@fjell/registry 4.4.7 → 4.4.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -4
- package/dist/Registry.cjs +20 -1
- package/dist/Registry.js +20 -1
- package/dist/RegistryHub.cjs +17 -1
- package/dist/RegistryHub.js +17 -1
- package/dist/index.cjs +35 -0
- package/dist/index.cjs.map +1 -1
- package/dist/types.d.ts +15 -0
- package/docs/README.md +74 -0
- package/docs/index.html +17 -0
- package/docs/memory-data/scaling-10-instances.json +206 -206
- package/docs/memory-data/scaling-100-instances.json +206 -206
- package/docs/memory-data/scaling-1000-instances.json +108 -108
- package/docs/memory-data/scaling-10000-instances.json +49 -49
- package/docs/memory-data/scaling-20-instances.json +208 -208
- package/docs/memory-data/scaling-200-instances.json +201 -201
- package/docs/memory-data/scaling-2000-instances.json +107 -107
- package/docs/memory-data/scaling-50-instances.json +206 -206
- package/docs/memory-data/scaling-500-instances.json +108 -108
- package/docs/memory-data/scaling-5000-instances.json +49 -49
- package/docs/memory-overhead.svg +17 -17
- package/docs/memory.md +111 -111
- package/docs/package.json +35 -0
- package/docs/public/README.md +623 -0
- package/docs/public/TIMING_NODE_OPTIMIZATION.md +207 -0
- package/docs/public/examples/coordinates-example.ts +253 -0
- package/docs/public/examples/multi-level-keys.ts +374 -0
- package/docs/public/examples/registry-hub-coordinates-example.ts +370 -0
- package/docs/public/examples/registry-hub-types.ts +437 -0
- package/docs/public/examples/simple-example.ts +250 -0
- package/docs/public/examples-README.md +222 -0
- package/docs/public/fjell-icon.svg +1 -0
- package/docs/public/icon.png +0 -0
- package/docs/public/icon2.png +0 -0
- package/docs/public/memory-overhead.svg +120 -0
- package/docs/public/memory.md +430 -0
- package/docs/public/pano.png +0 -0
- package/docs/public/pano2.png +0 -0
- package/docs/public/timing-range.svg +176 -0
- package/docs/public/timing.md +483 -0
- package/docs/src/App.css +1175 -0
- package/docs/src/App.test.tsx +50 -0
- package/docs/src/App.tsx +583 -0
- package/docs/src/index.css +40 -0
- package/docs/src/main.tsx +10 -0
- package/docs/src/test/setup.ts +1 -0
- package/docs/timing-range.svg +41 -41
- package/docs/timing.md +101 -101
- package/docs/tsconfig.node.json +13 -0
- package/docs/vitest.config.ts +14 -0
- package/examples/README.md +35 -0
- package/examples/coordinates-example.ts +253 -0
- package/examples/registry-hub-coordinates-example.ts +370 -0
- package/package.json +1 -1
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Node.js Optimization for Timing Tests
|
|
2
|
+
|
|
3
|
+
This document outlines Node.js runtime parameters that can be tuned to minimize interference and improve timing test accuracy.
|
|
4
|
+
|
|
5
|
+
## Quick Start: Optimized Timing Test
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm run test:timing:optimized
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
This runs timing tests with pre-configured optimal Node.js flags.
|
|
12
|
+
|
|
13
|
+
## Key Node.js Optimization Flags
|
|
14
|
+
|
|
15
|
+
### Memory Management
|
|
16
|
+
|
|
17
|
+
#### `--max-old-space-size=8192`
|
|
18
|
+
- **Purpose**: Increases maximum heap size to 8GB (default ~1.4GB)
|
|
19
|
+
- **Benefit**: Prevents garbage collection during test runs
|
|
20
|
+
- **Why 8GB**: Provides ample headroom for 100 rounds × multiple tree sizes
|
|
21
|
+
- **Alternative**: `--max-old-space-size=4096` for systems with less RAM
|
|
22
|
+
|
|
23
|
+
#### `--max-semi-space-size=1024`
|
|
24
|
+
- **Purpose**: Increases semi-space size to 1GB (default varies)
|
|
25
|
+
- **Benefit**: Reduces minor GC frequency during object allocation
|
|
26
|
+
- **Impact**: Each semi-space can hold more objects before collection
|
|
27
|
+
|
|
28
|
+
### Garbage Collection Control
|
|
29
|
+
|
|
30
|
+
#### `--expose-gc`
|
|
31
|
+
- **Purpose**: Exposes `global.gc()` function for manual garbage collection
|
|
32
|
+
- **Benefit**: Allows forced GC between test rounds for consistent baselines
|
|
33
|
+
- **Usage**: Can trigger GC at specific points to isolate timing measurements
|
|
34
|
+
|
|
35
|
+
#### `--gc-interval=1000000`
|
|
36
|
+
- **Purpose**: Reduces GC frequency (higher number = less frequent)
|
|
37
|
+
- **Benefit**: Minimizes GC interruptions during timing measurements
|
|
38
|
+
- **Trade-off**: Uses more memory but provides consistent timing
|
|
39
|
+
|
|
40
|
+
### Execution Predictability
|
|
41
|
+
|
|
42
|
+
#### `--predictable`
|
|
43
|
+
- **Purpose**: Makes execution more deterministic
|
|
44
|
+
- **Benefit**: Reduces timing variance from non-deterministic optimizations
|
|
45
|
+
- **Impact**: Slightly slower but more consistent measurements
|
|
46
|
+
|
|
47
|
+
#### `--no-compilation-cache`
|
|
48
|
+
- **Purpose**: Disables V8 compilation cache
|
|
49
|
+
- **Benefit**: Ensures consistent JIT compilation behavior across runs
|
|
50
|
+
- **Use Case**: When testing cold start performance or eliminating cache effects
|
|
51
|
+
|
|
52
|
+
### JIT Compilation Control
|
|
53
|
+
|
|
54
|
+
#### `--optimize-for-size`
|
|
55
|
+
- **Purpose**: Optimizes for code size rather than speed
|
|
56
|
+
- **Benefit**: More predictable compilation behavior
|
|
57
|
+
- **Alternative**: `--max-opt` for maximum optimization (less predictable)
|
|
58
|
+
|
|
59
|
+
#### `--no-opt`
|
|
60
|
+
- **Purpose**: Disables JIT compilation entirely
|
|
61
|
+
- **Benefit**: Eliminates JIT timing variance (but much slower execution)
|
|
62
|
+
- **Use Case**: Testing interpreter-only performance
|
|
63
|
+
|
|
64
|
+
## Complete Optimization Command
|
|
65
|
+
|
|
66
|
+
For maximum timing accuracy, use all optimization flags:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Use NODE_OPTIONS for compatibility with modern Node.js
|
|
70
|
+
NODE_OPTIONS="--max-old-space-size=8192 --max-semi-space-size=1024" \
|
|
71
|
+
vitest run tests/timing.test.ts
|
|
72
|
+
|
|
73
|
+
# Or use direct node invocation (requires vitest executable)
|
|
74
|
+
node --max-old-space-size=8192 --max-semi-space-size=1024 \
|
|
75
|
+
./node_modules/vitest/vitest.mjs run tests/timing.test.ts
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## System-Specific Adjustments
|
|
79
|
+
|
|
80
|
+
### Low-Memory Systems (< 8GB RAM)
|
|
81
|
+
```bash
|
|
82
|
+
NODE_OPTIONS="--max-old-space-size=2048 --max-semi-space-size=256" \
|
|
83
|
+
vitest run tests/timing.test.ts
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### High-Memory Systems (> 16GB RAM)
|
|
87
|
+
```bash
|
|
88
|
+
NODE_OPTIONS="--max-old-space-size=16384 --max-semi-space-size=2048" \
|
|
89
|
+
vitest run tests/timing.test.ts
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Docker/Container Environments
|
|
93
|
+
```bash
|
|
94
|
+
NODE_OPTIONS="--max-old-space-size=4096 --max-semi-space-size=512" \
|
|
95
|
+
vitest run tests/timing.test.ts
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Environment Variables
|
|
99
|
+
|
|
100
|
+
### Additional V8 Options
|
|
101
|
+
```bash
|
|
102
|
+
export NODE_OPTIONS="--max-old-space-size=8192 --max-semi-space-size=1024"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Memory Monitoring
|
|
106
|
+
```bash
|
|
107
|
+
export NODE_ENV=production # Disable development overhead
|
|
108
|
+
export UV_THREADPOOL_SIZE=8 # Increase thread pool if needed
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Monitoring Memory During Tests
|
|
112
|
+
|
|
113
|
+
Add memory monitoring to timing tests:
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
// Add to timing test setup
|
|
117
|
+
if (global.gc) {
|
|
118
|
+
console.log('Memory before tests:', process.memoryUsage());
|
|
119
|
+
global.gc();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Add between test rounds
|
|
123
|
+
if (global.gc && round % 20 === 0) {
|
|
124
|
+
global.gc();
|
|
125
|
+
console.log(`Memory after round ${round}:`, process.memoryUsage());
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Platform-Specific Considerations
|
|
130
|
+
|
|
131
|
+
### macOS
|
|
132
|
+
- Default memory limits are generous
|
|
133
|
+
- Use `--max-old-space-size=8192` safely
|
|
134
|
+
- Activity Monitor shows Node.js memory usage
|
|
135
|
+
|
|
136
|
+
### Linux
|
|
137
|
+
- Check `ulimit -v` for virtual memory limits
|
|
138
|
+
- May need `sudo sysctl vm.max_map_count=262144` for large heaps
|
|
139
|
+
- Use `htop` or `ps` to monitor memory
|
|
140
|
+
|
|
141
|
+
### Windows
|
|
142
|
+
- WSL may have memory constraints
|
|
143
|
+
- PowerShell: `Get-Process node | Select-Object WorkingSet64`
|
|
144
|
+
- Task Manager shows detailed memory breakdown
|
|
145
|
+
|
|
146
|
+
### CI/CD Environments
|
|
147
|
+
- GitHub Actions: 7GB RAM limit, use `--max-old-space-size=4096`
|
|
148
|
+
- GitLab CI: Variable memory, check runner specs
|
|
149
|
+
- Docker: Set container memory limits appropriately
|
|
150
|
+
|
|
151
|
+
## Performance Analysis Tools
|
|
152
|
+
|
|
153
|
+
### V8 Profiling
|
|
154
|
+
```bash
|
|
155
|
+
node --prof --log-timer-events ./timing-test.js
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Heap Snapshots
|
|
159
|
+
```bash
|
|
160
|
+
node --inspect --heap-prof ./timing-test.js
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### GC Logging
|
|
164
|
+
```bash
|
|
165
|
+
node --trace-gc --trace-gc-verbose ./timing-test.js
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Validation
|
|
169
|
+
|
|
170
|
+
Test that optimizations are working:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
# Run normal timing tests
|
|
174
|
+
pnpm run test:timing
|
|
175
|
+
|
|
176
|
+
# Run optimized timing tests
|
|
177
|
+
pnpm run test:timing:optimized
|
|
178
|
+
|
|
179
|
+
# Compare results - optimized should show:
|
|
180
|
+
# 1. Lower timing variance (smaller standard deviations)
|
|
181
|
+
# 2. More consistent Bollinger bands
|
|
182
|
+
# 3. Fewer outlier measurements
|
|
183
|
+
# 4. Reduced memory-related timing spikes
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Recommended Configuration
|
|
187
|
+
|
|
188
|
+
For most use cases, the optimized configuration provides the best balance:
|
|
189
|
+
|
|
190
|
+
```json
|
|
191
|
+
{
|
|
192
|
+
"scripts": {
|
|
193
|
+
"test:timing:optimized": "NODE_OPTIONS=\"--max-old-space-size=8192 --max-semi-space-size=1024\" vitest run tests/timing.test.ts"
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
This configuration:
|
|
199
|
+
- ✅ Eliminates most GC interference
|
|
200
|
+
- ✅ Provides consistent execution
|
|
201
|
+
- ✅ Works on most development machines
|
|
202
|
+
- ✅ Maintains reasonable test execution time
|
|
203
|
+
- ✅ Produces reliable performance metrics
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
*For production timing analysis, always use optimized Node.js flags to ensure accurate performance measurements.*
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coordinates Discovery Example
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates how to use the getCoordinates() method to:
|
|
5
|
+
* - Discover all registered instances in a registry
|
|
6
|
+
* - Inspect coordinates and their scopes
|
|
7
|
+
* - Monitor registry state for debugging
|
|
8
|
+
* - Implement discovery mechanisms
|
|
9
|
+
*
|
|
10
|
+
* Run this example with: npx tsx examples/coordinates-example.ts
|
|
11
|
+
*
|
|
12
|
+
* Note: In a real application, import from the built package:
|
|
13
|
+
* import { createRegistry, createInstance } from '@fjell/registry';
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
// Import the actual registry functionality
|
|
17
|
+
import { createRegistry } from '../src/Registry';
|
|
18
|
+
import { createInstance } from '../src/Instance';
|
|
19
|
+
|
|
20
|
+
// ===== Service Examples =====
|
|
21
|
+
|
|
22
|
+
class DatabaseService {
|
|
23
|
+
constructor(private type: string, private environment: string) { }
|
|
24
|
+
|
|
25
|
+
connect() {
|
|
26
|
+
console.log(`Connected to ${this.type} database in ${this.environment}`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
getInfo() {
|
|
30
|
+
return `${this.type} (${this.environment})`;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
class CacheService {
|
|
35
|
+
constructor(private type: string) { }
|
|
36
|
+
|
|
37
|
+
get(key: string) {
|
|
38
|
+
console.log(`Getting ${key} from ${this.type} cache`);
|
|
39
|
+
return `cached_${key}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
getInfo() {
|
|
43
|
+
return this.type;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
class LoggingService {
|
|
48
|
+
constructor(private level: string) { }
|
|
49
|
+
|
|
50
|
+
log(message: string) {
|
|
51
|
+
console.log(`[${this.level.toUpperCase()}] ${message}`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
getInfo() {
|
|
55
|
+
return `Logging at ${this.level} level`;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ===== Main Example =====
|
|
60
|
+
|
|
61
|
+
async function runCoordinatesExample() {
|
|
62
|
+
console.log('🔍 Registry Coordinates Discovery Example\n');
|
|
63
|
+
|
|
64
|
+
// Step 1: Create a registry
|
|
65
|
+
console.log('1. Creating registry...');
|
|
66
|
+
const registry = createRegistry('services');
|
|
67
|
+
console.log(' ✅ Registry created\n');
|
|
68
|
+
|
|
69
|
+
// Step 2: Register multiple instances with different scopes
|
|
70
|
+
console.log('2. Registering instances with various configurations...\n');
|
|
71
|
+
|
|
72
|
+
// Database services for different environments
|
|
73
|
+
registry.createInstance(
|
|
74
|
+
['database'],
|
|
75
|
+
['production', 'postgres'],
|
|
76
|
+
(coordinate, context) => {
|
|
77
|
+
const service = new DatabaseService('PostgreSQL', 'production');
|
|
78
|
+
const instance = createInstance(context.registry, coordinate);
|
|
79
|
+
(instance as any).connect = service.connect.bind(service);
|
|
80
|
+
(instance as any).getInfo = service.getInfo.bind(service);
|
|
81
|
+
return instance;
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
console.log(' ✅ PostgreSQL database (production) registered');
|
|
85
|
+
|
|
86
|
+
registry.createInstance(
|
|
87
|
+
['database'],
|
|
88
|
+
['development', 'sqlite'],
|
|
89
|
+
(coordinate, context) => {
|
|
90
|
+
const service = new DatabaseService('SQLite', 'development');
|
|
91
|
+
const instance = createInstance(context.registry, coordinate);
|
|
92
|
+
(instance as any).connect = service.connect.bind(service);
|
|
93
|
+
(instance as any).getInfo = service.getInfo.bind(service);
|
|
94
|
+
return instance;
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
console.log(' ✅ SQLite database (development) registered');
|
|
98
|
+
|
|
99
|
+
// Cache services
|
|
100
|
+
registry.createInstance(
|
|
101
|
+
['cache', 'redis'],
|
|
102
|
+
['production'],
|
|
103
|
+
(coordinate, context) => {
|
|
104
|
+
const service = new CacheService('Redis');
|
|
105
|
+
const instance = createInstance(context.registry, coordinate);
|
|
106
|
+
(instance as any).get = service.get.bind(service);
|
|
107
|
+
(instance as any).getInfo = service.getInfo.bind(service);
|
|
108
|
+
return instance;
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
console.log(' ✅ Redis cache (production) registered');
|
|
112
|
+
|
|
113
|
+
registry.createInstance(
|
|
114
|
+
['cache', 'memory'],
|
|
115
|
+
['development', 'testing'],
|
|
116
|
+
(coordinate, context) => {
|
|
117
|
+
const service = new CacheService('In-Memory');
|
|
118
|
+
const instance = createInstance(context.registry, coordinate);
|
|
119
|
+
(instance as any).get = service.get.bind(service);
|
|
120
|
+
(instance as any).getInfo = service.getInfo.bind(service);
|
|
121
|
+
return instance;
|
|
122
|
+
}
|
|
123
|
+
);
|
|
124
|
+
console.log(' ✅ Memory cache (development/testing) registered');
|
|
125
|
+
|
|
126
|
+
// Logging services
|
|
127
|
+
registry.createInstance(
|
|
128
|
+
['logging'],
|
|
129
|
+
['production'],
|
|
130
|
+
(coordinate, context) => {
|
|
131
|
+
const service = new LoggingService('error');
|
|
132
|
+
const instance = createInstance(context.registry, coordinate);
|
|
133
|
+
(instance as any).log = service.log.bind(service);
|
|
134
|
+
(instance as any).getInfo = service.getInfo.bind(service);
|
|
135
|
+
return instance;
|
|
136
|
+
}
|
|
137
|
+
);
|
|
138
|
+
console.log(' ✅ Error logging (production) registered');
|
|
139
|
+
|
|
140
|
+
registry.createInstance(
|
|
141
|
+
['logging'],
|
|
142
|
+
['development'],
|
|
143
|
+
(coordinate, context) => {
|
|
144
|
+
const service = new LoggingService('debug');
|
|
145
|
+
const instance = createInstance(context.registry, coordinate);
|
|
146
|
+
(instance as any).log = service.log.bind(service);
|
|
147
|
+
(instance as any).getInfo = service.getInfo.bind(service);
|
|
148
|
+
return instance;
|
|
149
|
+
}
|
|
150
|
+
);
|
|
151
|
+
console.log(' ✅ Debug logging (development) registered\n');
|
|
152
|
+
|
|
153
|
+
// Step 3: Demonstrate getCoordinates functionality
|
|
154
|
+
console.log('3. Discovering all registered coordinates...\n');
|
|
155
|
+
|
|
156
|
+
const coordinates = registry.getCoordinates();
|
|
157
|
+
console.log(`📊 Total registered coordinates: ${coordinates.length}\n`);
|
|
158
|
+
|
|
159
|
+
// Display all coordinates with their details
|
|
160
|
+
console.log('📍 Registered Coordinates:');
|
|
161
|
+
console.log('─'.repeat(60));
|
|
162
|
+
coordinates.forEach((coord, index) => {
|
|
163
|
+
console.log(`${index + 1}. ${coord.toString()}`);
|
|
164
|
+
console.log(` Key Path: [${coord.kta.join(' → ')}]`);
|
|
165
|
+
console.log(` Scopes: ${coord.scopes.length > 0 ? coord.scopes.join(', ') : 'none'}`);
|
|
166
|
+
console.log('');
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// Step 4: Demonstrate filtering and analysis
|
|
170
|
+
console.log('4. Analyzing coordinate patterns...\n');
|
|
171
|
+
|
|
172
|
+
// Group by environment
|
|
173
|
+
const byEnvironment = {
|
|
174
|
+
production: coordinates.filter(c => c.scopes.includes('production')),
|
|
175
|
+
development: coordinates.filter(c => c.scopes.includes('development')),
|
|
176
|
+
testing: coordinates.filter(c => c.scopes.includes('testing')),
|
|
177
|
+
unscoped: coordinates.filter(c => c.scopes.length === 0)
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
console.log('🏢 Coordinates by Environment:');
|
|
181
|
+
Object.entries(byEnvironment).forEach(([env, coords]) => {
|
|
182
|
+
if (coords.length > 0) {
|
|
183
|
+
console.log(` ${env}: ${coords.length} instance(s)`);
|
|
184
|
+
coords.forEach(coord => {
|
|
185
|
+
console.log(` - ${coord.kta.join('.')}`);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// Group by service type (first element of kta)
|
|
191
|
+
const byServiceType = coordinates.reduce((acc, coord) => {
|
|
192
|
+
const serviceType = coord.kta[0];
|
|
193
|
+
if (!acc[serviceType]) acc[serviceType] = [];
|
|
194
|
+
acc[serviceType].push(coord);
|
|
195
|
+
return acc;
|
|
196
|
+
}, {} as Record<string, typeof coordinates>);
|
|
197
|
+
|
|
198
|
+
console.log('\n🔧 Coordinates by Service Type:');
|
|
199
|
+
Object.entries(byServiceType).forEach(([type, coords]) => {
|
|
200
|
+
console.log(` ${type}: ${coords.length} instance(s)`);
|
|
201
|
+
coords.forEach(coord => {
|
|
202
|
+
const scopeInfo = coord.scopes.length > 0 ? ` (${coord.scopes.join(', ')})` : '';
|
|
203
|
+
console.log(` - ${coord.kta.join('.')}${scopeInfo}`);
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// Step 5: Demonstrate practical usage scenarios
|
|
208
|
+
console.log('\n5. Practical usage scenarios...\n');
|
|
209
|
+
|
|
210
|
+
// Scenario 1: Health check - verify all expected services are registered
|
|
211
|
+
console.log('🏥 Health Check Example:');
|
|
212
|
+
const expectedServices = ['database', 'cache', 'logging'];
|
|
213
|
+
const registeredServices = [...new Set(coordinates.map(c => c.kta[0]))];
|
|
214
|
+
|
|
215
|
+
expectedServices.forEach(service => {
|
|
216
|
+
const isRegistered = registeredServices.includes(service);
|
|
217
|
+
console.log(` ${service}: ${isRegistered ? '✅ Registered' : '❌ Missing'}`);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// Scenario 2: Environment validation
|
|
221
|
+
console.log('\n🌍 Environment Validation:');
|
|
222
|
+
const productionServices = coordinates.filter(c => c.scopes.includes('production'));
|
|
223
|
+
const developmentServices = coordinates.filter(c => c.scopes.includes('development'));
|
|
224
|
+
|
|
225
|
+
console.log(` Production environment has ${productionServices.length} service(s) registered`);
|
|
226
|
+
console.log(` Development environment has ${developmentServices.length} service(s) registered`);
|
|
227
|
+
|
|
228
|
+
// Scenario 3: Discovery mechanism
|
|
229
|
+
console.log('\n🔍 Service Discovery Example:');
|
|
230
|
+
console.log(' Available cache services:');
|
|
231
|
+
coordinates
|
|
232
|
+
.filter(c => c.kta.includes('cache'))
|
|
233
|
+
.forEach(coord => {
|
|
234
|
+
console.log(` - ${coord.kta.join('.')} (${coord.scopes.join(', ') || 'any scope'})`);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
console.log('\n✨ Coordinates discovery example completed!');
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
totalCoordinates: coordinates.length,
|
|
241
|
+
coordinates: coordinates,
|
|
242
|
+
byEnvironment,
|
|
243
|
+
byServiceType
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Export for testing
|
|
248
|
+
export { runCoordinatesExample };
|
|
249
|
+
|
|
250
|
+
// Run the example if this file is executed directly
|
|
251
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
252
|
+
runCoordinatesExample().catch(console.error);
|
|
253
|
+
}
|