ninja-reverse-proxy 1.0.4 → 1.0.6

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.
Files changed (525) hide show
  1. package/README.md +187 -139
  2. package/dist/balancer/contracts/balancer.interface.d.ts +8 -0
  3. package/dist/balancer/contracts/balancer.interface.d.ts.map +1 -0
  4. package/dist/balancer/contracts/balancer.interface.js +2 -0
  5. package/dist/balancer/contracts/balancer.interface.js.map +1 -0
  6. package/dist/balancer/contracts/context.types.d.ts +7 -0
  7. package/dist/balancer/contracts/context.types.d.ts.map +1 -0
  8. package/dist/balancer/contracts/context.types.js +2 -0
  9. package/dist/balancer/contracts/context.types.js.map +1 -0
  10. package/dist/balancer/contracts/strategy.interface.d.ts +6 -0
  11. package/dist/balancer/contracts/strategy.interface.d.ts.map +1 -0
  12. package/dist/balancer/contracts/strategy.interface.js +2 -0
  13. package/dist/balancer/contracts/strategy.interface.js.map +1 -0
  14. package/dist/balancer/core/load-balancer.d.ts +21 -0
  15. package/dist/balancer/core/load-balancer.d.ts.map +1 -0
  16. package/dist/balancer/core/load-balancer.js +188 -0
  17. package/dist/balancer/core/load-balancer.js.map +1 -0
  18. package/dist/balancer/core/strategy-registry.d.ts +8 -0
  19. package/dist/balancer/core/strategy-registry.d.ts.map +1 -0
  20. package/dist/balancer/core/strategy-registry.js +11 -0
  21. package/dist/balancer/core/strategy-registry.js.map +1 -0
  22. package/dist/balancer/factory/balancer.factory.d.ts +4 -0
  23. package/dist/balancer/factory/balancer.factory.d.ts.map +1 -0
  24. package/dist/balancer/factory/balancer.factory.js +35 -0
  25. package/dist/balancer/factory/balancer.factory.js.map +1 -0
  26. package/dist/balancer/index.d.ts +6 -0
  27. package/dist/balancer/index.d.ts.map +1 -0
  28. package/dist/balancer/index.js +3 -0
  29. package/dist/balancer/index.js.map +1 -0
  30. package/dist/balancer/strategies/adaptive-wrr.strategy.d.ts +8 -0
  31. package/dist/balancer/strategies/adaptive-wrr.strategy.d.ts.map +1 -0
  32. package/dist/balancer/strategies/adaptive-wrr.strategy.js +32 -0
  33. package/dist/balancer/strategies/adaptive-wrr.strategy.js.map +1 -0
  34. package/dist/balancer/strategies/consistent-hashing.strategy.d.ts +11 -0
  35. package/dist/balancer/strategies/consistent-hashing.strategy.d.ts.map +1 -0
  36. package/dist/balancer/strategies/consistent-hashing.strategy.js +45 -0
  37. package/dist/balancer/strategies/consistent-hashing.strategy.js.map +1 -0
  38. package/dist/balancer/strategies/ip-hash.strategy.d.ts +7 -0
  39. package/dist/balancer/strategies/ip-hash.strategy.d.ts.map +1 -0
  40. package/dist/balancer/strategies/ip-hash.strategy.js +24 -0
  41. package/dist/balancer/strategies/ip-hash.strategy.js.map +1 -0
  42. package/dist/balancer/strategies/least-connections.strategy.d.ts +6 -0
  43. package/dist/balancer/strategies/least-connections.strategy.d.ts.map +1 -0
  44. package/dist/balancer/strategies/least-connections.strategy.js +8 -0
  45. package/dist/balancer/strategies/least-connections.strategy.js.map +1 -0
  46. package/dist/balancer/strategies/least-response-time.strategy.d.ts +6 -0
  47. package/dist/balancer/strategies/least-response-time.strategy.d.ts.map +1 -0
  48. package/dist/balancer/strategies/least-response-time.strategy.js +8 -0
  49. package/dist/balancer/strategies/least-response-time.strategy.js.map +1 -0
  50. package/dist/balancer/strategies/power-of-two.strategy.d.ts +6 -0
  51. package/dist/balancer/strategies/power-of-two.strategy.d.ts.map +1 -0
  52. package/dist/balancer/strategies/power-of-two.strategy.js +17 -0
  53. package/dist/balancer/strategies/power-of-two.strategy.js.map +1 -0
  54. package/dist/balancer/strategies/random.strategy.d.ts +6 -0
  55. package/dist/balancer/strategies/random.strategy.d.ts.map +1 -0
  56. package/dist/balancer/strategies/random.strategy.js +8 -0
  57. package/dist/balancer/strategies/random.strategy.js.map +1 -0
  58. package/dist/balancer/strategies/resource-based.strategy.d.ts +7 -0
  59. package/dist/balancer/strategies/resource-based.strategy.d.ts.map +1 -0
  60. package/dist/balancer/strategies/resource-based.strategy.js +24 -0
  61. package/dist/balancer/strategies/resource-based.strategy.js.map +1 -0
  62. package/dist/balancer/strategies/round-robin.strategy.d.ts +7 -0
  63. package/dist/balancer/strategies/round-robin.strategy.d.ts.map +1 -0
  64. package/dist/balancer/strategies/round-robin.strategy.js +11 -0
  65. package/dist/balancer/strategies/round-robin.strategy.js.map +1 -0
  66. package/dist/balancer/strategies/sticky-sessions.strategy.d.ts +8 -0
  67. package/dist/balancer/strategies/sticky-sessions.strategy.d.ts.map +1 -0
  68. package/dist/balancer/strategies/sticky-sessions.strategy.js +20 -0
  69. package/dist/balancer/strategies/sticky-sessions.strategy.js.map +1 -0
  70. package/dist/balancer/strategies/weighted-least-connections.strategy.d.ts +6 -0
  71. package/dist/balancer/strategies/weighted-least-connections.strategy.d.ts.map +1 -0
  72. package/dist/balancer/strategies/weighted-least-connections.strategy.js +12 -0
  73. package/dist/balancer/strategies/weighted-least-connections.strategy.js.map +1 -0
  74. package/dist/balancer/strategies/weighted-round-robin.strategy.d.ts +8 -0
  75. package/dist/balancer/strategies/weighted-round-robin.strategy.d.ts.map +1 -0
  76. package/dist/balancer/strategies/weighted-round-robin.strategy.js +31 -0
  77. package/dist/balancer/strategies/weighted-round-robin.strategy.js.map +1 -0
  78. package/dist/cache/cache-manager.d.ts +25 -0
  79. package/dist/cache/cache-manager.d.ts.map +1 -0
  80. package/dist/cache/cache-manager.js +176 -0
  81. package/dist/cache/cache-manager.js.map +1 -0
  82. package/dist/cache/contracts/cache-config.interface.d.ts +25 -0
  83. package/dist/cache/contracts/cache-config.interface.d.ts.map +1 -0
  84. package/dist/cache/contracts/cache-config.interface.js +2 -0
  85. package/dist/cache/contracts/cache-config.interface.js.map +1 -0
  86. package/dist/cache/contracts/cache.interface.d.ts +8 -0
  87. package/dist/cache/contracts/cache.interface.d.ts.map +1 -0
  88. package/dist/cache/contracts/cache.interface.js +2 -0
  89. package/dist/cache/contracts/cache.interface.js.map +1 -0
  90. package/dist/cache/contracts/invalidator.interface.d.ts +6 -0
  91. package/dist/cache/contracts/invalidator.interface.d.ts.map +1 -0
  92. package/dist/cache/contracts/invalidator.interface.js +2 -0
  93. package/dist/cache/contracts/invalidator.interface.js.map +1 -0
  94. package/dist/cache/index.d.ts +3 -0
  95. package/dist/cache/index.d.ts.map +1 -0
  96. package/dist/cache/index.js +2 -0
  97. package/dist/cache/index.js.map +1 -0
  98. package/dist/cache/invalidation/debezium.invalidator.d.ts +8 -0
  99. package/dist/cache/invalidation/debezium.invalidator.d.ts.map +1 -0
  100. package/dist/cache/invalidation/debezium.invalidator.js +71 -0
  101. package/dist/cache/invalidation/debezium.invalidator.js.map +1 -0
  102. package/dist/cache/invalidation/pattern.invalidator.d.ts +9 -0
  103. package/dist/cache/invalidation/pattern.invalidator.d.ts.map +1 -0
  104. package/dist/cache/invalidation/pattern.invalidator.js +10 -0
  105. package/dist/cache/invalidation/pattern.invalidator.js.map +1 -0
  106. package/dist/cache/invalidation/tag.invalidator.d.ts +7 -0
  107. package/dist/cache/invalidation/tag.invalidator.d.ts.map +1 -0
  108. package/dist/cache/invalidation/tag.invalidator.js +17 -0
  109. package/dist/cache/invalidation/tag.invalidator.js.map +1 -0
  110. package/dist/cache/policies/cache-control.parser.d.ts +9 -0
  111. package/dist/cache/policies/cache-control.parser.d.ts.map +1 -0
  112. package/dist/cache/policies/cache-control.parser.js +18 -0
  113. package/dist/cache/policies/cache-control.parser.js.map +1 -0
  114. package/dist/cache/policies/key-builder.d.ts +11 -0
  115. package/dist/cache/policies/key-builder.d.ts.map +1 -0
  116. package/dist/cache/policies/key-builder.js +20 -0
  117. package/dist/cache/policies/key-builder.js.map +1 -0
  118. package/dist/cache/policies/stale-if-error.d.ts +4 -0
  119. package/dist/cache/policies/stale-if-error.d.ts.map +1 -0
  120. package/dist/cache/policies/stale-if-error.js +7 -0
  121. package/dist/cache/policies/stale-if-error.js.map +1 -0
  122. package/dist/cache/policies/stale-while-revalidate.d.ts +7 -0
  123. package/dist/cache/policies/stale-while-revalidate.d.ts.map +1 -0
  124. package/dist/cache/policies/stale-while-revalidate.js +13 -0
  125. package/dist/cache/policies/stale-while-revalidate.js.map +1 -0
  126. package/dist/cache/stores/hybrid.cache.d.ts +13 -0
  127. package/dist/cache/stores/hybrid.cache.d.ts.map +1 -0
  128. package/dist/cache/stores/hybrid.cache.js +36 -0
  129. package/dist/cache/stores/hybrid.cache.js.map +1 -0
  130. package/dist/cache/stores/in-memory-lru.d.ts +14 -0
  131. package/dist/cache/stores/in-memory-lru.d.ts.map +1 -0
  132. package/dist/cache/stores/in-memory-lru.js +41 -0
  133. package/dist/cache/stores/in-memory-lru.js.map +1 -0
  134. package/dist/cache/stores/redis.cache.d.ts +13 -0
  135. package/dist/cache/stores/redis.cache.d.ts.map +1 -0
  136. package/dist/cache/stores/redis.cache.js +39 -0
  137. package/dist/cache/stores/redis.cache.js.map +1 -0
  138. package/dist/config/config-schema.d.ts +3 -0
  139. package/dist/config/config-schema.d.ts.map +1 -0
  140. package/dist/config/config-schema.js +2 -0
  141. package/dist/config/config-schema.js.map +1 -0
  142. package/dist/config/config.d.ts +2 -0
  143. package/dist/config/config.d.ts.map +1 -0
  144. package/dist/config/config.js +2 -0
  145. package/dist/config/config.js.map +1 -0
  146. package/dist/config/config.loader.d.ts +266 -0
  147. package/dist/config/config.loader.d.ts.map +1 -0
  148. package/dist/config/config.loader.js +204 -0
  149. package/dist/config/config.loader.js.map +1 -0
  150. package/dist/config/index.d.ts +10 -0
  151. package/dist/config/index.d.ts.map +1 -0
  152. package/dist/config/index.js +10 -0
  153. package/dist/config/index.js.map +1 -0
  154. package/dist/config/schemas/admin.schema.d.ts +7 -0
  155. package/dist/config/schemas/admin.schema.d.ts.map +1 -0
  156. package/dist/config/schemas/admin.schema.js +11 -0
  157. package/dist/config/schemas/admin.schema.js.map +1 -0
  158. package/dist/config/schemas/balancer.schema.d.ts +32 -0
  159. package/dist/config/schemas/balancer.schema.d.ts.map +1 -0
  160. package/dist/config/schemas/balancer.schema.js +52 -0
  161. package/dist/config/schemas/balancer.schema.js.map +1 -0
  162. package/dist/config/schemas/cache.schema.d.ts +25 -0
  163. package/dist/config/schemas/cache.schema.d.ts.map +1 -0
  164. package/dist/config/schemas/cache.schema.js +57 -0
  165. package/dist/config/schemas/cache.schema.js.map +1 -0
  166. package/dist/config/schemas/discovery.schema.d.ts +8 -0
  167. package/dist/config/schemas/discovery.schema.d.ts.map +1 -0
  168. package/dist/config/schemas/discovery.schema.js +13 -0
  169. package/dist/config/schemas/discovery.schema.js.map +1 -0
  170. package/dist/config/schemas/observability.schema.d.ts +48 -0
  171. package/dist/config/schemas/observability.schema.d.ts.map +1 -0
  172. package/dist/config/schemas/observability.schema.js +56 -0
  173. package/dist/config/schemas/observability.schema.js.map +1 -0
  174. package/dist/config/schemas/ratelimit.schema.d.ts +36 -0
  175. package/dist/config/schemas/ratelimit.schema.d.ts.map +1 -0
  176. package/dist/config/schemas/ratelimit.schema.js +51 -0
  177. package/dist/config/schemas/ratelimit.schema.js.map +1 -0
  178. package/dist/config/schemas/resilience.schema.d.ts +36 -0
  179. package/dist/config/schemas/resilience.schema.d.ts.map +1 -0
  180. package/dist/config/schemas/resilience.schema.js +91 -0
  181. package/dist/config/schemas/resilience.schema.js.map +1 -0
  182. package/dist/config/schemas/server.schema.d.ts +512 -0
  183. package/dist/config/schemas/server.schema.d.ts.map +1 -0
  184. package/dist/config/schemas/server.schema.js +104 -0
  185. package/dist/config/schemas/server.schema.js.map +1 -0
  186. package/dist/config/server-schema.d.ts +2 -0
  187. package/dist/config/server-schema.d.ts.map +1 -0
  188. package/dist/config/server-schema.js +2 -0
  189. package/dist/config/server-schema.js.map +1 -0
  190. package/dist/{server-schema.d.ts → core/cluster/ipc.protocol.d.ts} +4 -8
  191. package/dist/core/cluster/ipc.protocol.d.ts.map +1 -0
  192. package/dist/{server-schema.js → core/cluster/ipc.protocol.js} +5 -4
  193. package/dist/core/cluster/ipc.protocol.js.map +1 -0
  194. package/dist/core/cluster/master.d.ts +10 -0
  195. package/dist/core/cluster/master.d.ts.map +1 -0
  196. package/dist/core/cluster/master.js +875 -0
  197. package/dist/core/cluster/master.js.map +1 -0
  198. package/dist/core/cluster/worker.d.ts +2 -0
  199. package/dist/core/cluster/worker.d.ts.map +1 -0
  200. package/dist/core/cluster/worker.js +313 -0
  201. package/dist/core/cluster/worker.js.map +1 -0
  202. package/dist/core/pipeline/context.d.ts +12 -0
  203. package/dist/core/pipeline/context.d.ts.map +1 -0
  204. package/dist/core/pipeline/context.js +10 -0
  205. package/dist/core/pipeline/context.js.map +1 -0
  206. package/dist/core/pipeline/middleware.pipeline.d.ts +8 -0
  207. package/dist/core/pipeline/middleware.pipeline.d.ts.map +1 -0
  208. package/dist/core/pipeline/middleware.pipeline.js +18 -0
  209. package/dist/core/pipeline/middleware.pipeline.js.map +1 -0
  210. package/dist/core/proxy/connection.pool.d.ts +6 -0
  211. package/dist/core/proxy/connection.pool.d.ts.map +1 -0
  212. package/dist/core/proxy/connection.pool.js +18 -0
  213. package/dist/core/proxy/connection.pool.js.map +1 -0
  214. package/dist/core/proxy/http.handler.d.ts +18 -0
  215. package/dist/core/proxy/http.handler.d.ts.map +1 -0
  216. package/dist/core/proxy/http.handler.js +35 -0
  217. package/dist/core/proxy/http.handler.js.map +1 -0
  218. package/dist/core/proxy/upstream.client.d.ts +12 -0
  219. package/dist/core/proxy/upstream.client.d.ts.map +1 -0
  220. package/dist/core/proxy/upstream.client.js +13 -0
  221. package/dist/core/proxy/upstream.client.js.map +1 -0
  222. package/dist/core/proxy/websocket.handler.d.ts +12 -0
  223. package/dist/core/proxy/websocket.handler.d.ts.map +1 -0
  224. package/dist/core/proxy/websocket.handler.js +77 -0
  225. package/dist/core/proxy/websocket.handler.js.map +1 -0
  226. package/dist/core/router/route.matcher.d.ts +7 -0
  227. package/dist/core/router/route.matcher.d.ts.map +1 -0
  228. package/dist/core/router/route.matcher.js +16 -0
  229. package/dist/core/router/route.matcher.js.map +1 -0
  230. package/dist/core/router/route.types.d.ts +17 -0
  231. package/dist/core/router/route.types.d.ts.map +1 -0
  232. package/dist/core/router/route.types.js +2 -0
  233. package/dist/core/router/route.types.js.map +1 -0
  234. package/dist/core/router/router.d.ts +8 -0
  235. package/dist/core/router/router.d.ts.map +1 -0
  236. package/dist/core/router/router.js +14 -0
  237. package/dist/core/router/router.js.map +1 -0
  238. package/dist/discovery/contracts/registry.interface.d.ts +13 -0
  239. package/dist/discovery/contracts/registry.interface.d.ts.map +1 -0
  240. package/dist/discovery/contracts/registry.interface.js +2 -0
  241. package/dist/discovery/contracts/registry.interface.js.map +1 -0
  242. package/dist/discovery/health/active.probe.d.ts +10 -0
  243. package/dist/discovery/health/active.probe.d.ts.map +1 -0
  244. package/dist/discovery/health/active.probe.js +46 -0
  245. package/dist/discovery/health/active.probe.js.map +1 -0
  246. package/dist/discovery/health/health.manager.d.ts +18 -0
  247. package/dist/discovery/health/health.manager.d.ts.map +1 -0
  248. package/dist/discovery/health/health.manager.js +76 -0
  249. package/dist/discovery/health/health.manager.js.map +1 -0
  250. package/dist/discovery/health/passive.probe.d.ts +12 -0
  251. package/dist/discovery/health/passive.probe.d.ts.map +1 -0
  252. package/dist/discovery/health/passive.probe.js +12 -0
  253. package/dist/discovery/health/passive.probe.js.map +1 -0
  254. package/dist/discovery/index.d.ts +7 -0
  255. package/dist/discovery/index.d.ts.map +1 -0
  256. package/dist/discovery/index.js +6 -0
  257. package/dist/discovery/index.js.map +1 -0
  258. package/dist/{Serviceregistry.d.ts → discovery/registry/dynamic.registry.d.ts} +7 -3
  259. package/dist/discovery/registry/dynamic.registry.d.ts.map +1 -0
  260. package/dist/discovery/registry/dynamic.registry.js +138 -0
  261. package/dist/discovery/registry/dynamic.registry.js.map +1 -0
  262. package/dist/discovery/target-node.d.ts +12 -0
  263. package/dist/discovery/target-node.d.ts.map +1 -0
  264. package/dist/discovery/target-node.js +8 -0
  265. package/dist/discovery/target-node.js.map +1 -0
  266. package/dist/index.js +52 -16
  267. package/dist/index.js.map +1 -1
  268. package/dist/middleware/auth.middleware.d.ts +3 -0
  269. package/dist/middleware/auth.middleware.d.ts.map +1 -0
  270. package/dist/middleware/auth.middleware.js +15 -0
  271. package/dist/middleware/auth.middleware.js.map +1 -0
  272. package/dist/middleware/body-limit.middleware.d.ts +3 -0
  273. package/dist/middleware/body-limit.middleware.d.ts.map +1 -0
  274. package/dist/middleware/body-limit.middleware.js +12 -0
  275. package/dist/middleware/body-limit.middleware.js.map +1 -0
  276. package/dist/middleware/cache.middleware.d.ts +4 -0
  277. package/dist/middleware/cache.middleware.d.ts.map +1 -0
  278. package/dist/middleware/cache.middleware.js +16 -0
  279. package/dist/middleware/cache.middleware.js.map +1 -0
  280. package/dist/middleware/circuit.middleware.d.ts +3 -0
  281. package/dist/middleware/circuit.middleware.d.ts.map +1 -0
  282. package/dist/middleware/circuit.middleware.js +11 -0
  283. package/dist/middleware/circuit.middleware.js.map +1 -0
  284. package/dist/middleware/cors.middleware.d.ts +3 -0
  285. package/dist/middleware/cors.middleware.d.ts.map +1 -0
  286. package/dist/middleware/cors.middleware.js +19 -0
  287. package/dist/middleware/cors.middleware.js.map +1 -0
  288. package/dist/middleware/logging.middleware.d.ts +3 -0
  289. package/dist/middleware/logging.middleware.d.ts.map +1 -0
  290. package/dist/middleware/logging.middleware.js +9 -0
  291. package/dist/middleware/logging.middleware.js.map +1 -0
  292. package/dist/middleware/rate-limit.middleware.d.ts +4 -0
  293. package/dist/middleware/rate-limit.middleware.d.ts.map +1 -0
  294. package/dist/middleware/rate-limit.middleware.js +29 -0
  295. package/dist/middleware/rate-limit.middleware.js.map +1 -0
  296. package/dist/middleware/tracing.middleware.d.ts +3 -0
  297. package/dist/middleware/tracing.middleware.d.ts.map +1 -0
  298. package/dist/middleware/tracing.middleware.js +18 -0
  299. package/dist/middleware/tracing.middleware.js.map +1 -0
  300. package/dist/observability/health/readiness.d.ts +14 -0
  301. package/dist/observability/health/readiness.d.ts.map +1 -0
  302. package/dist/observability/health/readiness.js +23 -0
  303. package/dist/observability/health/readiness.js.map +1 -0
  304. package/dist/observability/index.d.ts +12 -0
  305. package/dist/observability/index.d.ts.map +1 -0
  306. package/dist/observability/index.js +8 -0
  307. package/dist/observability/index.js.map +1 -0
  308. package/dist/observability/logger/logger.d.ts +19 -0
  309. package/dist/observability/logger/logger.d.ts.map +1 -0
  310. package/dist/observability/logger/logger.js +83 -0
  311. package/dist/observability/logger/logger.js.map +1 -0
  312. package/dist/observability/logger/tenant-log.streamer.d.ts +29 -0
  313. package/dist/observability/logger/tenant-log.streamer.d.ts.map +1 -0
  314. package/dist/observability/logger/tenant-log.streamer.js +80 -0
  315. package/dist/observability/logger/tenant-log.streamer.js.map +1 -0
  316. package/dist/observability/metrics/histogram.registry.d.ts +43 -0
  317. package/dist/observability/metrics/histogram.registry.d.ts.map +1 -0
  318. package/dist/observability/metrics/histogram.registry.js +87 -0
  319. package/dist/observability/metrics/histogram.registry.js.map +1 -0
  320. package/dist/observability/metrics/prometheus.exporter.d.ts +19 -0
  321. package/dist/observability/metrics/prometheus.exporter.d.ts.map +1 -0
  322. package/dist/observability/metrics/prometheus.exporter.js +107 -0
  323. package/dist/observability/metrics/prometheus.exporter.js.map +1 -0
  324. package/dist/observability/metrics/system.metrics.d.ts +10 -0
  325. package/dist/observability/metrics/system.metrics.d.ts.map +1 -0
  326. package/dist/observability/metrics/system.metrics.js +20 -0
  327. package/dist/observability/metrics/system.metrics.js.map +1 -0
  328. package/dist/observability/tracing/tracer.d.ts +16 -0
  329. package/dist/observability/tracing/tracer.d.ts.map +1 -0
  330. package/dist/observability/tracing/tracer.js +24 -0
  331. package/dist/observability/tracing/tracer.js.map +1 -0
  332. package/dist/ratelimit/algorithms/fixed-window.d.ts +6 -0
  333. package/dist/ratelimit/algorithms/fixed-window.d.ts.map +1 -0
  334. package/dist/ratelimit/algorithms/fixed-window.js +20 -0
  335. package/dist/ratelimit/algorithms/fixed-window.js.map +1 -0
  336. package/dist/ratelimit/algorithms/leaking-bucket.d.ts +5 -0
  337. package/dist/ratelimit/algorithms/leaking-bucket.d.ts.map +1 -0
  338. package/dist/ratelimit/algorithms/leaking-bucket.js +17 -0
  339. package/dist/ratelimit/algorithms/leaking-bucket.js.map +1 -0
  340. package/dist/ratelimit/algorithms/sliding-window-counter.d.ts +5 -0
  341. package/dist/ratelimit/algorithms/sliding-window-counter.d.ts.map +1 -0
  342. package/dist/ratelimit/algorithms/sliding-window-counter.js +24 -0
  343. package/dist/ratelimit/algorithms/sliding-window-counter.js.map +1 -0
  344. package/dist/ratelimit/algorithms/sliding-window-log.d.ts +5 -0
  345. package/dist/ratelimit/algorithms/sliding-window-log.d.ts.map +1 -0
  346. package/dist/ratelimit/algorithms/sliding-window-log.js +16 -0
  347. package/dist/ratelimit/algorithms/sliding-window-log.js.map +1 -0
  348. package/dist/ratelimit/algorithms/token-bucket.d.ts +5 -0
  349. package/dist/ratelimit/algorithms/token-bucket.d.ts.map +1 -0
  350. package/dist/ratelimit/algorithms/token-bucket.js +19 -0
  351. package/dist/ratelimit/algorithms/token-bucket.js.map +1 -0
  352. package/dist/ratelimit/contracts/limiter.interface.d.ts +11 -0
  353. package/dist/ratelimit/contracts/limiter.interface.d.ts.map +1 -0
  354. package/dist/ratelimit/contracts/limiter.interface.js +2 -0
  355. package/dist/ratelimit/contracts/limiter.interface.js.map +1 -0
  356. package/dist/ratelimit/contracts/storage.interface.d.ts +6 -0
  357. package/dist/ratelimit/contracts/storage.interface.d.ts.map +1 -0
  358. package/dist/ratelimit/contracts/storage.interface.js +2 -0
  359. package/dist/ratelimit/contracts/storage.interface.js.map +1 -0
  360. package/dist/ratelimit/index.d.ts +16 -0
  361. package/dist/ratelimit/index.d.ts.map +1 -0
  362. package/dist/ratelimit/index.js +12 -0
  363. package/dist/ratelimit/index.js.map +1 -0
  364. package/dist/ratelimit/policies/multi-dimension.policy.d.ts +14 -0
  365. package/dist/ratelimit/policies/multi-dimension.policy.d.ts.map +1 -0
  366. package/dist/ratelimit/policies/multi-dimension.policy.js +13 -0
  367. package/dist/ratelimit/policies/multi-dimension.policy.js.map +1 -0
  368. package/dist/ratelimit/policies/soft-limit.policy.d.ts +8 -0
  369. package/dist/ratelimit/policies/soft-limit.policy.d.ts.map +1 -0
  370. package/dist/ratelimit/policies/soft-limit.policy.js +16 -0
  371. package/dist/ratelimit/policies/soft-limit.policy.js.map +1 -0
  372. package/dist/ratelimit/rate-limiter.d.ts +48 -0
  373. package/dist/ratelimit/rate-limiter.d.ts.map +1 -0
  374. package/dist/ratelimit/rate-limiter.js +420 -0
  375. package/dist/ratelimit/rate-limiter.js.map +1 -0
  376. package/dist/ratelimit/storage/hybrid.store.d.ts +10 -0
  377. package/dist/ratelimit/storage/hybrid.store.d.ts.map +1 -0
  378. package/dist/ratelimit/storage/hybrid.store.js +58 -0
  379. package/dist/ratelimit/storage/hybrid.store.js.map +1 -0
  380. package/dist/ratelimit/storage/memory.store.d.ts +8 -0
  381. package/dist/ratelimit/storage/memory.store.d.ts.map +1 -0
  382. package/dist/ratelimit/storage/memory.store.js +20 -0
  383. package/dist/ratelimit/storage/memory.store.js.map +1 -0
  384. package/dist/ratelimit/storage/redis.store.d.ts +10 -0
  385. package/dist/ratelimit/storage/redis.store.d.ts.map +1 -0
  386. package/dist/ratelimit/storage/redis.store.js +20 -0
  387. package/dist/ratelimit/storage/redis.store.js.map +1 -0
  388. package/dist/resilience/bulkhead/bulkhead.d.ts +11 -0
  389. package/dist/resilience/bulkhead/bulkhead.d.ts.map +1 -0
  390. package/dist/resilience/bulkhead/bulkhead.js +38 -0
  391. package/dist/resilience/bulkhead/bulkhead.js.map +1 -0
  392. package/dist/resilience/circuit-breaker/adaptive.circuit-breaker.d.ts +17 -0
  393. package/dist/resilience/circuit-breaker/adaptive.circuit-breaker.d.ts.map +1 -0
  394. package/dist/resilience/circuit-breaker/adaptive.circuit-breaker.js +33 -0
  395. package/dist/resilience/circuit-breaker/adaptive.circuit-breaker.js.map +1 -0
  396. package/dist/resilience/circuit-breaker/circuit-breaker.manager.d.ts +9 -0
  397. package/dist/resilience/circuit-breaker/circuit-breaker.manager.d.ts.map +1 -0
  398. package/dist/resilience/circuit-breaker/circuit-breaker.manager.js +22 -0
  399. package/dist/resilience/circuit-breaker/circuit-breaker.manager.js.map +1 -0
  400. package/dist/resilience/circuit-breaker/classic.circuit-breaker.d.ts +15 -0
  401. package/dist/resilience/circuit-breaker/classic.circuit-breaker.d.ts.map +1 -0
  402. package/dist/resilience/circuit-breaker/classic.circuit-breaker.js +39 -0
  403. package/dist/resilience/circuit-breaker/classic.circuit-breaker.js.map +1 -0
  404. package/dist/resilience/circuit-breaker/contracts/circuit-breaker.interface.d.ts +6 -0
  405. package/dist/resilience/circuit-breaker/contracts/circuit-breaker.interface.d.ts.map +1 -0
  406. package/dist/resilience/circuit-breaker/contracts/circuit-breaker.interface.js +2 -0
  407. package/dist/resilience/circuit-breaker/contracts/circuit-breaker.interface.js.map +1 -0
  408. package/dist/resilience/circuit-breaker/states/closed.state.d.ts +5 -0
  409. package/dist/resilience/circuit-breaker/states/closed.state.d.ts.map +1 -0
  410. package/dist/resilience/circuit-breaker/states/closed.state.js +7 -0
  411. package/dist/resilience/circuit-breaker/states/closed.state.js.map +1 -0
  412. package/dist/resilience/circuit-breaker/states/half-open.state.d.ts +5 -0
  413. package/dist/resilience/circuit-breaker/states/half-open.state.d.ts.map +1 -0
  414. package/dist/resilience/circuit-breaker/states/half-open.state.js +7 -0
  415. package/dist/resilience/circuit-breaker/states/half-open.state.js.map +1 -0
  416. package/dist/resilience/circuit-breaker/states/open.state.d.ts +5 -0
  417. package/dist/resilience/circuit-breaker/states/open.state.d.ts.map +1 -0
  418. package/dist/resilience/circuit-breaker/states/open.state.js +7 -0
  419. package/dist/resilience/circuit-breaker/states/open.state.js.map +1 -0
  420. package/dist/resilience/index.d.ts +13 -0
  421. package/dist/resilience/index.d.ts.map +1 -0
  422. package/dist/resilience/index.js +11 -0
  423. package/dist/resilience/index.js.map +1 -0
  424. package/dist/resilience/retry/backoff/decorrelated-jitter.backoff.d.ts +2 -0
  425. package/dist/resilience/retry/backoff/decorrelated-jitter.backoff.d.ts.map +1 -0
  426. package/dist/resilience/retry/backoff/decorrelated-jitter.backoff.js +7 -0
  427. package/dist/resilience/retry/backoff/decorrelated-jitter.backoff.js.map +1 -0
  428. package/dist/resilience/retry/backoff/equal-jitter.backoff.d.ts +2 -0
  429. package/dist/resilience/retry/backoff/equal-jitter.backoff.d.ts.map +1 -0
  430. package/dist/resilience/retry/backoff/equal-jitter.backoff.js +6 -0
  431. package/dist/resilience/retry/backoff/equal-jitter.backoff.js.map +1 -0
  432. package/dist/resilience/retry/backoff/exponential.backoff.d.ts +2 -0
  433. package/dist/resilience/retry/backoff/exponential.backoff.d.ts.map +1 -0
  434. package/dist/resilience/retry/backoff/exponential.backoff.js +4 -0
  435. package/dist/resilience/retry/backoff/exponential.backoff.js.map +1 -0
  436. package/dist/resilience/retry/backoff/full-jitter.backoff.d.ts +2 -0
  437. package/dist/resilience/retry/backoff/full-jitter.backoff.d.ts.map +1 -0
  438. package/dist/resilience/retry/backoff/full-jitter.backoff.js +5 -0
  439. package/dist/resilience/retry/backoff/full-jitter.backoff.js.map +1 -0
  440. package/dist/resilience/retry/contracts/retry.interface.d.ts +5 -0
  441. package/dist/resilience/retry/contracts/retry.interface.d.ts.map +1 -0
  442. package/dist/resilience/retry/contracts/retry.interface.js +2 -0
  443. package/dist/resilience/retry/contracts/retry.interface.js.map +1 -0
  444. package/dist/resilience/retry/retry-budget.d.ts +17 -0
  445. package/dist/resilience/retry/retry-budget.d.ts.map +1 -0
  446. package/dist/resilience/retry/retry-budget.js +37 -0
  447. package/dist/resilience/retry/retry-budget.js.map +1 -0
  448. package/dist/resilience/retry/retry-handler.d.ts +7 -0
  449. package/dist/resilience/retry/retry-handler.d.ts.map +1 -0
  450. package/dist/resilience/retry/retry-handler.js +24 -0
  451. package/dist/resilience/retry/retry-handler.js.map +1 -0
  452. package/dist/server.d.ts +5 -9
  453. package/dist/server.d.ts.map +1 -1
  454. package/dist/server.js +12 -645
  455. package/dist/server.js.map +1 -1
  456. package/dist/types/balancer.types.d.ts +18 -0
  457. package/dist/types/balancer.types.d.ts.map +1 -0
  458. package/dist/types/balancer.types.js +2 -0
  459. package/dist/types/balancer.types.js.map +1 -0
  460. package/dist/types/common.types.d.ts +11 -0
  461. package/dist/types/common.types.d.ts.map +1 -0
  462. package/dist/types/common.types.js +2 -0
  463. package/dist/types/common.types.js.map +1 -0
  464. package/dist/types/config.types.d.ts +8 -0
  465. package/dist/types/config.types.d.ts.map +1 -0
  466. package/dist/types/config.types.js +2 -0
  467. package/dist/types/config.types.js.map +1 -0
  468. package/dist/types/http.types.d.ts +14 -0
  469. package/dist/types/http.types.d.ts.map +1 -0
  470. package/dist/types/http.types.js +2 -0
  471. package/dist/types/http.types.js.map +1 -0
  472. package/dist/types/index.d.ts +7 -0
  473. package/dist/types/index.d.ts.map +1 -0
  474. package/dist/types/index.js +2 -0
  475. package/dist/types/index.js.map +1 -0
  476. package/dist/types/resilience.types.d.ts +31 -0
  477. package/dist/types/resilience.types.d.ts.map +1 -0
  478. package/dist/types/resilience.types.js +2 -0
  479. package/dist/types/resilience.types.js.map +1 -0
  480. package/dist/types/upstream.types.d.ts +28 -0
  481. package/dist/types/upstream.types.d.ts.map +1 -0
  482. package/dist/types/upstream.types.js +2 -0
  483. package/dist/types/upstream.types.js.map +1 -0
  484. package/package.json +9 -3
  485. package/config.example.yaml +0 -99
  486. package/dist/Serviceregistry.d.ts.map +0 -1
  487. package/dist/Serviceregistry.js +0 -95
  488. package/dist/Serviceregistry.js.map +0 -1
  489. package/dist/auto-scaler.d.ts +0 -27
  490. package/dist/auto-scaler.d.ts.map +0 -1
  491. package/dist/auto-scaler.js +0 -133
  492. package/dist/auto-scaler.js.map +0 -1
  493. package/dist/cache.d.ts +0 -22
  494. package/dist/cache.d.ts.map +0 -1
  495. package/dist/cache.js +0 -112
  496. package/dist/cache.js.map +0 -1
  497. package/dist/config-schema.d.ts +0 -53
  498. package/dist/config-schema.d.ts.map +0 -1
  499. package/dist/config-schema.js +0 -78
  500. package/dist/config-schema.js.map +0 -1
  501. package/dist/config.d.ts +0 -47
  502. package/dist/config.d.ts.map +0 -1
  503. package/dist/config.js +0 -73
  504. package/dist/config.js.map +0 -1
  505. package/dist/health.d.ts +0 -5
  506. package/dist/health.d.ts.map +0 -1
  507. package/dist/health.js +0 -72
  508. package/dist/health.js.map +0 -1
  509. package/dist/loadBalancer.d.ts +0 -31
  510. package/dist/loadBalancer.d.ts.map +0 -1
  511. package/dist/loadBalancer.js +0 -171
  512. package/dist/loadBalancer.js.map +0 -1
  513. package/dist/metrics.d.ts +0 -14
  514. package/dist/metrics.d.ts.map +0 -1
  515. package/dist/metrics.js +0 -70
  516. package/dist/metrics.js.map +0 -1
  517. package/dist/rate-limiter.d.ts +0 -16
  518. package/dist/rate-limiter.d.ts.map +0 -1
  519. package/dist/rate-limiter.js +0 -59
  520. package/dist/rate-limiter.js.map +0 -1
  521. package/dist/server-schema.d.ts.map +0 -1
  522. package/dist/server-schema.js.map +0 -1
  523. package/monitoring/docker-compose.monitoring.yml +0 -22
  524. package/monitoring/prometheus.yml +0 -11
  525. package/monitoring/retry.t +0 -16
