@aster-rpc/aster 0.1.2

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 (233) hide show
  1. package/dist/capabilities.d.ts +26 -0
  2. package/dist/capabilities.d.ts.map +1 -0
  3. package/dist/capabilities.js +29 -0
  4. package/dist/capabilities.js.map +1 -0
  5. package/dist/client.d.ts +65 -0
  6. package/dist/client.d.ts.map +1 -0
  7. package/dist/client.js +108 -0
  8. package/dist/client.js.map +1 -0
  9. package/dist/codec.d.ts +156 -0
  10. package/dist/codec.d.ts.map +1 -0
  11. package/dist/codec.js +477 -0
  12. package/dist/codec.js.map +1 -0
  13. package/dist/config.d.ts +102 -0
  14. package/dist/config.d.ts.map +1 -0
  15. package/dist/config.js +454 -0
  16. package/dist/config.js.map +1 -0
  17. package/dist/contract/identity.d.ts +115 -0
  18. package/dist/contract/identity.d.ts.map +1 -0
  19. package/dist/contract/identity.js +188 -0
  20. package/dist/contract/identity.js.map +1 -0
  21. package/dist/contract/manifest.d.ts +77 -0
  22. package/dist/contract/manifest.d.ts.map +1 -0
  23. package/dist/contract/manifest.js +127 -0
  24. package/dist/contract/manifest.js.map +1 -0
  25. package/dist/contract/publication.d.ts +71 -0
  26. package/dist/contract/publication.d.ts.map +1 -0
  27. package/dist/contract/publication.js +85 -0
  28. package/dist/contract/publication.js.map +1 -0
  29. package/dist/decorators.d.ts +139 -0
  30. package/dist/decorators.d.ts.map +1 -0
  31. package/dist/decorators.js +175 -0
  32. package/dist/decorators.js.map +1 -0
  33. package/dist/dynamic.d.ts +61 -0
  34. package/dist/dynamic.d.ts.map +1 -0
  35. package/dist/dynamic.js +147 -0
  36. package/dist/dynamic.js.map +1 -0
  37. package/dist/framing.d.ts +74 -0
  38. package/dist/framing.d.ts.map +1 -0
  39. package/dist/framing.js +162 -0
  40. package/dist/framing.js.map +1 -0
  41. package/dist/health.d.ts +127 -0
  42. package/dist/health.d.ts.map +1 -0
  43. package/dist/health.js +236 -0
  44. package/dist/health.js.map +1 -0
  45. package/dist/index.d.ts +67 -0
  46. package/dist/index.d.ts.map +1 -0
  47. package/dist/index.js +101 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/interceptors/audit.d.ts +25 -0
  50. package/dist/interceptors/audit.d.ts.map +1 -0
  51. package/dist/interceptors/audit.js +46 -0
  52. package/dist/interceptors/audit.js.map +1 -0
  53. package/dist/interceptors/auth.d.ts +13 -0
  54. package/dist/interceptors/auth.d.ts.map +1 -0
  55. package/dist/interceptors/auth.js +34 -0
  56. package/dist/interceptors/auth.js.map +1 -0
  57. package/dist/interceptors/base.d.ts +74 -0
  58. package/dist/interceptors/base.d.ts.map +1 -0
  59. package/dist/interceptors/base.js +103 -0
  60. package/dist/interceptors/base.js.map +1 -0
  61. package/dist/interceptors/capability.d.ts +16 -0
  62. package/dist/interceptors/capability.d.ts.map +1 -0
  63. package/dist/interceptors/capability.js +63 -0
  64. package/dist/interceptors/capability.js.map +1 -0
  65. package/dist/interceptors/circuit-breaker.d.ts +40 -0
  66. package/dist/interceptors/circuit-breaker.d.ts.map +1 -0
  67. package/dist/interceptors/circuit-breaker.js +91 -0
  68. package/dist/interceptors/circuit-breaker.js.map +1 -0
  69. package/dist/interceptors/compression.d.ts +11 -0
  70. package/dist/interceptors/compression.d.ts.map +1 -0
  71. package/dist/interceptors/compression.js +12 -0
  72. package/dist/interceptors/compression.js.map +1 -0
  73. package/dist/interceptors/deadline.d.ts +12 -0
  74. package/dist/interceptors/deadline.d.ts.map +1 -0
  75. package/dist/interceptors/deadline.js +28 -0
  76. package/dist/interceptors/deadline.js.map +1 -0
  77. package/dist/interceptors/metrics.d.ts +43 -0
  78. package/dist/interceptors/metrics.d.ts.map +1 -0
  79. package/dist/interceptors/metrics.js +132 -0
  80. package/dist/interceptors/metrics.js.map +1 -0
  81. package/dist/interceptors/rate-limit.d.ts +24 -0
  82. package/dist/interceptors/rate-limit.d.ts.map +1 -0
  83. package/dist/interceptors/rate-limit.js +84 -0
  84. package/dist/interceptors/rate-limit.js.map +1 -0
  85. package/dist/interceptors/retry.d.ts +25 -0
  86. package/dist/interceptors/retry.d.ts.map +1 -0
  87. package/dist/interceptors/retry.js +55 -0
  88. package/dist/interceptors/retry.js.map +1 -0
  89. package/dist/limits.d.ts +77 -0
  90. package/dist/limits.d.ts.map +1 -0
  91. package/dist/limits.js +137 -0
  92. package/dist/limits.js.map +1 -0
  93. package/dist/logging.d.ts +40 -0
  94. package/dist/logging.d.ts.map +1 -0
  95. package/dist/logging.js +92 -0
  96. package/dist/logging.js.map +1 -0
  97. package/dist/metadata.d.ts +14 -0
  98. package/dist/metadata.d.ts.map +1 -0
  99. package/dist/metadata.js +68 -0
  100. package/dist/metadata.js.map +1 -0
  101. package/dist/metrics.d.ts +40 -0
  102. package/dist/metrics.d.ts.map +1 -0
  103. package/dist/metrics.js +92 -0
  104. package/dist/metrics.js.map +1 -0
  105. package/dist/peer-store.d.ts +53 -0
  106. package/dist/peer-store.d.ts.map +1 -0
  107. package/dist/peer-store.js +105 -0
  108. package/dist/peer-store.js.map +1 -0
  109. package/dist/protocol.d.ts +44 -0
  110. package/dist/protocol.d.ts.map +1 -0
  111. package/dist/protocol.js +59 -0
  112. package/dist/protocol.js.map +1 -0
  113. package/dist/registration.d.ts +81 -0
  114. package/dist/registration.d.ts.map +1 -0
  115. package/dist/registration.js +161 -0
  116. package/dist/registration.js.map +1 -0
  117. package/dist/registry/acl.d.ts +57 -0
  118. package/dist/registry/acl.d.ts.map +1 -0
  119. package/dist/registry/acl.js +104 -0
  120. package/dist/registry/acl.js.map +1 -0
  121. package/dist/registry/client.d.ts +70 -0
  122. package/dist/registry/client.d.ts.map +1 -0
  123. package/dist/registry/client.js +115 -0
  124. package/dist/registry/client.js.map +1 -0
  125. package/dist/registry/gossip.d.ts +43 -0
  126. package/dist/registry/gossip.d.ts.map +1 -0
  127. package/dist/registry/gossip.js +102 -0
  128. package/dist/registry/gossip.js.map +1 -0
  129. package/dist/registry/keys.d.ts +25 -0
  130. package/dist/registry/keys.d.ts.map +1 -0
  131. package/dist/registry/keys.js +47 -0
  132. package/dist/registry/keys.js.map +1 -0
  133. package/dist/registry/models.d.ts +80 -0
  134. package/dist/registry/models.d.ts.map +1 -0
  135. package/dist/registry/models.js +35 -0
  136. package/dist/registry/models.js.map +1 -0
  137. package/dist/registry/publisher.d.ts +65 -0
  138. package/dist/registry/publisher.d.ts.map +1 -0
  139. package/dist/registry/publisher.js +164 -0
  140. package/dist/registry/publisher.js.map +1 -0
  141. package/dist/runtime.d.ts +267 -0
  142. package/dist/runtime.d.ts.map +1 -0
  143. package/dist/runtime.js +1366 -0
  144. package/dist/runtime.js.map +1 -0
  145. package/dist/server.d.ts +100 -0
  146. package/dist/server.d.ts.map +1 -0
  147. package/dist/server.js +511 -0
  148. package/dist/server.js.map +1 -0
  149. package/dist/service.d.ts +72 -0
  150. package/dist/service.d.ts.map +1 -0
  151. package/dist/service.js +98 -0
  152. package/dist/service.js.map +1 -0
  153. package/dist/session.d.ts +64 -0
  154. package/dist/session.d.ts.map +1 -0
  155. package/dist/session.js +350 -0
  156. package/dist/session.js.map +1 -0
  157. package/dist/status.d.ts +113 -0
  158. package/dist/status.d.ts.map +1 -0
  159. package/dist/status.js +206 -0
  160. package/dist/status.js.map +1 -0
  161. package/dist/transport/base.d.ts +46 -0
  162. package/dist/transport/base.d.ts.map +1 -0
  163. package/dist/transport/base.js +10 -0
  164. package/dist/transport/base.js.map +1 -0
  165. package/dist/transport/iroh.d.ts +45 -0
  166. package/dist/transport/iroh.d.ts.map +1 -0
  167. package/dist/transport/iroh.js +225 -0
  168. package/dist/transport/iroh.js.map +1 -0
  169. package/dist/transport/local.d.ts +48 -0
  170. package/dist/transport/local.d.ts.map +1 -0
  171. package/dist/transport/local.js +139 -0
  172. package/dist/transport/local.js.map +1 -0
  173. package/dist/trust/admission.d.ts +60 -0
  174. package/dist/trust/admission.d.ts.map +1 -0
  175. package/dist/trust/admission.js +149 -0
  176. package/dist/trust/admission.js.map +1 -0
  177. package/dist/trust/bootstrap.d.ts +109 -0
  178. package/dist/trust/bootstrap.d.ts.map +1 -0
  179. package/dist/trust/bootstrap.js +311 -0
  180. package/dist/trust/bootstrap.js.map +1 -0
  181. package/dist/trust/clock.d.ts +93 -0
  182. package/dist/trust/clock.d.ts.map +1 -0
  183. package/dist/trust/clock.js +154 -0
  184. package/dist/trust/clock.js.map +1 -0
  185. package/dist/trust/consumer.d.ts +139 -0
  186. package/dist/trust/consumer.d.ts.map +1 -0
  187. package/dist/trust/consumer.js +323 -0
  188. package/dist/trust/consumer.js.map +1 -0
  189. package/dist/trust/credentials.d.ts +98 -0
  190. package/dist/trust/credentials.d.ts.map +1 -0
  191. package/dist/trust/credentials.js +250 -0
  192. package/dist/trust/credentials.js.map +1 -0
  193. package/dist/trust/delegated.d.ts +118 -0
  194. package/dist/trust/delegated.d.ts.map +1 -0
  195. package/dist/trust/delegated.js +292 -0
  196. package/dist/trust/delegated.js.map +1 -0
  197. package/dist/trust/gossip.d.ts +146 -0
  198. package/dist/trust/gossip.d.ts.map +1 -0
  199. package/dist/trust/gossip.js +334 -0
  200. package/dist/trust/gossip.js.map +1 -0
  201. package/dist/trust/hooks.d.ts +84 -0
  202. package/dist/trust/hooks.d.ts.map +1 -0
  203. package/dist/trust/hooks.js +125 -0
  204. package/dist/trust/hooks.js.map +1 -0
  205. package/dist/trust/iid.d.ts +65 -0
  206. package/dist/trust/iid.d.ts.map +1 -0
  207. package/dist/trust/iid.js +104 -0
  208. package/dist/trust/iid.js.map +1 -0
  209. package/dist/trust/mesh.d.ts +43 -0
  210. package/dist/trust/mesh.d.ts.map +1 -0
  211. package/dist/trust/mesh.js +105 -0
  212. package/dist/trust/mesh.js.map +1 -0
  213. package/dist/trust/nonce.d.ts +39 -0
  214. package/dist/trust/nonce.d.ts.map +1 -0
  215. package/dist/trust/nonce.js +46 -0
  216. package/dist/trust/nonce.js.map +1 -0
  217. package/dist/trust/producer.d.ts +80 -0
  218. package/dist/trust/producer.d.ts.map +1 -0
  219. package/dist/trust/producer.js +151 -0
  220. package/dist/trust/producer.js.map +1 -0
  221. package/dist/trust/rcan.d.ts +29 -0
  222. package/dist/trust/rcan.d.ts.map +1 -0
  223. package/dist/trust/rcan.js +57 -0
  224. package/dist/trust/rcan.js.map +1 -0
  225. package/dist/types.d.ts +57 -0
  226. package/dist/types.d.ts.map +1 -0
  227. package/dist/types.js +50 -0
  228. package/dist/types.js.map +1 -0
  229. package/dist/xlang.d.ts +26 -0
  230. package/dist/xlang.d.ts.map +1 -0
  231. package/dist/xlang.js +55 -0
  232. package/dist/xlang.js.map +1 -0
  233. package/package.json +59 -0
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Circuit breaker interceptor — stops sending requests to failing services.
3
+ *
4
+ * States: CLOSED (normal) -> OPEN (failing) -> HALF_OPEN (probe) -> CLOSED
5
+ */
6
+ import { RpcError, StatusCode } from '../status.js';
7
+ export class CircuitBreakerInterceptor {
8
+ state = 'closed';
9
+ failures = 0;
10
+ lastFailure = 0;
11
+ halfOpenCalls = 0;
12
+ failureThreshold;
13
+ resetTimeoutMs;
14
+ halfOpenMaxCalls;
15
+ constructor(opts = {}) {
16
+ this.failureThreshold = opts.failureThreshold ?? 5;
17
+ this.resetTimeoutMs = opts.resetTimeoutMs ?? 30_000;
18
+ this.halfOpenMaxCalls = opts.halfOpenMaxCalls ?? 1;
19
+ }
20
+ async onRequest(_ctx, request) {
21
+ if (this.state === 'open') {
22
+ if (Date.now() - this.lastFailure > this.resetTimeoutMs) {
23
+ this.state = 'half_open';
24
+ this.halfOpenCalls = 0;
25
+ }
26
+ else {
27
+ throw new RpcError(StatusCode.UNAVAILABLE, 'circuit breaker is open');
28
+ }
29
+ }
30
+ if (this.state === 'half_open' && this.halfOpenCalls >= this.halfOpenMaxCalls) {
31
+ throw new RpcError(StatusCode.UNAVAILABLE, 'circuit breaker half-open limit reached');
32
+ }
33
+ if (this.state === 'half_open')
34
+ this.halfOpenCalls++;
35
+ return request;
36
+ }
37
+ async onResponse(_ctx, response) {
38
+ if (this.state === 'half_open') {
39
+ this.state = 'closed';
40
+ this.failures = 0;
41
+ }
42
+ return response;
43
+ }
44
+ async onError(_ctx, error) {
45
+ this.failures++;
46
+ this.lastFailure = Date.now();
47
+ if (this.failures >= this.failureThreshold) {
48
+ this.state = 'open';
49
+ }
50
+ return error;
51
+ }
52
+ /** Current circuit state. */
53
+ get currentState() {
54
+ return this.state;
55
+ }
56
+ /**
57
+ * Pre-call gate check — throws if circuit is open.
58
+ * Alias for the logic in onRequest(), callable without a full call context.
59
+ */
60
+ beforeCall() {
61
+ if (this.state === 'open') {
62
+ if (Date.now() - this.lastFailure > this.resetTimeoutMs) {
63
+ this.state = 'half_open';
64
+ this.halfOpenCalls = 0;
65
+ }
66
+ else {
67
+ throw new RpcError(StatusCode.UNAVAILABLE, 'circuit breaker is open');
68
+ }
69
+ }
70
+ if (this.state === 'half_open' && this.halfOpenCalls >= this.halfOpenMaxCalls) {
71
+ throw new RpcError(StatusCode.UNAVAILABLE, 'circuit breaker half-open limit reached');
72
+ }
73
+ if (this.state === 'half_open')
74
+ this.halfOpenCalls++;
75
+ }
76
+ /** Record a successful call — resets the failure count. */
77
+ recordSuccess() {
78
+ if (this.state === 'half_open')
79
+ this.state = 'closed';
80
+ this.failures = 0;
81
+ }
82
+ /** Record a failed call — may open the circuit. */
83
+ recordFailure() {
84
+ this.failures++;
85
+ this.lastFailure = Date.now();
86
+ if (this.failures >= this.failureThreshold) {
87
+ this.state = 'open';
88
+ }
89
+ }
90
+ }
91
+ //# sourceMappingURL=circuit-breaker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-breaker.js","sourceRoot":"","sources":["../../src/interceptors/circuit-breaker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Compression interceptor — manages payload compression negotiation.
3
+ */
4
+ import type { Interceptor } from './base.js';
5
+ import { CallContext } from './base.js';
6
+ export declare class CompressionInterceptor implements Interceptor {
7
+ readonly threshold: number;
8
+ constructor(threshold?: number);
9
+ onRequest(ctx: CallContext, request: unknown): Promise<unknown>;
10
+ }
11
+ //# sourceMappingURL=compression.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compression.d.ts","sourceRoot":"","sources":["../../src/interceptors/compression.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,qBAAa,sBAAuB,YAAW,WAAW;IACxD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBACf,SAAS,SAAO;IAEtB,SAAS,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;CAItE"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Compression interceptor — manages payload compression negotiation.
3
+ */
4
+ export class CompressionInterceptor {
5
+ threshold;
6
+ constructor(threshold = 4096) { this.threshold = threshold; }
7
+ async onRequest(ctx, request) {
8
+ ctx.metadata['accept-encoding'] = 'zstd';
9
+ return request;
10
+ }
11
+ }
12
+ //# sourceMappingURL=compression.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compression.js","sourceRoot":"","sources":["../../src/interceptors/compression.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,OAAO,sBAAsB;IACxB,SAAS,CAAS;IAC3B,YAAY,SAAS,GAAG,IAAI,IAAI,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC;IAE7D,KAAK,CAAC,SAAS,CAAC,GAAgB,EAAE,OAAgB;QAChD,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC,GAAG,MAAM,CAAC;QACzC,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Deadline enforcement interceptor. Spec S6.8.1.
3
+ */
4
+ import type { Interceptor } from './base.js';
5
+ import { CallContext } from './base.js';
6
+ export declare class DeadlineInterceptor implements Interceptor {
7
+ private skewToleranceMs;
8
+ constructor(skewToleranceMs?: number);
9
+ onRequest(ctx: CallContext, request: unknown): Promise<unknown>;
10
+ timeoutSeconds(ctx: CallContext): number | undefined;
11
+ }
12
+ //# sourceMappingURL=deadline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deadline.d.ts","sourceRoot":"","sources":["../../src/interceptors/deadline.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAGxC,qBAAa,mBAAoB,YAAW,WAAW;IACrD,OAAO,CAAC,eAAe,CAAS;gBAEpB,eAAe,SAAO;IAI5B,SAAS,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAiBrE,cAAc,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS;CAIrD"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Deadline enforcement interceptor. Spec S6.8.1.
3
+ */
4
+ import { RpcError, StatusCode } from '../status.js';
5
+ export class DeadlineInterceptor {
6
+ skewToleranceMs;
7
+ constructor(skewToleranceMs = 5000) {
8
+ this.skewToleranceMs = skewToleranceMs;
9
+ }
10
+ async onRequest(ctx, request) {
11
+ if (ctx.deadline !== undefined) {
12
+ const nowMs = Date.now();
13
+ const deadlineMs = ctx.deadline * 1000;
14
+ if (nowMs > deadlineMs + this.skewToleranceMs) {
15
+ throw new RpcError(StatusCode.DEADLINE_EXCEEDED, `deadline already expired on receipt (skew_tolerance=${this.skewToleranceMs}ms)`);
16
+ }
17
+ if (ctx.expired) {
18
+ throw new RpcError(StatusCode.DEADLINE_EXCEEDED, 'deadline exceeded');
19
+ }
20
+ }
21
+ return request;
22
+ }
23
+ timeoutSeconds(ctx) {
24
+ const remaining = ctx.remainingSeconds;
25
+ return remaining !== undefined ? Math.max(0, remaining) : undefined;
26
+ }
27
+ }
28
+ //# sourceMappingURL=deadline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deadline.js","sourceRoot":"","sources":["../../src/interceptors/deadline.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,OAAO,mBAAmB;IACtB,eAAe,CAAS;IAEhC,YAAY,eAAe,GAAG,IAAI;QAChC,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,GAAgB,EAAE,OAAgB;QAChD,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACzB,MAAM,UAAU,GAAG,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC;YACvC,IAAI,KAAK,GAAG,UAAU,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;gBAC9C,MAAM,IAAI,QAAQ,CAChB,UAAU,CAAC,iBAAiB,EAC5B,uDAAuD,IAAI,CAAC,eAAe,KAAK,CACjF,CAAC;YACJ,CAAC;YACD,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;gBAChB,MAAM,IAAI,QAAQ,CAAC,UAAU,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,CAAC;YACxE,CAAC;QACH,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,cAAc,CAAC,GAAgB;QAC7B,MAAM,SAAS,GAAG,GAAG,CAAC,gBAAgB,CAAC;QACvC,OAAO,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACtE,CAAC;CACF"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Metrics interceptor with optional OpenTelemetry integration.
3
+ *
4
+ * Collects RED metrics (Rate, Errors, Duration). Falls back to
5
+ * in-memory counters when OTel is not installed.
6
+ */
7
+ import type { Interceptor } from './base.js';
8
+ import { CallContext } from './base.js';
9
+ import type { RpcError } from '../status.js';
10
+ export declare class MetricsInterceptor implements Interceptor {
11
+ started: number;
12
+ succeeded: number;
13
+ failed: number;
14
+ inFlight: number;
15
+ /** Total duration of all completed RPCs in seconds (for computing averages). */
16
+ totalDurationS: number;
17
+ /** Duration of the last completed RPC in seconds. */
18
+ lastDurationS: number;
19
+ private startTimes;
20
+ private _tracer;
21
+ private _meter;
22
+ private _startedCounter;
23
+ private _completedCounter;
24
+ private _durationHistogram;
25
+ constructor();
26
+ /** Whether OpenTelemetry is available and configured. */
27
+ get hasOtel(): boolean;
28
+ onRequest(ctx: CallContext, request: unknown): Promise<unknown>;
29
+ onResponse(ctx: CallContext, response: unknown): Promise<unknown>;
30
+ onError(ctx: CallContext, error: RpcError): Promise<RpcError>;
31
+ /** Snapshot of current metrics. */
32
+ snapshot(): {
33
+ started: number;
34
+ succeeded: number;
35
+ failed: number;
36
+ inFlight: number;
37
+ totalDurationS: number;
38
+ lastDurationS: number;
39
+ };
40
+ /** Reset all counters. */
41
+ reset(): void;
42
+ }
43
+ //# sourceMappingURL=metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/interceptors/metrics.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,qBAAa,kBAAmB,YAAW,WAAW;IACpD,OAAO,SAAK;IACZ,SAAS,SAAK;IACd,MAAM,SAAK;IACX,QAAQ,SAAK;IAEb,gFAAgF;IAChF,cAAc,SAAK;IACnB,qDAAqD;IACrD,aAAa,SAAK;IAElB,OAAO,CAAC,UAAU,CAA6B;IAG/C,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,eAAe,CAAiB;IACxC,OAAO,CAAC,iBAAiB,CAAiB;IAC1C,OAAO,CAAC,kBAAkB,CAAiB;;IAyB3C,yDAAyD;IACzD,IAAI,OAAO,IAAI,OAAO,CAErB;IAEK,SAAS,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAa/D,UAAU,CAAC,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IA8BjE,OAAO,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IA8BnE,mCAAmC;IACnC,QAAQ,IAAI;QACV,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,MAAM,CAAC;KACvB;IAWD,0BAA0B;IAC1B,KAAK,IAAI,IAAI;CASd"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Metrics interceptor with optional OpenTelemetry integration.
3
+ *
4
+ * Collects RED metrics (Rate, Errors, Duration). Falls back to
5
+ * in-memory counters when OTel is not installed.
6
+ */
7
+ export class MetricsInterceptor {
8
+ started = 0;
9
+ succeeded = 0;
10
+ failed = 0;
11
+ inFlight = 0;
12
+ /** Total duration of all completed RPCs in seconds (for computing averages). */
13
+ totalDurationS = 0;
14
+ /** Duration of the last completed RPC in seconds. */
15
+ lastDurationS = 0;
16
+ startTimes = new Map();
17
+ // Optional OTel integration
18
+ _tracer = null;
19
+ _meter = null;
20
+ _startedCounter = null;
21
+ _completedCounter = null;
22
+ _durationHistogram = null;
23
+ constructor() {
24
+ try {
25
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
26
+ const { trace, metrics } = require('@opentelemetry/api');
27
+ this._tracer = trace.getTracer('aster.rpc', '0.1.0');
28
+ this._meter = metrics.getMeter('aster.rpc', '0.1.0');
29
+ this._startedCounter = this._meter.createCounter('aster.rpc.started', {
30
+ description: 'Total RPC calls started',
31
+ unit: '1',
32
+ });
33
+ this._completedCounter = this._meter.createCounter('aster.rpc.completed', {
34
+ description: 'Total RPC calls completed',
35
+ unit: '1',
36
+ });
37
+ this._durationHistogram = this._meter.createHistogram('aster.rpc.duration', {
38
+ description: 'RPC call duration',
39
+ unit: 's',
40
+ });
41
+ }
42
+ catch {
43
+ // OTel not installed — use fallback counters
44
+ }
45
+ }
46
+ /** Whether OpenTelemetry is available and configured. */
47
+ get hasOtel() {
48
+ return this._tracer !== null;
49
+ }
50
+ async onRequest(ctx, request) {
51
+ this.started++;
52
+ this.inFlight++;
53
+ this.startTimes.set(ctx.callId, performance.now());
54
+ if (this._startedCounter) {
55
+ const labels = { service: ctx.service, method: ctx.method, pattern: ctx.pattern ?? 'unary' };
56
+ this._startedCounter.add(1, labels);
57
+ }
58
+ return request;
59
+ }
60
+ async onResponse(ctx, response) {
61
+ this.succeeded++;
62
+ this.inFlight--;
63
+ const startTime = this.startTimes.get(ctx.callId);
64
+ if (startTime !== undefined) {
65
+ const durationS = (performance.now() - startTime) / 1000;
66
+ this.totalDurationS += durationS;
67
+ this.lastDurationS = durationS;
68
+ this.startTimes.delete(ctx.callId);
69
+ if (this._durationHistogram) {
70
+ this._durationHistogram.record(durationS, {
71
+ service: ctx.service,
72
+ method: ctx.method,
73
+ });
74
+ }
75
+ }
76
+ if (this._completedCounter) {
77
+ this._completedCounter.add(1, {
78
+ service: ctx.service,
79
+ method: ctx.method,
80
+ status: 'OK',
81
+ });
82
+ }
83
+ return response;
84
+ }
85
+ async onError(ctx, error) {
86
+ this.failed++;
87
+ this.inFlight--;
88
+ const startTime = this.startTimes.get(ctx.callId);
89
+ if (startTime !== undefined) {
90
+ const durationS = (performance.now() - startTime) / 1000;
91
+ this.totalDurationS += durationS;
92
+ this.lastDurationS = durationS;
93
+ this.startTimes.delete(ctx.callId);
94
+ if (this._durationHistogram) {
95
+ this._durationHistogram.record(durationS, {
96
+ service: ctx.service,
97
+ method: ctx.method,
98
+ });
99
+ }
100
+ }
101
+ if (this._completedCounter) {
102
+ this._completedCounter.add(1, {
103
+ service: ctx.service,
104
+ method: ctx.method,
105
+ status: String(error.code ?? 'UNKNOWN'),
106
+ });
107
+ }
108
+ return error;
109
+ }
110
+ /** Snapshot of current metrics. */
111
+ snapshot() {
112
+ return {
113
+ started: this.started,
114
+ succeeded: this.succeeded,
115
+ failed: this.failed,
116
+ inFlight: this.inFlight,
117
+ totalDurationS: this.totalDurationS,
118
+ lastDurationS: this.lastDurationS,
119
+ };
120
+ }
121
+ /** Reset all counters. */
122
+ reset() {
123
+ this.started = 0;
124
+ this.succeeded = 0;
125
+ this.failed = 0;
126
+ this.inFlight = 0;
127
+ this.totalDurationS = 0;
128
+ this.lastDurationS = 0;
129
+ this.startTimes.clear();
130
+ }
131
+ }
132
+ //# sourceMappingURL=metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../src/interceptors/metrics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Token-bucket rate limit interceptor.
3
+ *
4
+ * Enforces rate limits at global, per-service, per-method, and per-peer granularity.
5
+ */
6
+ import type { Interceptor } from './base.js';
7
+ import { CallContext } from './base.js';
8
+ export interface RateLimitOptions {
9
+ globalRps?: number;
10
+ perServiceRps?: number;
11
+ perMethodRps?: number;
12
+ perPeerRps?: number;
13
+ }
14
+ export declare class RateLimitInterceptor implements Interceptor {
15
+ private global;
16
+ private perService;
17
+ private perMethod;
18
+ private perPeer;
19
+ private opts;
20
+ constructor(opts?: RateLimitOptions);
21
+ onRequest(ctx: CallContext, request: unknown): Promise<unknown>;
22
+ private getOrCreate;
23
+ }
24
+ //# sourceMappingURL=rate-limit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/interceptors/rate-limit.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAgCxC,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,oBAAqB,YAAW,WAAW;IACtD,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,UAAU,CAAkC;IACpD,OAAO,CAAC,SAAS,CAAkC;IACnD,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,IAAI,CAA6B;gBAE7B,IAAI,GAAE,gBAAqB;IAYjC,SAAS,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IA8BrE,OAAO,CAAC,WAAW;CAQpB"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Token-bucket rate limit interceptor.
3
+ *
4
+ * Enforces rate limits at global, per-service, per-method, and per-peer granularity.
5
+ */
6
+ import { RpcError, StatusCode } from '../status.js';
7
+ class TokenBucket {
8
+ rps;
9
+ maxBurst;
10
+ tokens;
11
+ lastRefill;
12
+ constructor(rps, maxBurst) {
13
+ this.rps = rps;
14
+ this.maxBurst = maxBurst;
15
+ this.tokens = maxBurst;
16
+ this.lastRefill = performance.now();
17
+ }
18
+ tryConsume() {
19
+ this.refill();
20
+ if (this.tokens >= 1) {
21
+ this.tokens -= 1;
22
+ return true;
23
+ }
24
+ return false;
25
+ }
26
+ refill() {
27
+ const now = performance.now();
28
+ const elapsed = (now - this.lastRefill) / 1000;
29
+ this.tokens = Math.min(this.maxBurst, this.tokens + elapsed * this.rps);
30
+ this.lastRefill = now;
31
+ }
32
+ }
33
+ export class RateLimitInterceptor {
34
+ global;
35
+ perService = new Map();
36
+ perMethod = new Map();
37
+ perPeer = new Map();
38
+ opts;
39
+ constructor(opts = {}) {
40
+ this.opts = {
41
+ globalRps: opts.globalRps ?? 0,
42
+ perServiceRps: opts.perServiceRps ?? 0,
43
+ perMethodRps: opts.perMethodRps ?? 0,
44
+ perPeerRps: opts.perPeerRps ?? 0,
45
+ };
46
+ if (this.opts.globalRps > 0) {
47
+ this.global = new TokenBucket(this.opts.globalRps, this.opts.globalRps * 2);
48
+ }
49
+ }
50
+ async onRequest(ctx, request) {
51
+ if (this.global && !this.global.tryConsume()) {
52
+ throw new RpcError(StatusCode.RESOURCE_EXHAUSTED, 'global rate limit exceeded');
53
+ }
54
+ if (this.opts.perServiceRps > 0) {
55
+ const bucket = this.getOrCreate(this.perService, ctx.service, this.opts.perServiceRps);
56
+ if (!bucket.tryConsume()) {
57
+ throw new RpcError(StatusCode.RESOURCE_EXHAUSTED, `rate limit exceeded for service ${ctx.service}`);
58
+ }
59
+ }
60
+ if (this.opts.perMethodRps > 0) {
61
+ const key = `${ctx.service}/${ctx.method}`;
62
+ const bucket = this.getOrCreate(this.perMethod, key, this.opts.perMethodRps);
63
+ if (!bucket.tryConsume()) {
64
+ throw new RpcError(StatusCode.RESOURCE_EXHAUSTED, `rate limit exceeded for ${key}`);
65
+ }
66
+ }
67
+ if (this.opts.perPeerRps > 0 && ctx.peer) {
68
+ const bucket = this.getOrCreate(this.perPeer, ctx.peer, this.opts.perPeerRps);
69
+ if (!bucket.tryConsume()) {
70
+ throw new RpcError(StatusCode.RESOURCE_EXHAUSTED, `rate limit exceeded for peer ${ctx.peer}`);
71
+ }
72
+ }
73
+ return request;
74
+ }
75
+ getOrCreate(map, key, rps) {
76
+ let bucket = map.get(key);
77
+ if (!bucket) {
78
+ bucket = new TokenBucket(rps, rps * 2);
79
+ map.set(key, bucket);
80
+ }
81
+ return bucket;
82
+ }
83
+ }
84
+ //# sourceMappingURL=rate-limit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../src/interceptors/rate-limit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Retry interceptor with exponential backoff.
3
+ *
4
+ * Only retries idempotent calls on retryable status codes.
5
+ */
6
+ import type { Interceptor } from './base.js';
7
+ import { CallContext } from './base.js';
8
+ import { RpcError } from '../status.js';
9
+ import { type RetryPolicy } from '../types.js';
10
+ export declare class RetryInterceptor implements Interceptor {
11
+ private policy;
12
+ constructor(policy?: Partial<RetryPolicy>);
13
+ onError(ctx: CallContext, error: RpcError): Promise<RpcError>;
14
+ private backoffMs;
15
+ /**
16
+ * Decide if a call should be retried.
17
+ * Returns true if the error is retryable, call is idempotent, and attempts remain.
18
+ */
19
+ shouldRetry(error: RpcError, attempt: number, idempotent?: boolean): boolean;
20
+ /**
21
+ * Compute backoff duration in seconds for the given attempt number.
22
+ */
23
+ backoffSeconds(attempt: number): number;
24
+ }
25
+ //# sourceMappingURL=retry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/interceptors/retry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAc,MAAM,cAAc,CAAC;AACpD,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAS9D,qBAAa,gBAAiB,YAAW,WAAW;IAClD,OAAO,CAAC,MAAM,CAAc;gBAEhB,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC;IAInC,OAAO,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAWnE,OAAO,CAAC,SAAS;IAOjB;;;OAGG;IACH,WAAW,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,UAAQ,GAAG,OAAO;IAM1E;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;CAGxC"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Retry interceptor with exponential backoff.
3
+ *
4
+ * Only retries idempotent calls on retryable status codes.
5
+ */
6
+ import { StatusCode } from '../status.js';
7
+ import { DEFAULT_RETRY } from '../types.js';
8
+ const RETRYABLE_CODES = new Set([
9
+ StatusCode.UNAVAILABLE,
10
+ StatusCode.DEADLINE_EXCEEDED,
11
+ StatusCode.ABORTED,
12
+ StatusCode.RESOURCE_EXHAUSTED,
13
+ ]);
14
+ export class RetryInterceptor {
15
+ policy;
16
+ constructor(policy) {
17
+ this.policy = { ...DEFAULT_RETRY, ...policy };
18
+ }
19
+ async onError(ctx, error) {
20
+ if (!ctx.idempotent)
21
+ return error;
22
+ if (!RETRYABLE_CODES.has(error.code))
23
+ return error;
24
+ if (ctx.attempt >= this.policy.maxAttempts)
25
+ return error;
26
+ // Signal retry by attaching metadata
27
+ error.details['retry_after_ms'] = String(this.backoffMs(ctx.attempt));
28
+ error.details['retry_attempt'] = String(ctx.attempt);
29
+ return error;
30
+ }
31
+ backoffMs(attempt) {
32
+ const { initialMs, multiplier, maxMs, jitter } = this.policy.backoff;
33
+ const base = Math.min(initialMs * Math.pow(multiplier, attempt - 1), maxMs);
34
+ const jitterAmount = base * jitter * (Math.random() * 2 - 1);
35
+ return Math.max(0, Math.round(base + jitterAmount));
36
+ }
37
+ /**
38
+ * Decide if a call should be retried.
39
+ * Returns true if the error is retryable, call is idempotent, and attempts remain.
40
+ */
41
+ shouldRetry(error, attempt, idempotent = false) {
42
+ if (!idempotent)
43
+ return false;
44
+ if (!RETRYABLE_CODES.has(error.code))
45
+ return false;
46
+ return attempt < this.policy.maxAttempts;
47
+ }
48
+ /**
49
+ * Compute backoff duration in seconds for the given attempt number.
50
+ */
51
+ backoffSeconds(attempt) {
52
+ return this.backoffMs(attempt) / 1000;
53
+ }
54
+ }
55
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/interceptors/retry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAY,UAAU,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,aAAa,EAAoB,MAAM,aAAa,CAAC;AAE9D,MAAM,eAAe,GAAG,IAAI,GAAG,CAAS;IACtC,UAAU,CAAC,WAAW;IACtB,UAAU,CAAC,iBAAiB;IAC5B,UAAU,CAAC,OAAO;IAClB,UAAU,CAAC,kBAAkB;CAC9B,CAAC,CAAC;AAEH,MAAM,OAAO,gBAAgB;IACnB,MAAM,CAAc;IAE5B,YAAY,MAA6B;QACvC,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,aAAa,EAAE,GAAG,MAAM,EAAE,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAgB,EAAE,KAAe;QAC7C,IAAI,CAAC,GAAG,CAAC,UAAU;YAAE,OAAO,KAAK,CAAC;QAClC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QACnD,IAAI,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW;YAAE,OAAO,KAAK,CAAC;QAEzD,qCAAqC;QACrC,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;QACtE,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACrD,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,SAAS,CAAC,OAAe;QAC/B,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;QACrE,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QAC5E,MAAM,YAAY,GAAG,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7D,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,YAAY,CAAC,CAAC,CAAC;IACtD,CAAC;IAED;;;OAGG;IACH,WAAW,CAAC,KAAe,EAAE,OAAe,EAAE,UAAU,GAAG,KAAK;QAC9D,IAAI,CAAC,UAAU;YAAE,OAAO,KAAK,CAAC;QAC9B,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QACnD,OAAO,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;IAC3C,CAAC;IAED;;OAEG;IACH,cAAc,CAAC,OAAe;QAC5B,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IACxC,CAAC;CACF"}