@backendkit-labs/bulkhead 0.1.2 → 0.2.0

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/package.json CHANGED
@@ -1,103 +1,103 @@
1
- {
2
- "name": "@backendkit-labs/bulkhead",
3
- "version": "0.1.2",
4
- "license": "Apache-2.0",
5
- "author": {
6
- "name": "BackendKit Labs",
7
- "email": "backendkit.dev@gmail.com"
8
- },
9
- "homepage": "https://github.com/backendkit-dev/backendkit-monorepo",
10
- "repository": {
11
- "type": "git",
12
- "url": "https://github.com/backendkit-dev/backendkit-monorepo.git",
13
- "directory": "packages/bulkhead"
14
- },
15
- "description": "Bulkhead concurrency limiting for Node.js — inspired by Resilience4j, with optional NestJS integration",
16
- "type": "module",
17
- "main": "./dist/index.cjs",
18
- "module": "./dist/index.js",
19
- "types": "./dist/index.d.ts",
20
- "exports": {
21
- ".": {
22
- "types": "./dist/index.d.ts",
23
- "import": "./dist/index.js",
24
- "require": "./dist/index.cjs"
25
- },
26
- "./nestjs": {
27
- "types": "./dist/nestjs/index.d.ts",
28
- "import": "./dist/nestjs/index.js",
29
- "require": "./dist/nestjs/index.cjs"
30
- }
31
- },
32
- "files": [
33
- "dist",
34
- "README.md",
35
- "LICENSE"
36
- ],
37
- "scripts": {
38
- "build": "tsup",
39
- "dev": "tsup --watch",
40
- "test": "vitest run",
41
- "test:watch": "vitest",
42
- "test:coverage": "vitest run --coverage",
43
- "typecheck": "tsc --noEmit",
44
- "lint": "eslint src/",
45
- "format": "prettier --write src/",
46
- "prepublishOnly": "npm run build && npm run test && npm run lint"
47
- },
48
- "keywords": [
49
- "resilience",
50
- "bulkhead",
51
- "concurrency",
52
- "rate-limiting",
53
- "circuit-breaker",
54
- "nestjs",
55
- "node",
56
- "backend"
57
- ],
58
- "bugs": {
59
- "url": "https://github.com/backendkit-dev/backendkit-monorepo/issues"
60
- },
61
- "publishConfig": {
62
- "access": "public"
63
- },
64
- "sideEffects": false,
65
- "engines": {
66
- "node": ">=18"
67
- },
68
- "peerDependencies": {
69
- "@nestjs/common": ">=10.0.0",
70
- "@nestjs/core": ">=10.0.0",
71
- "express": ">=4.0.0",
72
- "rxjs": ">=7.0.0"
73
- },
74
- "peerDependenciesMeta": {
75
- "@nestjs/common": {
76
- "optional": true
77
- },
78
- "@nestjs/core": {
79
- "optional": true
80
- },
81
- "express": {
82
- "optional": true
83
- },
84
- "rxjs": {
85
- "optional": true
86
- }
87
- },
88
- "devDependencies": {
89
- "@eslint/js": "^9.39.4",
90
- "@nestjs/common": "^10.0.0",
91
- "@nestjs/core": "^10.0.0",
92
- "@types/express": "^4.17.21",
93
- "@types/node": "^22.0.0",
94
- "eslint": "^9.0.0",
95
- "prettier": "^3.0.0",
96
- "reflect-metadata": "^0.2.0",
97
- "rxjs": "^7.8.0",
98
- "tsup": "^8.0.0",
99
- "typescript": "^5.5.0",
100
- "typescript-eslint": "^8.59.3",
101
- "vitest": "^2.0.0"
102
- }
103
- }
1
+ {
2
+ "name": "@backendkit-labs/bulkhead",
3
+ "version": "0.2.0",
4
+ "license": "Apache-2.0",
5
+ "author": {
6
+ "name": "BackendKit Labs",
7
+ "email": "hello@backendkitlabs.dev"
8
+ },
9
+ "homepage": "https://backendkitlabs.dev/docs/bulkhead/",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/BackendKit-labs/backendkit-monorepo.git",
13
+ "directory": "packages/bulkhead"
14
+ },
15
+ "description": "Bulkhead concurrency limiting for Node.js — inspired by Resilience4j, with optional NestJS integration",
16
+ "type": "module",
17
+ "main": "./dist/index.cjs",
18
+ "module": "./dist/index.js",
19
+ "types": "./dist/index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "import": "./dist/index.js",
24
+ "require": "./dist/index.cjs"
25
+ },
26
+ "./nestjs": {
27
+ "types": "./dist/nestjs/index.d.ts",
28
+ "import": "./dist/nestjs/index.js",
29
+ "require": "./dist/nestjs/index.cjs"
30
+ }
31
+ },
32
+ "files": [
33
+ "dist",
34
+ "README.md",
35
+ "LICENSE"
36
+ ],
37
+ "scripts": {
38
+ "build": "tsup",
39
+ "dev": "tsup --watch",
40
+ "test": "vitest run",
41
+ "test:watch": "vitest",
42
+ "test:coverage": "vitest run --coverage",
43
+ "typecheck": "tsc --noEmit",
44
+ "lint": "eslint src/",
45
+ "format": "prettier --write src/",
46
+ "prepublishOnly": "npm run build && npm run test && npm run lint"
47
+ },
48
+ "keywords": [
49
+ "resilience",
50
+ "bulkhead",
51
+ "concurrency",
52
+ "rate-limiting",
53
+ "circuit-breaker",
54
+ "nestjs",
55
+ "node",
56
+ "backend"
57
+ ],
58
+ "bugs": {
59
+ "url": "https://github.com/BackendKit-labs/backendkit-monorepo/issues"
60
+ },
61
+ "publishConfig": {
62
+ "access": "public"
63
+ },
64
+ "sideEffects": false,
65
+ "engines": {
66
+ "node": ">=18"
67
+ },
68
+ "peerDependencies": {
69
+ "@nestjs/common": ">=10.0.0",
70
+ "@nestjs/core": ">=10.0.0",
71
+ "express": ">=4.0.0",
72
+ "rxjs": ">=7.0.0"
73
+ },
74
+ "peerDependenciesMeta": {
75
+ "@nestjs/common": {
76
+ "optional": true
77
+ },
78
+ "@nestjs/core": {
79
+ "optional": true
80
+ },
81
+ "express": {
82
+ "optional": true
83
+ },
84
+ "rxjs": {
85
+ "optional": true
86
+ }
87
+ },
88
+ "devDependencies": {
89
+ "@eslint/js": "^9.39.4",
90
+ "@nestjs/common": "^10.0.0",
91
+ "@nestjs/core": "^10.0.0",
92
+ "@types/express": "^4.17.21",
93
+ "@types/node": "^22.0.0",
94
+ "eslint": "^9.0.0",
95
+ "prettier": "^3.0.0",
96
+ "reflect-metadata": "^0.2.0",
97
+ "rxjs": "^7.8.0",
98
+ "tsup": "^8.0.0",
99
+ "typescript": "^5.5.0",
100
+ "typescript-eslint": "^8.59.3",
101
+ "vitest": "^2.0.0"
102
+ }
103
+ }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/bulkhead/bulkhead.ts","../src/bulkhead/bulkhead.registry.ts"],"names":[],"mappings":"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","file":"chunk-LXXCDKHB.cjs","sourcesContent":["export interface BulkheadConfig {\n /** Max number of concurrent executions */\n maxConcurrentCalls: number;\n /** Max queue size for waiting tasks */\n maxQueueSize: number;\n /** Max time a task can wait in queue (ms) */\n queueTimeoutMs: number;\n /** Reject immediately when queue is full; if false, retries with backoff */\n rejectWhenFull: boolean;\n /** Identifier used in metrics and error messages */\n name: string;\n}\n\nexport interface BulkheadMetrics {\n name: string;\n activeCalls: number;\n queuedCalls: number;\n maxConcurrentCalls: number;\n maxQueueSize: number;\n totalCalls: number;\n successfulCalls: number;\n failedCalls: number;\n rejectedCalls: number;\n timedOutCalls: number;\n averageDurationMs: number;\n}\n\nexport class BulkheadRejectedError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'BulkheadRejectedError';\n }\n}\n\nexport class BulkheadTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'BulkheadTimeoutError';\n }\n}\n\nexport class Bulkhead {\n private activeCalls = 0;\n private nextId = 0;\n private queue: Array<{\n id: number;\n task: () => Promise<unknown>;\n resolve: (value: unknown) => void;\n reject: (reason: unknown) => void;\n queuedAt: number;\n }> = [];\n\n private totalCalls = 0;\n private successfulCalls = 0;\n private failedCalls = 0;\n private rejectedCalls = 0;\n private timedOutCalls = 0;\n private totalDurationMs = 0;\n\n constructor(private readonly config: BulkheadConfig) {}\n\n async execute<T>(task: () => Promise<T>): Promise<T> {\n const startTime = Date.now();\n this.totalCalls++;\n\n if (this.activeCalls < this.config.maxConcurrentCalls) {\n return this.runTask(task, startTime);\n }\n\n if (this.queue.length >= this.config.maxQueueSize) {\n if (this.config.rejectWhenFull) {\n this.rejectedCalls++;\n throw new BulkheadRejectedError(\n `Bulkhead '${this.config.name}' is full. ` +\n `Active: ${this.activeCalls}, Queue: ${this.queue.length}, Max: ${this.config.maxConcurrentCalls}`,\n );\n }\n return this.waitAndRetry(task, startTime);\n }\n\n const entryId = this.nextId++;\n return new Promise<T>((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n const index = this.queue.findIndex(item => item.id === entryId);\n if (index !== -1) this.queue.splice(index, 1);\n this.timedOutCalls++;\n reject(\n new BulkheadTimeoutError(\n `Bulkhead '${this.config.name}' timeout after ${this.config.queueTimeoutMs}ms`,\n ),\n );\n }, this.config.queueTimeoutMs);\n\n this.queue.push({\n id: entryId,\n task: task as () => Promise<unknown>,\n resolve: value => {\n clearTimeout(timeoutId);\n resolve(value as T);\n },\n reject: reason => {\n clearTimeout(timeoutId);\n reject(reason);\n },\n queuedAt: startTime,\n });\n\n this.processQueue();\n });\n }\n\n private async runTask<T>(task: () => Promise<T>, startTime: number): Promise<T> {\n this.activeCalls++;\n try {\n const result = await task();\n this.successfulCalls++;\n this.totalDurationMs += Date.now() - startTime;\n return result;\n } catch (error) {\n this.failedCalls++;\n throw error;\n } finally {\n this.activeCalls--;\n this.processQueue();\n }\n }\n\n private async waitAndRetry<T>(task: () => Promise<T>, startTime: number): Promise<T> {\n const maxRetries = 3;\n const baseDelay = 100;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n if (this.activeCalls < this.config.maxConcurrentCalls) {\n return this.runTask(task, startTime);\n }\n await new Promise(resolve => setTimeout(resolve, baseDelay * Math.pow(2, attempt - 1)));\n }\n\n this.rejectedCalls++;\n throw new BulkheadRejectedError(\n `Bulkhead '${this.config.name}' rejected after ${maxRetries} retries`,\n );\n }\n\n private processQueue(): void {\n while (this.activeCalls < this.config.maxConcurrentCalls && this.queue.length > 0) {\n const next = this.queue.shift();\n if (!next) break;\n\n const waitTime = Date.now() - next.queuedAt;\n if (waitTime > this.config.queueTimeoutMs) {\n next.reject(new BulkheadTimeoutError(`Task timed out after ${waitTime}ms in queue`));\n this.timedOutCalls++;\n continue;\n }\n\n this.activeCalls++;\n next\n .task()\n .then(result => {\n this.successfulCalls++;\n next.resolve(result);\n })\n .catch(error => {\n this.failedCalls++;\n next.reject(error);\n })\n .finally(() => {\n this.activeCalls--;\n this.processQueue();\n });\n }\n }\n\n getMetrics(): BulkheadMetrics {\n return {\n name: this.config.name,\n activeCalls: this.activeCalls,\n queuedCalls: this.queue.length,\n maxConcurrentCalls: this.config.maxConcurrentCalls,\n maxQueueSize: this.config.maxQueueSize,\n totalCalls: this.totalCalls,\n successfulCalls: this.successfulCalls,\n failedCalls: this.failedCalls,\n rejectedCalls: this.rejectedCalls,\n timedOutCalls: this.timedOutCalls,\n averageDurationMs:\n this.successfulCalls > 0 ? Math.round(this.totalDurationMs / this.successfulCalls) : 0,\n };\n }\n\n canAccept(): boolean {\n return (\n this.activeCalls < this.config.maxConcurrentCalls ||\n this.queue.length < this.config.maxQueueSize\n );\n }\n\n resetMetrics(): void {\n this.totalCalls = 0;\n this.successfulCalls = 0;\n this.failedCalls = 0;\n this.rejectedCalls = 0;\n this.timedOutCalls = 0;\n this.totalDurationMs = 0;\n }\n}\n","import { Bulkhead, BulkheadConfig, BulkheadMetrics } from './bulkhead.js';\n\nexport interface BulkheadOptions extends Partial<BulkheadConfig> {\n name: string;\n}\n\nconst DEFAULT_CONFIG: Omit<BulkheadConfig, 'name'> = {\n maxConcurrentCalls: 10,\n maxQueueSize: 100,\n queueTimeoutMs: 30000,\n rejectWhenFull: true,\n};\n\nexport class BulkheadRegistry {\n private readonly bulkheads = new Map<string, Bulkhead>();\n\n getOrCreate(options: BulkheadOptions): Bulkhead {\n if (!this.bulkheads.has(options.name)) {\n const config: BulkheadConfig = { ...DEFAULT_CONFIG, ...options, name: options.name };\n this.bulkheads.set(options.name, new Bulkhead(config));\n }\n return this.bulkheads.get(options.name)!;\n }\n\n /** Per-client isolation — 5 concurrent, 20 queued */\n getForClient(clientId: string, endpoint?: string): Bulkhead {\n const name = endpoint ? `client:${clientId}:${endpoint}` : `client:${clientId}`;\n return this.getOrCreate({ name, maxConcurrentCalls: 5, maxQueueSize: 20 });\n }\n\n /** Service-level limiting — 20 concurrent, 200 queued */\n getForService(serviceName: string): Bulkhead {\n return this.getOrCreate({\n name: `service:${serviceName}`,\n maxConcurrentCalls: 20,\n maxQueueSize: 200,\n });\n }\n\n /** Database connection limiting — 15 concurrent, 150 queued */\n getForDatabase(schema: string): Bulkhead {\n return this.getOrCreate({\n name: `database:${schema}`,\n maxConcurrentCalls: 15,\n maxQueueSize: 150,\n });\n }\n\n /** External HTTP calls — 8 concurrent, 50 queued, 10s timeout */\n getForHttpExternal(serviceName: string): Bulkhead {\n return this.getOrCreate({\n name: `http:${serviceName}`,\n maxConcurrentCalls: 8,\n maxQueueSize: 50,\n queueTimeoutMs: 10000,\n });\n }\n\n getAllMetrics(): Record<string, BulkheadMetrics> {\n const metrics: Record<string, BulkheadMetrics> = {};\n for (const [name, bulkhead] of this.bulkheads) {\n metrics[name] = bulkhead.getMetrics();\n }\n return metrics;\n }\n\n /** Returns bulkheads at or above 80% active capacity */\n getOverloadedBulkheads(): BulkheadMetrics[] {\n const overloaded: BulkheadMetrics[] = [];\n for (const bulkhead of this.bulkheads.values()) {\n const m = bulkhead.getMetrics();\n if (m.activeCalls >= m.maxConcurrentCalls * 0.8) {\n overloaded.push(m);\n }\n }\n return overloaded;\n }\n\n resetAllMetrics(): void {\n for (const bulkhead of this.bulkheads.values()) {\n bulkhead.resetMetrics();\n }\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/bulkhead/bulkhead.ts","../src/bulkhead/bulkhead.registry.ts"],"names":[],"mappings":"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","file":"chunk-SRWDZPTJ.js","sourcesContent":["export interface BulkheadConfig {\n /** Max number of concurrent executions */\n maxConcurrentCalls: number;\n /** Max queue size for waiting tasks */\n maxQueueSize: number;\n /** Max time a task can wait in queue (ms) */\n queueTimeoutMs: number;\n /** Reject immediately when queue is full; if false, retries with backoff */\n rejectWhenFull: boolean;\n /** Identifier used in metrics and error messages */\n name: string;\n}\n\nexport interface BulkheadMetrics {\n name: string;\n activeCalls: number;\n queuedCalls: number;\n maxConcurrentCalls: number;\n maxQueueSize: number;\n totalCalls: number;\n successfulCalls: number;\n failedCalls: number;\n rejectedCalls: number;\n timedOutCalls: number;\n averageDurationMs: number;\n}\n\nexport class BulkheadRejectedError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'BulkheadRejectedError';\n }\n}\n\nexport class BulkheadTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'BulkheadTimeoutError';\n }\n}\n\nexport class Bulkhead {\n private activeCalls = 0;\n private nextId = 0;\n private queue: Array<{\n id: number;\n task: () => Promise<unknown>;\n resolve: (value: unknown) => void;\n reject: (reason: unknown) => void;\n queuedAt: number;\n }> = [];\n\n private totalCalls = 0;\n private successfulCalls = 0;\n private failedCalls = 0;\n private rejectedCalls = 0;\n private timedOutCalls = 0;\n private totalDurationMs = 0;\n\n constructor(private readonly config: BulkheadConfig) {}\n\n async execute<T>(task: () => Promise<T>): Promise<T> {\n const startTime = Date.now();\n this.totalCalls++;\n\n if (this.activeCalls < this.config.maxConcurrentCalls) {\n return this.runTask(task, startTime);\n }\n\n if (this.queue.length >= this.config.maxQueueSize) {\n if (this.config.rejectWhenFull) {\n this.rejectedCalls++;\n throw new BulkheadRejectedError(\n `Bulkhead '${this.config.name}' is full. ` +\n `Active: ${this.activeCalls}, Queue: ${this.queue.length}, Max: ${this.config.maxConcurrentCalls}`,\n );\n }\n return this.waitAndRetry(task, startTime);\n }\n\n const entryId = this.nextId++;\n return new Promise<T>((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n const index = this.queue.findIndex(item => item.id === entryId);\n if (index !== -1) this.queue.splice(index, 1);\n this.timedOutCalls++;\n reject(\n new BulkheadTimeoutError(\n `Bulkhead '${this.config.name}' timeout after ${this.config.queueTimeoutMs}ms`,\n ),\n );\n }, this.config.queueTimeoutMs);\n\n this.queue.push({\n id: entryId,\n task: task as () => Promise<unknown>,\n resolve: value => {\n clearTimeout(timeoutId);\n resolve(value as T);\n },\n reject: reason => {\n clearTimeout(timeoutId);\n reject(reason);\n },\n queuedAt: startTime,\n });\n\n this.processQueue();\n });\n }\n\n private async runTask<T>(task: () => Promise<T>, startTime: number): Promise<T> {\n this.activeCalls++;\n try {\n const result = await task();\n this.successfulCalls++;\n this.totalDurationMs += Date.now() - startTime;\n return result;\n } catch (error) {\n this.failedCalls++;\n throw error;\n } finally {\n this.activeCalls--;\n this.processQueue();\n }\n }\n\n private async waitAndRetry<T>(task: () => Promise<T>, startTime: number): Promise<T> {\n const maxRetries = 3;\n const baseDelay = 100;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n if (this.activeCalls < this.config.maxConcurrentCalls) {\n return this.runTask(task, startTime);\n }\n await new Promise(resolve => setTimeout(resolve, baseDelay * Math.pow(2, attempt - 1)));\n }\n\n this.rejectedCalls++;\n throw new BulkheadRejectedError(\n `Bulkhead '${this.config.name}' rejected after ${maxRetries} retries`,\n );\n }\n\n private processQueue(): void {\n while (this.activeCalls < this.config.maxConcurrentCalls && this.queue.length > 0) {\n const next = this.queue.shift();\n if (!next) break;\n\n const waitTime = Date.now() - next.queuedAt;\n if (waitTime > this.config.queueTimeoutMs) {\n next.reject(new BulkheadTimeoutError(`Task timed out after ${waitTime}ms in queue`));\n this.timedOutCalls++;\n continue;\n }\n\n this.activeCalls++;\n next\n .task()\n .then(result => {\n this.successfulCalls++;\n next.resolve(result);\n })\n .catch(error => {\n this.failedCalls++;\n next.reject(error);\n })\n .finally(() => {\n this.activeCalls--;\n this.processQueue();\n });\n }\n }\n\n getMetrics(): BulkheadMetrics {\n return {\n name: this.config.name,\n activeCalls: this.activeCalls,\n queuedCalls: this.queue.length,\n maxConcurrentCalls: this.config.maxConcurrentCalls,\n maxQueueSize: this.config.maxQueueSize,\n totalCalls: this.totalCalls,\n successfulCalls: this.successfulCalls,\n failedCalls: this.failedCalls,\n rejectedCalls: this.rejectedCalls,\n timedOutCalls: this.timedOutCalls,\n averageDurationMs:\n this.successfulCalls > 0 ? Math.round(this.totalDurationMs / this.successfulCalls) : 0,\n };\n }\n\n canAccept(): boolean {\n return (\n this.activeCalls < this.config.maxConcurrentCalls ||\n this.queue.length < this.config.maxQueueSize\n );\n }\n\n resetMetrics(): void {\n this.totalCalls = 0;\n this.successfulCalls = 0;\n this.failedCalls = 0;\n this.rejectedCalls = 0;\n this.timedOutCalls = 0;\n this.totalDurationMs = 0;\n }\n}\n","import { Bulkhead, BulkheadConfig, BulkheadMetrics } from './bulkhead.js';\n\nexport interface BulkheadOptions extends Partial<BulkheadConfig> {\n name: string;\n}\n\nconst DEFAULT_CONFIG: Omit<BulkheadConfig, 'name'> = {\n maxConcurrentCalls: 10,\n maxQueueSize: 100,\n queueTimeoutMs: 30000,\n rejectWhenFull: true,\n};\n\nexport class BulkheadRegistry {\n private readonly bulkheads = new Map<string, Bulkhead>();\n\n getOrCreate(options: BulkheadOptions): Bulkhead {\n if (!this.bulkheads.has(options.name)) {\n const config: BulkheadConfig = { ...DEFAULT_CONFIG, ...options, name: options.name };\n this.bulkheads.set(options.name, new Bulkhead(config));\n }\n return this.bulkheads.get(options.name)!;\n }\n\n /** Per-client isolation — 5 concurrent, 20 queued */\n getForClient(clientId: string, endpoint?: string): Bulkhead {\n const name = endpoint ? `client:${clientId}:${endpoint}` : `client:${clientId}`;\n return this.getOrCreate({ name, maxConcurrentCalls: 5, maxQueueSize: 20 });\n }\n\n /** Service-level limiting — 20 concurrent, 200 queued */\n getForService(serviceName: string): Bulkhead {\n return this.getOrCreate({\n name: `service:${serviceName}`,\n maxConcurrentCalls: 20,\n maxQueueSize: 200,\n });\n }\n\n /** Database connection limiting — 15 concurrent, 150 queued */\n getForDatabase(schema: string): Bulkhead {\n return this.getOrCreate({\n name: `database:${schema}`,\n maxConcurrentCalls: 15,\n maxQueueSize: 150,\n });\n }\n\n /** External HTTP calls — 8 concurrent, 50 queued, 10s timeout */\n getForHttpExternal(serviceName: string): Bulkhead {\n return this.getOrCreate({\n name: `http:${serviceName}`,\n maxConcurrentCalls: 8,\n maxQueueSize: 50,\n queueTimeoutMs: 10000,\n });\n }\n\n getAllMetrics(): Record<string, BulkheadMetrics> {\n const metrics: Record<string, BulkheadMetrics> = {};\n for (const [name, bulkhead] of this.bulkheads) {\n metrics[name] = bulkhead.getMetrics();\n }\n return metrics;\n }\n\n /** Returns bulkheads at or above 80% active capacity */\n getOverloadedBulkheads(): BulkheadMetrics[] {\n const overloaded: BulkheadMetrics[] = [];\n for (const bulkhead of this.bulkheads.values()) {\n const m = bulkhead.getMetrics();\n if (m.activeCalls >= m.maxConcurrentCalls * 0.8) {\n overloaded.push(m);\n }\n }\n return overloaded;\n }\n\n resetAllMetrics(): void {\n for (const bulkhead of this.bulkheads.values()) {\n bulkhead.resetMetrics();\n }\n }\n}\n"]}