package/README.md CHANGED
@@ -1,186 +1,234 @@
1
- # Ninja Reverse Proxy
1
+ # 🛡️ Ninja Reverse Proxy
2
2
 
3
- A production-grade, backend-agnostic **Layer 7 Reverse Proxy** built from scratch in TypeScript and Node.js.
3
+ A production-grade, backend-agnostic **Layer 7 Reverse Proxy & Load Balancer** built from scratch in TypeScript and Node.js.
4
4
 
5
- Designed in the same philosophy as Nginx, Traefik, and HAProxy — configure it once, point it at any backend, and it handles everything else.
5
+ Designed in the same engineering philosophy as **NGINX, Envoy, and HAProxy** — configure it once, point it at any backend, and it handles enterprise-grade traffic distribution, load balancing, rate limiting, multi-tier caching, resilience patterns, and health monitoring automatically.
6
6
 
7
7
  ---
8
8
 
9
- ## Works with any HTTP backend
9
+ ## 🏛️ Master-Worker Architecture Overview
10
10
 
11
- node· Kubernetes Services · Docker Compose services · **Any service that speaks HTTP**
11
+ Ninja Reverse Proxy utilizes a highly performant **Master-Worker Cluster Architecture** that runs on all available CPU cores using Node.js Inter-Process Communication (IPC).
12
12
 
13
- The proxy never cares what technology runs behind the URLs. You configure upstreams in `config.yaml` and the proxy routes, balances, caches, rate-limits, and health-checks them automatically.
13
+ ```
14
+ +----------------------------+
15
+ | Client (WS/HTTPS) |
16
+ +--------------+-------------+
17
+ |
18
+
19
+ +----------------------------+
20
+ | Master Node (IPC Watchdog)|
21
+ +-------+------------+-------+
22
+ | |
23
+ (IPC Chans) (IPC Chans)
24
+ | |
25
+ +----------------v---+ +---v----------------+
26
+ | Worker 1 | | Worker 2 |
27
+ | - HTTP/WS Pipeline | | - HTTP/WS Pipeline |
28
+ | - L1 In-Memory LRU | | - L1 In-Memory LRU |
29
+ +-------+------------+ +---+----------------+
30
+ | |
31
+ (TCP/WSS Proxy) (TCP/WSS Proxy)
32
+ | |
33
+ +-------------v---------------------v-------------+
34
+ | Shared Distributed Tier: |
35
+ | - L2 Response Cache (Redis) |
36
+ | - Distributed Rate Limiter State (Redis Lua) |
37
+ | - Telemetry & Dynamic Service Registry |
38
+ | - Debezium CDC Invalidation Stream |
39
+ +------+------------------------------------+-----+
40
+ | |
41
+ ▼ ▼
42
+ +--------------+ +--------------+
43
+ | Upstream A | | Upstream B |
44
+ +--------------+ +--------------+
45
+ ```
14
46
 
15
47
  ---
16
48
 
17
- ## Features
18
-
19
- | Feature | Details |
20
- |---|---|
21
- | Cluster Architecture | Master/Worker pattern via Node.js cluster — uses all CPU cores |
22
- | Round-Robin Load Balancing | Equal request distribution across healthy upstreams |
23
- | Circuit Breaker | Marks upstreams DOWN after configurable failure threshold |
24
- | Redis Response Cache | GET response caching with configurable TTL |
25
- | Per-Route Rate Limiting | Sliding window rate limiter per client IP per route |
26
- | Service Registry | Backends self-register, deregister, and send heartbeats |
27
- | Continuous Health Checks | Every 10 seconds — auto-removes and auto-recovers upstreams |
28
- | HTTPS / TLS Termination | Full SSL at the proxy; all HTTP auto-redirected (301) |
29
- | Sticky Sessions | Cookie-based session affinity per upstream |
30
- | Retry Logic | Up to 2 retries on upstream failure, each on a different upstream |
31
- | Graceful Shutdown | Drains all connections on SIGTERM / SIGINT |
32
- | Hot Reload | Watches `config.yaml` and `config.d/` — zero-downtime config updates |
33
- | Admin API | Live stats for load balancer, cache, registry, auto scaler |
34
- | YAML Configuration | One file, fully validated with Zod — no source code changes needed |
49
+ ## 📐 Enterprise Design Patterns Implemented
35
50
 
36
- ---
51
+ 1. **Strategy Pattern (`ILoadBalancerStrategy`, `IRateLimiterAlgorithm`)**: Decouples algorithm selection from proxy execution. All 12 load balancing and 5 rate limiting algorithms implement common interfaces and are swapped at runtime.
52
+ 2. **Factory Pattern (`BalancerFactory`)**: Centralized instantiator that parses Zod schemas and generates configured load balancer strategies.
53
+ 3. **Dependency Inversion Principle (SOLID)**: Core proxy components depend strictly on abstractions (`ICache`, `IInvalidator`, `IServiceRegistry`), enabling seamless swapping between Memory, Redis, and Hybrid stores.
54
+ 4. **Koa/Express Onion Middleware Model**: Declarative pipeline (`RequestContext`, `MiddlewarePipeline`) executing CORS, Authentication, Tracing, Rate Limiting, Cache, and Circuit Breakers in non-blocking order.
55
+ 5. **Zero-Copy TCP Socket Tunneling**: Direct bidirectional piping (`clientSocket.pipe(targetSocket)`) for WebSocket and HTTPS connections.
37
56
 
38
- ## Quick Start
57
+ ---
39
58
 
40
- ### 1. Install globally
59
+ ## Core Systems & Features
41
60
 
42
- ```bash
43
- npm install -g ninja-reverse-proxy
44
- ```
61
+ ### 1. Advanced Load Balancing Engine (12 Strategies)
62
+ All load balancing strategies are dynamically validated using Zod schemas and instantiated via `BalancerFactory`:
45
63
 
46
- ### 2. Generate TLS certificates
64
+ * **Weighted Round-Robin (WRR)**: Smooth interleaved scheduling (NGINX style) using `currentWeight` adjustments.
65
+ * **Adaptive Weighted Round-Robin**: Automatically modifies weights in real time based on latency EWMA and request error rates.
66
+ * **Power of Two Choices (P2C)**: Pick two random healthy upstreams and route to the one with the lowest active connections ($O(1)$ efficiency).
67
+ * **Least Connections**: Route to the healthy upstream with the fewest active connections.
68
+ * **Weighted Least Connections**: Select using the `activeConnections / weight` ratio.
69
+ * **Least Response Time**: Route using latency EWMA (Exponentially Weighted Moving Average).
70
+ * **Consistent Hashing**: Distributed virtual node (150 replicas) ring mapping client IP to upstreams with minimum cache eviction.
71
+ * **IP Hash**: FNV-1a hash-modulo routing using client IP.
72
+ * **Sticky Sessions**: Cookie-based (`NINJA_ROUTE`) session affinity.
73
+ * **Resource-Based**: Telemetry-aware load routing using live CPU and memory metrics reported by sidecars.
74
+ * **Random Selection**: Fallback randomized distribution.
47
75
 
48
- ```bash
49
- openssl req -x509 -newkey rsa:4096 \
50
- -keyout key.pem -out cert.pem \
51
- -days 365 -nodes \
52
- -subj "/CN=localhost"
53
- ```
76
+ ---
54
77
 
55
- ### 3. Create your config file
78
+ ### 2. High-Performance Multi-Tier Caching & Invalidation
79
+ * **L1/L2 Hybrid Caching**: In-memory LRU cache (L1 RAM) backed by Redis (L2 Distributed Store) with automatic L1 warming & background synchronization.
80
+ * **Debezium CDC (Change Data Capture) Invalidation**: Subscribes to Redis Pub/Sub events from Debezium Server. Parses transaction log updates from SQL databases and MongoDB (supporting ObjectId `$oid` conversions) to invalidate cached paths instantly:
81
+ * *SQL Event Map*: `{"op":"u", "source":{"table":"orders"}, "after":{"id":999}}` $\rightarrow$ Invalidates `/api/orders/999`.
82
+ * *Mongo Event Map*: `{"op":"u", "source":{"collection":"orders"}, "after":{"_id":{"$oid":"60d5ec4b..."}}}` $\rightarrow$ Invalidates matching mapped paths.
83
+ * **Pattern & Tag-Based Invalidation**: Glob pattern matching (`PatternInvalidator`) and metadata grouping (`TagInvalidator`).
84
+ * **Cache Control Directives (`CacheControlParser`)**: Parses standards-compliant HTTP headers (`no-store`, `no-cache`, `max-age`, `s-maxage`, `private`).
85
+ * **Cache Normalization (`KeyBuilder`)**: Strips marketing query parameters (`utm_source`, `fbclid`) and handles `Vary` headers (`Accept-Encoding: gzip`).
86
+ * **Advanced Cache Policies**:
87
+ * `stale-while-revalidate`: Serves stale cache while triggering concurrent lock-free background revalidation (preventing Thundering Herd / Cache Stampedes).
88
+ * `stale-if-error`: Serves expired stale cache during upstream 5xx or network outages.
56
89
 
57
- ```yaml
58
- # config.yaml
59
- server:
60
- listen: 8080
61
- httpsPort: 8443
62
- workers: 2
90
+ ---
63
91
 
64
- loadBalancing:
65
- strategy: round-robin
66
- failureThreshold: 3
67
- recoveryTimeMs: 15000
68
- retry:
69
- maxAttempts: 2
70
- statusCodes: [502, 503, 504]
71
-
72
- upstreams:
73
- - id: my-api
74
- url: http://localhost:5000
75
- - id: my-api-2
76
- url: http://localhost:5001
77
-
78
- paths:
79
- - path: /
80
- upstream: [my-api, my-api-2]
81
-
82
- headers:
83
- - key: X-Forwarded-For
84
- value: client_ip
85
-
86
- cache:
87
- enabled: false
88
- host: redis
89
- port: 6379
90
- ttlSeconds: 60
91
- ```
92
+ ### 3. Distributed Rate Limiting & Throttling
93
+ * **5 Algorithms**: `token-bucket`, `leaking-bucket`, `fixed-window`, `sliding-window-log`, and `sliding-window-counter`.
94
+ * **Atomic Redis Lua Scripts**: Server-side Lua script execution preventing race conditions across distributed proxy nodes.
95
+ * **Soft Limit Warning & Burst Policy**: Dynamically increases burst limit ($1.5\times$ base limit) when current system load is below soft threshold.
96
+ * **Multi-Dimension Rules**: Independent rate limiting rules evaluated per IP, Route, API-Key, and Header combination (`rl:ip:/api/v1:10.0.0.1`).
92
97
 
93
- ### 4. Start the proxy
98
+ ---
94
99
 
95
- ```bash
96
- ninja-proxy --config config.yaml
97
- ```
100
+ ### 4. Advanced Fault Tolerance & Resilience
101
+ * **Classic Circuit Breaker**: Standard state machine (`CLOSED` $\rightarrow$ `OPEN` $\rightarrow$ `HALF_OPEN`) based on consecutive failure thresholds.
102
+ * **Google SRE EWMA Adaptive Circuit Breaker**: Rate-based shedding model using Google SRE probability math:
103
+ $$P = \frac{\text{requests} - K \times \text{accepts}}{\text{requests} + 1}$$
104
+ * **Bulkhead Pattern**: Concurrency isolation slots preventing slow upstreams from exhausting worker thread pools.
105
+ * **4 Jitter Backoff Algorithms**:
106
+ * `ExponentialBackoff`: Deterministic doubling.
107
+ * `FullJitterBackoff`: $Random(0, min(cap, base \times 2^{attempt}))$.
108
+ * `EqualJitterBackoff`: $\frac{temp}{2} + Random(0, \frac{temp}{2})$.
109
+ * `DecorrelatedJitterBackoff`: $Random(base, previousSleep \times 3)$.
110
+ * **Retry Budgets**: Capped retry allowance (e.g. max 15% retry budget) to prevent upstream retry storms.
98
111
 
99
- ### 5. Test it
112
+ ---
100
113
 
101
- ```bash
102
- curl -k https://localhost:8443/
103
- curl -k https://localhost:8443/__lb-stats
104
- ```
114
+ ### 5. Dynamic Service Registry & Health Probes
115
+ * **Dynamic Self-Registration REST API**: Upstreams can self-register, heartbeat, and deregister (`/__registry/register`, `heartbeat`, `deregister`).
116
+ * **Disk Snapshot Persistence**: Automatic rehydration of services from `registry.json` snapshot backups on proxy restart.
117
+ * **Dual Health Probes**: Active HTTP ping probes (`checkUpstream`) + Passive background failure monitors.
105
118
 
106
119
  ---
107
120
 
108
- ## Dynamic Service Registry
109
-
110
- Backends can self-register at runtime without touching `config.yaml`:
121
+ ### 6. Observability, Telemetry & Multi-Tenant Logging
122
+ * **Prometheus Exposition Endpoint (`/metrics`)**: Exposes latency percentiles (P50, P95, P99), RPS, active connections, and circuit breaker status.
123
+ * **5 Auto-Provisioned Grafana Dashboards**: Visual monitoring dashboards for Proxy Overview, Load Balancers, Cache, Circuit Breakers, and Rate Limiters.
124
+ * **Tenant Log Streamer**: Webhook log streaming engine dispatching structured JSON access logs to tenant HTTP webhooks.
111
125
 
112
- ```bash
113
- # Register a new upstream dynamically
114
- curl -X POST -H "Content-Type: application/json" \
115
- -d '{"id":"my-service","url":"http://localhost:3000"}' \
116
- http://localhost:8080/__registry/register
126
+ ---
117
127
 
118
- # Send a heartbeat
119
- curl -X PUT http://localhost:8080/__registry/heartbeat/my-service
128
+ ## 📄 Complete Production `config.yaml` Reference
120
129
 
121
- # Deregister
122
- curl -X DELETE http://localhost:8080/__registry/deregister/my-service
130
+ ```yaml
131
+ server:
132
+ host: "0.0.0.0"
133
+ port: 8080
134
+ httpsPort: 8443
135
+ workers: 4
136
+
137
+ upstreams:
138
+ - id: "app-node-1"
139
+ url: "http://127.0.0.1:3000"
140
+ weight: 3
141
+ maxConnections: 500
142
+ healthPath: "/health"
143
+ - id: "app-node-2"
144
+ url: "http://127.0.0.1:3001"
145
+ weight: 1
146
+ maxConnections: 500
147
+ healthPath: "/health"
148
+
149
+ loadBalancing:
150
+ strategy: "weighted-round-robin" # Options: round-robin, least-connections, power-of-two, consistent-hashing, adaptive-wrr, resource-based
151
+ stickyCookieName: "NINJA_ROUTE"
152
+
153
+ rateLimit:
154
+ enabled: true
155
+ storage: "memory" # Options: memory, redis, hybrid
156
+ algorithm: "token-bucket" # Options: fixed-window, sliding-window-log, sliding-window-counter, token-bucket, leaking-bucket
157
+ windowMs: 60000
158
+ maxRequests: 1000
159
+ softLimit: true
160
+ dimensions:
161
+ - dimension: "ip"
162
+ maxRequests: 100
163
+ windowMs: 60000
164
+ - dimension: "api-key"
165
+ maxRequests: 500
166
+ windowMs: 60000
167
+
168
+ cache:
169
+ enabled: true
170
+ ttlSeconds: 60
171
+ l1MaxSize: 1000
172
+ staleWhileRevalidate: true
173
+ staleIfError: true
174
+ debezium:
175
+ enabled: true
176
+ channel: "debezium-cdc-events"
177
+ mappings:
178
+ - table: "orders"
179
+ pathPattern: "/api/orders/{id}"
180
+
181
+ resilience:
182
+ circuitBreaker:
183
+ mode: "adaptive" # Options: classic, adaptive
184
+ failureThreshold: 3
185
+ recoveryTimeMs: 10000
186
+ bulkhead:
187
+ maxConcurrent: 100
188
+ retry:
189
+ maxAttempts: 3
190
+ backoff: "full-jitter" # Options: exponential, full-jitter, equal-jitter, decorrelated-jitter
191
+
192
+ observability:
193
+ metrics:
194
+ enabled: true
195
+ path: "/metrics"
123
196
  ```
124
197
 
125
198
  ---
126
199
 
127
- ## Multi-Tenant Config (Nginx-style)
128
-
129
- Drop extra config files into a `config.d/` folder — the proxy merges them automatically with zero downtime:
200
+ ## 🧪 Testing & Verification Suites
130
201
 
202
+ ### 1. Run Complete 63-Unit & Integration Test Suite
131
203
  ```bash
132
- mkdir config.d
133
-
134
- # Each tenant/app gets their own isolated file
135
- echo "
136
- server:
137
- upstreams:
138
- - id: tenant-a
139
- url: http://localhost:4000
140
- paths:
141
- - path: /tenant-a
142
- upstream: [tenant-a]
143
- " > config.d/tenant-a.yaml
204
+ node node_modules/typescript/bin/tsc -p tsconfig.test.json && node --test dist-test/tests/unit/**/*.js dist-test/tests/integration/*.js
144
205
  ```
145
206
 
146
- The proxy hot-reloads `config.d/` automatically whenever a file is added or changed.
147
-
148
- ---
149
-
150
- ## Admin API
207
+ ### 2. Run 30-Feature Audit & Report Generator
208
+ ```bash
209
+ node node_modules/typescript/bin/tsc -p tsconfig.test.json && node dist-test/scripts/verify-all-features.js
210
+ ```
211
+ *(Generates markdown proof report in `results/interview_proof_report.md`)*
151
212
 
152
- | Endpoint | Method | Description |
153
- |---|---|---|
154
- | `/__lb-stats` | GET | Load balancer stats + healthy upstreams |
155
- | `/__cache-stats` | GET | Redis cache hit/miss stats |
156
- | `/__registry` | GET | All registered services |
157
- | `/__registry/register` | POST | Register a new upstream |
158
- | `/__registry/deregister/:id` | DELETE | Deregister an upstream |
159
- | `/__registry/heartbeat/:id` | PUT | Upstream heartbeat ping |
213
+ ### 3. Run Production High-RPS Benchmark
214
+ ```bash
215
+ npx tsx scripts/benchmark.ts https://localhost:8443/ 1000 20
216
+ ```
160
217
 
161
218
  ---
162
219
 
163
- ## Configuration Reference
220
+ ## 📦 Build & NPM Publish
164
221
 
165
- | Field | Default | Description |
166
- |---|---|---|
167
- | `server.listen` | `8080` | HTTP port — redirects all traffic to HTTPS |
168
- | `server.httpsPort` | `8443` | HTTPS port — main entry point |
169
- | `server.workers` | `2` | Set to your CPU core count |
170
- | `loadBalancing.strategy` | `round-robin` | `round-robin` \| `least-connections` \| `ip-hash` \| `random` |
171
- | `loadBalancing.failure0Threshold` | `3` | Mark upstream DOWN after N consecutive failures |
172
- | `loadBalancing.recoveryTimeMs` | `15000` | Retry a DOWN upstream after N ms |
173
- | `cache.enabled` | `false` | Enable Redis GET response caching |
174
- | `cache.ttlSeconds` | `60` | Cache TTL in seconds |
175
-
176
- ---
177
-
178
- ## Repository
222
+ ```bash
223
+ # Build TypeScript bundle to dist/
224
+ pnpm run build
179
225
 
180
- [github.com/praveenkumar-co/reverse-proxy](https://github.com/praveenkumar-co/reverse-proxy)
226
+ # Publish to npmjs.com
227
+ npm publish
228
+ ```
181
229
 
182
230
  ---
183
231
 
184
- ## License
232
+ ## 📜 License
185
233
 
186
- MIT
234
+ MIT License © 2026 Praveen Kumar
@@ -0,0 +1,8 @@
1
+ export interface IBalancer {
2
+ pickFiltered(healthyIds: Set<string>, clientIp?: string, attemptedIds?: Set<string>, cookies?: string): string | null;
3
+ recordSuccess(id: string, latencyMs?: number): void;
4
+ recordFailure(id: string): void;
5
+ setHealthy(id: string, healthy: boolean): void;
6
+ getStats(): Record<string, any>;
7
+ }
8
+ //# sourceMappingURL=balancer.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"balancer.interface.d.ts","sourceRoot":"","sources":["../../../src/balancer/contracts/balancer.interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,YAAY,CACV,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,EACvB,QAAQ,CAAC,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAC1B,OAAO,CAAC,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAAC;IACjB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpD,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/C,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACjC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=balancer.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"balancer.interface.js","sourceRoot":"","sources":["../../../src/balancer/contracts/balancer.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ export interface PickContext {
2
+ clientIp?: string;
3
+ attemptedIds?: Set<string>;
4
+ cookies?: string;
5
+ headers?: Record<string, string>;
6
+ }
7
+ //# sourceMappingURL=context.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.types.d.ts","sourceRoot":"","sources":["../../../src/balancer/contracts/context.types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=context.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.types.js","sourceRoot":"","sources":["../../../src/balancer/contracts/context.types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ import type { UpstreamState } from "../../types/upstream.types.js";
2
+ export interface IStrategy {
3
+ pick(candidates: UpstreamState[], clientIp?: string, cookies?: string): UpstreamState | null;
4
+ onUpstreamsChanged?(upstreams: UpstreamState[]): void;
5
+ }
6
+ //# sourceMappingURL=strategy.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strategy.interface.d.ts","sourceRoot":"","sources":["../../../src/balancer/contracts/strategy.interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAEnE,MAAM,WAAW,SAAS;IACxB,IAAI,CACF,UAAU,EAAE,aAAa,EAAE,EAC3B,QAAQ,CAAC,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,GACf,aAAa,GAAG,IAAI,CAAC;IACxB,kBAAkB,CAAC,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;CACvD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=strategy.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strategy.interface.js","sourceRoot":"","sources":["../../../src/balancer/contracts/strategy.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,21 @@
1
+ import type { LoadBalancerOptions } from "../../types/balancer.types.js";
2
+ import type { IStrategy } from "../contracts/strategy.interface.js";
3
+ export declare class LoadBalancer {
4
+ private strategy;
5
+ private ewmaAlpha;
6
+ private slowStartSeconds;
7
+ private circuitBreakerConfig;
8
+ private states;
9
+ constructor(options: LoadBalancerOptions, strategy: IStrategy);
10
+ addUpstream(id: string, url: string, weight?: number, maxConnections?: number): void;
11
+ removeUpstream(id: string): void;
12
+ setHealthy(id: string, healthy: boolean): void;
13
+ incrementConnection(id: string): void;
14
+ releaseConnection(id: string): void;
15
+ recordSuccess(id: string, latencyMs?: number): void;
16
+ recordFailure(id: string): void;
17
+ pickFiltered(healthyIds: Set<string>, clientIp?: string, attemptedIds?: Set<string>, cookies?: string): string | null;
18
+ getStats(): any[];
19
+ private notifyStrategy;
20
+ }
21
+ //# sourceMappingURL=load-balancer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-balancer.d.ts","sourceRoot":"","sources":["../../../src/balancer/core/load-balancer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAMzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAC;AAEpE,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,oBAAoB,CAAM;IAClC,OAAO,CAAC,MAAM,CAAoC;gBAEtC,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,SAAS;IAoCtD,WAAW,CAChB,EAAE,EAAE,MAAM,EACV,GAAG,EAAE,MAAM,EACX,MAAM,SAAI,EACV,cAAc,CAAC,EAAE,MAAM;IA2BlB,cAAc,CAAC,EAAE,EAAE,MAAM;IAKzB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAyBvC,mBAAmB,CAAC,EAAE,EAAE,MAAM;IAI9B,iBAAiB,CAAC,EAAE,EAAE,MAAM;IAI5B,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,SAAI;IAuCvC,aAAa,CAAC,EAAE,EAAE,MAAM;IAsBxB,YAAY,CACjB,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,EACvB,QAAQ,CAAC,EAAE,MAAM,EACjB,YAAY,cAAoB,EAChC,OAAO,CAAC,EAAE,MAAM,GACf,MAAM,GAAG,IAAI;IAqCT,QAAQ,IAAI,GAAG,EAAE;IAsBxB,OAAO,CAAC,cAAc;CAKvB"}
@@ -0,0 +1,188 @@
1
+ import { logger } from "../../observability/logger/logger.js";
2
+ import { circuitBreakerManager } from "../../resilience/circuit-breaker/circuit-breaker.manager.js";
3
+ import { ClassicCircuitBreaker } from "../../resilience/circuit-breaker/classic.circuit-breaker.js";
4
+ import { AdaptiveCircuitBreaker } from "../../resilience/circuit-breaker/adaptive.circuit-breaker.js";
5
+ export class LoadBalancer {
6
+ strategy;
7
+ ewmaAlpha;
8
+ slowStartSeconds;
9
+ circuitBreakerConfig;
10
+ states = new Map();
11
+ constructor(options, strategy) {
12
+ this.strategy = strategy;
13
+ this.ewmaAlpha = options.ewmaAlpha ?? 0.1;
14
+ this.slowStartSeconds = options.slowStartSeconds ?? 30;
15
+ this.circuitBreakerConfig = options.circuitBreaker ?? {
16
+ mode: "classic",
17
+ failureThreshold: options.failureThreshold ?? 3,
18
+ recoveryTimeMs: options.recoveryTimeMs ?? 15000,
19
+ K: 2,
20
+ windowMs: 10000,
21
+ };
22
+ for (const upstream of options.upstreams) {
23
+ this.states.set(upstream.id, {
24
+ id: upstream.id,
25
+ weight: upstream.weight ?? 1,
26
+ activeConnections: 0,
27
+ failures: 0,
28
+ state: "CLOSED",
29
+ lastFailureTime: 0,
30
+ responseTime: 10,
31
+ healthy: true,
32
+ requests: 0,
33
+ accepts: 0,
34
+ slowStartEndTime: 0,
35
+ maxConnections: upstream.maxConnections,
36
+ currentWeight: 0,
37
+ });
38
+ circuitBreakerManager.getOrCreate(upstream.id, this.circuitBreakerConfig.mode, this.circuitBreakerConfig);
39
+ }
40
+ this.notifyStrategy();
41
+ }
42
+ addUpstream(id, url, weight = 1, maxConnections) {
43
+ if (this.states.has(id))
44
+ return;
45
+ this.states.set(id, {
46
+ id,
47
+ url,
48
+ activeConnections: 0,
49
+ failures: 0,
50
+ lastFailureTime: 0,
51
+ state: "CLOSED",
52
+ healthy: true,
53
+ weight,
54
+ responseTime: 10,
55
+ totalBytes: 0,
56
+ requests: 0,
57
+ accepts: 0,
58
+ slowStartEndTime: 0,
59
+ maxConnections,
60
+ currentWeight: 0,
61
+ });
62
+ circuitBreakerManager.getOrCreate(id, this.circuitBreakerConfig.mode, this.circuitBreakerConfig);
63
+ this.notifyStrategy();
64
+ }
65
+ removeUpstream(id) {
66
+ if (this.states.delete(id)) {
67
+ this.notifyStrategy();
68
+ }
69
+ }
70
+ setHealthy(id, healthy) {
71
+ const s = this.states.get(id);
72
+ if (!s)
73
+ return;
74
+ if (s.healthy !== healthy) {
75
+ logger.info("LoadBalancer", `Upstream health changed: ${id} -> ${healthy ? "HEALTHY" : "UNHEALTHY"}`);
76
+ s.healthy = healthy;
77
+ if (healthy) {
78
+ const cb = circuitBreakerManager.getOrCreate(id, this.circuitBreakerConfig.mode, this.circuitBreakerConfig);
79
+ if (cb instanceof ClassicCircuitBreaker &&
80
+ cb.getState() === "OPEN") {
81
+ cb.recordSuccess(0);
82
+ }
83
+ s.slowStartEndTime = Date.now() + this.slowStartSeconds * 1000;
84
+ }
85
+ }
86
+ }
87
+ incrementConnection(id) {
88
+ const s = this.states.get(id);
89
+ if (s)
90
+ s.activeConnections++;
91
+ }
92
+ releaseConnection(id) {
93
+ const s = this.states.get(id);
94
+ if (s && s.activeConnections > 0)
95
+ s.activeConnections--;
96
+ }
97
+ recordSuccess(id, latencyMs = 0) {
98
+ const s = this.states.get(id);
99
+ if (!s)
100
+ return;
101
+ s.responseTime =
102
+ this.ewmaAlpha * latencyMs + (1 - this.ewmaAlpha) * s.responseTime;
103
+ const cb = circuitBreakerManager.getOrCreate(id, this.circuitBreakerConfig.mode, this.circuitBreakerConfig);
104
+ const prevState = cb instanceof ClassicCircuitBreaker ? cb.getState() : "CLOSED";
105
+ cb.recordSuccess(latencyMs);
106
+ const postState = cb instanceof ClassicCircuitBreaker ? cb.getState() : "CLOSED";
107
+ if (cb instanceof ClassicCircuitBreaker &&
108
+ (prevState === "OPEN" || prevState === "HALF_OPEN") &&
109
+ postState === "CLOSED") {
110
+ logger.info("CircuitBreaker", `${id} restored to CLOSED state`);
111
+ s.slowStartEndTime = 0;
112
+ let totalWeight = 0;
113
+ for (const [, state] of this.states) {
114
+ const peerCb = circuitBreakerManager.getOrCreate(state.id, this.circuitBreakerConfig.mode, this.circuitBreakerConfig);
115
+ const peerOpen = peerCb instanceof ClassicCircuitBreaker &&
116
+ peerCb.getState() === "OPEN";
117
+ if (state.healthy && !peerOpen) {
118
+ totalWeight += state.weight;
119
+ }
120
+ }
121
+ s.currentWeight -= totalWeight;
122
+ }
123
+ }
124
+ recordFailure(id) {
125
+ const s = this.states.get(id);
126
+ if (!s)
127
+ return;
128
+ const cb = circuitBreakerManager.getOrCreate(id, this.circuitBreakerConfig.mode, this.circuitBreakerConfig);
129
+ const prevState = cb instanceof ClassicCircuitBreaker ? cb.getState() : "CLOSED";
130
+ cb.recordFailure();
131
+ const postState = cb instanceof ClassicCircuitBreaker ? cb.getState() : "CLOSED";
132
+ if (cb instanceof ClassicCircuitBreaker &&
133
+ prevState !== "OPEN" &&
134
+ postState === "OPEN") {
135
+ logger.warn("CircuitBreaker", `${id} tripped to OPEN state`);
136
+ }
137
+ }
138
+ pickFiltered(healthyIds, clientIp, attemptedIds = new Set(), cookies) {
139
+ const candidates = [];
140
+ for (const [id, s] of this.states.entries()) {
141
+ if (!healthyIds.has(id) || !s.healthy)
142
+ continue;
143
+ if (attemptedIds.has(id))
144
+ continue;
145
+ const cb = circuitBreakerManager.getOrCreate(id, this.circuitBreakerConfig.mode, this.circuitBreakerConfig);
146
+ if (!cb.isAllowed())
147
+ continue;
148
+ if (s.maxConnections !== undefined &&
149
+ s.activeConnections >= s.maxConnections) {
150
+ continue;
151
+ }
152
+ candidates.push(s);
153
+ }
154
+ if (candidates.length === 0)
155
+ return null;
156
+ const halfOpenCandidates = candidates.filter((s) => {
157
+ const cb = circuitBreakerManager.getOrCreate(s.id, this.circuitBreakerConfig.mode, this.circuitBreakerConfig);
158
+ return (cb instanceof ClassicCircuitBreaker && cb.getState() === "HALF_OPEN");
159
+ });
160
+ if (halfOpenCandidates.length > 0) {
161
+ return halfOpenCandidates[0].id;
162
+ }
163
+ const chosen = this.strategy.pick(candidates, clientIp, cookies);
164
+ return chosen ? chosen.id : null;
165
+ }
166
+ getStats() {
167
+ const list = [];
168
+ for (const [id, s] of this.states.entries()) {
169
+ const cb = circuitBreakerManager.getOrCreate(id, this.circuitBreakerConfig.mode, this.circuitBreakerConfig);
170
+ list.push({
171
+ id,
172
+ activeConnections: s.activeConnections,
173
+ failures: cb instanceof ClassicCircuitBreaker ? cb.getFailures() : 0,
174
+ state: cb instanceof ClassicCircuitBreaker ? cb.getState() : "CLOSED",
175
+ responseTime: s.responseTime,
176
+ healthy: s.healthy,
177
+ ...(cb instanceof AdaptiveCircuitBreaker ? { adaptiveStats: cb.getStats() } : {}),
178
+ });
179
+ }
180
+ return list;
181
+ }
182
+ notifyStrategy() {
183
+ if (this.strategy.onUpstreamsChanged) {
184
+ this.strategy.onUpstreamsChanged([...this.states.values()]);
185
+ }
186
+ }
187
+ }
188
+ //# sourceMappingURL=load-balancer.js.map