tywrap 0.2.0 → 0.2.1

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 (88) hide show
  1. package/README.md +1 -1
  2. package/dist/index.d.ts +20 -4
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +22 -2
  5. package/dist/index.js.map +1 -1
  6. package/dist/runtime/base.d.ts +17 -7
  7. package/dist/runtime/base.d.ts.map +1 -1
  8. package/dist/runtime/base.js +18 -1
  9. package/dist/runtime/base.js.map +1 -1
  10. package/dist/runtime/bounded-context.d.ts +252 -0
  11. package/dist/runtime/bounded-context.d.ts.map +1 -0
  12. package/dist/runtime/bounded-context.js +454 -0
  13. package/dist/runtime/bounded-context.js.map +1 -0
  14. package/dist/runtime/bridge-protocol.d.ts +167 -0
  15. package/dist/runtime/bridge-protocol.d.ts.map +1 -0
  16. package/dist/runtime/bridge-protocol.js +247 -0
  17. package/dist/runtime/bridge-protocol.js.map +1 -0
  18. package/dist/runtime/disposable.d.ts +40 -0
  19. package/dist/runtime/disposable.d.ts.map +1 -0
  20. package/dist/runtime/disposable.js +49 -0
  21. package/dist/runtime/disposable.js.map +1 -0
  22. package/dist/runtime/http-io.d.ts +91 -0
  23. package/dist/runtime/http-io.d.ts.map +1 -0
  24. package/dist/runtime/http-io.js +195 -0
  25. package/dist/runtime/http-io.js.map +1 -0
  26. package/dist/runtime/http.d.ts +47 -13
  27. package/dist/runtime/http.d.ts.map +1 -1
  28. package/dist/runtime/http.js +55 -74
  29. package/dist/runtime/http.js.map +1 -1
  30. package/dist/runtime/node.d.ts +97 -130
  31. package/dist/runtime/node.d.ts.map +1 -1
  32. package/dist/runtime/node.js +256 -523
  33. package/dist/runtime/node.js.map +1 -1
  34. package/dist/runtime/pooled-transport.d.ts +131 -0
  35. package/dist/runtime/pooled-transport.d.ts.map +1 -0
  36. package/dist/runtime/pooled-transport.js +175 -0
  37. package/dist/runtime/pooled-transport.js.map +1 -0
  38. package/dist/runtime/process-io.d.ts +204 -0
  39. package/dist/runtime/process-io.d.ts.map +1 -0
  40. package/dist/runtime/process-io.js +695 -0
  41. package/dist/runtime/process-io.js.map +1 -0
  42. package/dist/runtime/pyodide-io.d.ts +155 -0
  43. package/dist/runtime/pyodide-io.d.ts.map +1 -0
  44. package/dist/runtime/pyodide-io.js +397 -0
  45. package/dist/runtime/pyodide-io.js.map +1 -0
  46. package/dist/runtime/pyodide.d.ts +51 -19
  47. package/dist/runtime/pyodide.d.ts.map +1 -1
  48. package/dist/runtime/pyodide.js +57 -186
  49. package/dist/runtime/pyodide.js.map +1 -1
  50. package/dist/runtime/safe-codec.d.ts +81 -0
  51. package/dist/runtime/safe-codec.d.ts.map +1 -0
  52. package/dist/runtime/safe-codec.js +345 -0
  53. package/dist/runtime/safe-codec.js.map +1 -0
  54. package/dist/runtime/transport.d.ts +186 -0
  55. package/dist/runtime/transport.d.ts.map +1 -0
  56. package/dist/runtime/transport.js +86 -0
  57. package/dist/runtime/transport.js.map +1 -0
  58. package/dist/runtime/validators.d.ts +131 -0
  59. package/dist/runtime/validators.d.ts.map +1 -0
  60. package/dist/runtime/validators.js +219 -0
  61. package/dist/runtime/validators.js.map +1 -0
  62. package/dist/runtime/worker-pool.d.ts +196 -0
  63. package/dist/runtime/worker-pool.d.ts.map +1 -0
  64. package/dist/runtime/worker-pool.js +371 -0
  65. package/dist/runtime/worker-pool.js.map +1 -0
  66. package/dist/utils/codec.d.ts.map +1 -1
  67. package/dist/utils/codec.js +120 -1
  68. package/dist/utils/codec.js.map +1 -1
  69. package/package.json +2 -2
  70. package/runtime/python_bridge.py +30 -3
  71. package/runtime/safe_codec.py +344 -0
  72. package/src/index.ts +48 -5
  73. package/src/runtime/base.ts +18 -26
  74. package/src/runtime/bounded-context.ts +608 -0
  75. package/src/runtime/bridge-protocol.ts +319 -0
  76. package/src/runtime/disposable.ts +65 -0
  77. package/src/runtime/http-io.ts +244 -0
  78. package/src/runtime/http.ts +71 -117
  79. package/src/runtime/node.ts +358 -691
  80. package/src/runtime/pooled-transport.ts +252 -0
  81. package/src/runtime/process-io.ts +902 -0
  82. package/src/runtime/pyodide-io.ts +485 -0
  83. package/src/runtime/pyodide.ts +75 -215
  84. package/src/runtime/safe-codec.ts +443 -0
  85. package/src/runtime/transport.ts +273 -0
  86. package/src/runtime/validators.ts +241 -0
  87. package/src/runtime/worker-pool.ts +498 -0
  88. package/src/utils/codec.ts +126 -1
@@ -1,22 +1,56 @@
1
1
  /**
2
- * HTTP runtime bridge
2
+ * HTTP runtime bridge for BridgeProtocol.
3
+ *
4
+ * HttpBridge extends BridgeProtocol and uses HttpIO transport for
5
+ * stateless HTTP POST-based communication with a Python server.
6
+ *
7
+ * @see https://github.com/bbopen/tywrap/issues/149
8
+ */
9
+ import { BridgeProtocol } from './bridge-protocol.js';
10
+ import type { CodecOptions } from './safe-codec.js';
11
+ /**
12
+ * Configuration options for HttpBridge.
3
13
  */
4
- import { RuntimeBridge } from './base.js';
5
14
  export interface HttpBridgeOptions {
15
+ /** Base URL for the Python server (e.g., 'http://localhost:8000') */
6
16
  baseURL: string;
17
+ /** Additional headers to include in each request */
7
18
  headers?: Record<string, string>;
19
+ /** Timeout in ms for requests. Default: 30000 (30 seconds) */
8
20
  timeoutMs?: number;
21
+ /** Codec options for validation/serialization */
22
+ codec?: CodecOptions;
9
23
  }
10
- export declare class HttpBridge extends RuntimeBridge {
11
- private readonly baseURL;
12
- private readonly headers;
13
- private readonly timeoutMs;
14
- constructor(options?: HttpBridgeOptions);
15
- call<T = unknown>(module: string, functionName: string, args: unknown[], kwargs?: Record<string, unknown>): Promise<T>;
16
- instantiate<T = unknown>(module: string, className: string, args: unknown[], kwargs?: Record<string, unknown>): Promise<T>;
17
- callMethod<T = unknown>(handle: string, methodName: string, args: unknown[], kwargs?: Record<string, unknown>): Promise<T>;
18
- disposeInstance(handle: string): Promise<void>;
19
- dispose(): Promise<void>;
20
- private post;
24
+ /**
25
+ * HTTP-based runtime bridge for executing Python code.
26
+ *
27
+ * HttpBridge provides a stateless HTTP transport for communication with
28
+ * a Python server. Each request is independent - no connection state is
29
+ * maintained between calls.
30
+ *
31
+ * Features:
32
+ * - Stateless HTTP POST communication
33
+ * - Timeout handling via AbortController
34
+ * - Full SafeCodec validation (NaN/Infinity rejection, key validation)
35
+ * - Automatic Arrow decoding for DataFrames/ndarrays
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * const bridge = new HttpBridge({ baseURL: 'http://localhost:8000' });
40
+ * await bridge.init();
41
+ *
42
+ * const result = await bridge.call('math', 'sqrt', [16]);
43
+ * console.log(result); // 4.0
44
+ *
45
+ * await bridge.dispose();
46
+ * ```
47
+ */
48
+ export declare class HttpBridge extends BridgeProtocol {
49
+ /**
50
+ * Create a new HttpBridge instance.
51
+ *
52
+ * @param options - Configuration options for the bridge
53
+ */
54
+ constructor(options: HttpBridgeOptions);
21
55
  }
22
56
  //# sourceMappingURL=http.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/runtime/http.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA2BD,qBAAa,UAAW,SAAQ,aAAa;IAC3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,OAAO,GAAE,iBAAwD;IAOvE,IAAI,CAAC,CAAC,GAAG,OAAO,EACpB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,OAAO,EAAE,EACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IAMP,WAAW,CAAC,CAAC,GAAG,OAAO,EAC3B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,OAAO,EAAE,EACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IAMP,UAAU,CAAC,CAAC,GAAG,OAAO,EAC1B,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,OAAO,EAAE,EACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IAMP,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK9C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YAIhB,IAAI;CA8BnB"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/runtime/http.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,cAAc,EAA8B,MAAM,sBAAsB,CAAC;AAElF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAMpD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAC;IAEhB,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,iDAAiD;IACjD,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAMD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,UAAW,SAAQ,cAAc;IAC5C;;;;OAIG;gBACS,OAAO,EAAE,iBAAiB;CAiBvC"}
@@ -1,79 +1,60 @@
1
1
  /**
2
- * HTTP runtime bridge
2
+ * HTTP runtime bridge for BridgeProtocol.
3
+ *
4
+ * HttpBridge extends BridgeProtocol and uses HttpIO transport for
5
+ * stateless HTTP POST-based communication with a Python server.
6
+ *
7
+ * @see https://github.com/bbopen/tywrap/issues/149
3
8
  */
4
- import { decodeValueAsync } from '../utils/codec.js';
5
- import { RuntimeBridge } from './base.js';
6
- export class HttpBridge extends RuntimeBridge {
7
- baseURL;
8
- headers;
9
- timeoutMs;
10
- constructor(options = { baseURL: 'http://localhost:8000' }) {
11
- super();
12
- this.baseURL = options.baseURL.replace(/\/$/, '');
13
- this.headers = { 'content-type': 'application/json', ...(options.headers ?? {}) };
14
- this.timeoutMs = options.timeoutMs ?? 30000;
15
- }
16
- async call(module, functionName, args, kwargs) {
17
- const payload = { module, functionName, args, kwargs };
18
- const res = await this.post(`${this.baseURL}/call`, payload);
19
- return (await decodeValueAsync(res));
20
- }
21
- async instantiate(module, className, args, kwargs) {
22
- const payload = { module, className, args, kwargs };
23
- const res = await this.post(`${this.baseURL}/instantiate`, payload);
24
- return (await decodeValueAsync(res));
25
- }
26
- async callMethod(handle, methodName, args, kwargs) {
27
- const payload = { handle, methodName, args, kwargs };
28
- const res = await this.post(`${this.baseURL}/call_method`, payload);
29
- return (await decodeValueAsync(res));
30
- }
31
- async disposeInstance(handle) {
32
- const payload = { handle };
33
- await this.post(`${this.baseURL}/dispose_instance`, payload);
34
- }
35
- async dispose() {
36
- // stateless
37
- }
38
- async post(url, body) {
39
- const controller = typeof AbortController !== 'undefined' ? new AbortController() : undefined;
40
- const timer = controller ? setTimeout(() => controller.abort(), this.timeoutMs) : undefined;
41
- try {
42
- const resp = await fetch(url, {
43
- method: 'POST',
44
- headers: this.headers,
45
- body: JSON.stringify(body),
46
- signal: controller?.signal,
47
- });
48
- if (!resp.ok) {
49
- const text = await safeText(resp);
50
- throw new Error(`HTTP ${resp.status}: ${text || resp.statusText}`);
51
- }
52
- const ct = resp.headers.get('content-type') ?? '';
53
- if (ct.includes('application/json')) {
54
- return (await resp.json());
55
- }
56
- const text = await resp.text();
57
- try {
58
- return JSON.parse(text);
59
- }
60
- catch {
61
- return text;
62
- }
63
- }
64
- finally {
65
- if (timer) {
66
- clearTimeout(timer);
67
- }
68
- }
69
- }
70
- }
71
- async function safeText(resp) {
72
- try {
73
- return await resp.text();
74
- }
75
- catch {
76
- return '';
9
+ import { BridgeProtocol } from './bridge-protocol.js';
10
+ import { HttpIO } from './http-io.js';
11
+ // =============================================================================
12
+ // HTTP BRIDGE
13
+ // =============================================================================
14
+ /**
15
+ * HTTP-based runtime bridge for executing Python code.
16
+ *
17
+ * HttpBridge provides a stateless HTTP transport for communication with
18
+ * a Python server. Each request is independent - no connection state is
19
+ * maintained between calls.
20
+ *
21
+ * Features:
22
+ * - Stateless HTTP POST communication
23
+ * - Timeout handling via AbortController
24
+ * - Full SafeCodec validation (NaN/Infinity rejection, key validation)
25
+ * - Automatic Arrow decoding for DataFrames/ndarrays
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const bridge = new HttpBridge({ baseURL: 'http://localhost:8000' });
30
+ * await bridge.init();
31
+ *
32
+ * const result = await bridge.call('math', 'sqrt', [16]);
33
+ * console.log(result); // 4.0
34
+ *
35
+ * await bridge.dispose();
36
+ * ```
37
+ */
38
+ export class HttpBridge extends BridgeProtocol {
39
+ /**
40
+ * Create a new HttpBridge instance.
41
+ *
42
+ * @param options - Configuration options for the bridge
43
+ */
44
+ constructor(options) {
45
+ // Create HTTP transport
46
+ const transport = new HttpIO({
47
+ baseURL: options.baseURL,
48
+ headers: options.headers,
49
+ defaultTimeoutMs: options.timeoutMs,
50
+ });
51
+ // Initialize BridgeProtocol with transport and codec options
52
+ const protocolOptions = {
53
+ transport,
54
+ codec: options.codec,
55
+ defaultTimeoutMs: options.timeoutMs,
56
+ };
57
+ super(protocolOptions);
77
58
  }
78
59
  }
79
60
  //# sourceMappingURL=http.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/runtime/http.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/runtime/http.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,cAAc,EAA8B,MAAM,sBAAsB,CAAC;AAClF,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAwBtC,gFAAgF;AAChF,cAAc;AACd,gFAAgF;AAEhF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,OAAO,UAAW,SAAQ,cAAc;IAC5C;;;;OAIG;IACH,YAAY,OAA0B;QACpC,wBAAwB;QACxB,MAAM,SAAS,GAAG,IAAI,MAAM,CAAC;YAC3B,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,gBAAgB,EAAE,OAAO,CAAC,SAAS;SACpC,CAAC,CAAC;QAEH,6DAA6D;QAC7D,MAAM,eAAe,GAA0B;YAC7C,SAAS;YACT,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,gBAAgB,EAAE,OAAO,CAAC,SAAS;SACpC,CAAC;QAEF,KAAK,CAAC,eAAe,CAAC,CAAC;IACzB,CAAC;CACF"}
@@ -1,29 +1,23 @@
1
1
  /**
2
- * Node.js Runtime Bridge with Optional Connection Pooling
2
+ * Node.js runtime bridge for BridgeProtocol.
3
3
  *
4
- * NodeBridge is the unified Node.js runtime bridge that supports both single-process
5
- * (correctness-first) and multi-process (pooled) configurations. By default, it runs
6
- * in single-process mode for maximum compatibility with the original NodeBridge behavior.
4
+ * NodeBridge extends BridgeProtocol and uses ProcessIO transports with
5
+ * optional pooling for concurrent Python execution.
7
6
  *
8
- * For high-throughput workloads, configure pooling via minProcesses/maxProcesses options.
7
+ * @see https://github.com/bbopen/tywrap/issues/149
9
8
  */
10
- import type { BridgeInfo } from '../types/index.js';
11
- import { RuntimeBridge } from './base.js';
9
+ import { BridgeProtocol } from './bridge-protocol.js';
10
+ import type { CodecOptions } from './safe-codec.js';
12
11
  /**
13
12
  * Configuration options for NodeBridge.
14
- *
15
- * By default, NodeBridge runs in single-process mode (minProcesses=1, maxProcesses=1).
16
- * For high-throughput workloads, increase these values to enable process pooling.
17
13
  */
18
14
  export interface NodeBridgeOptions {
19
15
  /** Minimum number of Python processes to keep alive. Default: 1 */
20
16
  minProcesses?: number;
21
17
  /** Maximum number of Python processes to spawn. Default: 1 (single-process mode) */
22
18
  maxProcesses?: number;
23
- /** Time in ms to keep idle processes alive before termination. Default: 300000 (5 min) */
24
- maxIdleTime?: number;
25
- /** Restart process after this many requests. Default: 1000 */
26
- maxRequestsPerProcess?: number;
19
+ /** Maximum concurrent requests per process. Default: 10 */
20
+ maxConcurrentPerProcess?: number;
27
21
  /** Path to Python executable. Auto-detected if not specified. */
28
22
  pythonPath?: string;
29
23
  /** Path to python_bridge.py script. Auto-detected if not specified. */
@@ -34,161 +28,134 @@ export interface NodeBridgeOptions {
34
28
  cwd?: string;
35
29
  /** Timeout in ms for Python calls. Default: 30000 */
36
30
  timeoutMs?: number;
37
- /** Maximum line length for JSONL protocol. */
38
- maxLineLength?: number;
31
+ /** Timeout in ms for waiting in pool queue. Default: 30000 */
32
+ queueTimeoutMs?: number;
39
33
  /** Inherit all environment variables from parent process. Default: false */
40
34
  inheritProcessEnv?: boolean;
41
- /**
42
- * When true, sets TYWRAP_CODEC_FALLBACK=json for the Python process to prefer JSON encoding
43
- * for rich types (ndarray/dataframe/series). Default: false for fast-fail on Arrow path issues.
44
- */
45
- enableJsonFallback?: boolean;
46
35
  /** Enable result caching for pure functions. Default: false */
47
36
  enableCache?: boolean;
48
37
  /** Optional extra environment variables to pass to the Python subprocess. */
49
38
  env?: Record<string, string | undefined>;
39
+ /** Codec options for validation/serialization */
40
+ codec?: CodecOptions;
50
41
  /** Commands to run on each process at startup for warming up. */
51
42
  warmupCommands?: Array<{
43
+ module: string;
44
+ functionName: string;
45
+ args?: unknown[];
46
+ } | {
52
47
  method: string;
53
48
  params: unknown;
54
49
  }>;
55
- }
56
- interface BridgeStats {
57
- totalRequests: number;
58
- totalTime: number;
59
- cacheHits: number;
60
- poolHits: number;
61
- poolMisses: number;
62
- processSpawns: number;
63
- processDeaths: number;
64
- memoryPeak: number;
65
- averageTime: number;
66
- cacheHitRate: number;
67
- }
68
- interface BridgeStatsSnapshot extends BridgeStats {
69
- poolSize: number;
70
- busyWorkers: number;
71
- memoryUsage: NodeJS.MemoryUsage;
72
- workerStats: Array<{
73
- id: string;
74
- requestCount: number;
75
- averageTime: number;
76
- errorCount: number;
77
- busy: boolean;
78
- pendingRequests: number;
79
- }>;
50
+ /**
51
+ * @deprecated No longer used. Pool idle time is managed by WorkerPool.
52
+ */
53
+ maxIdleTime?: number;
54
+ /**
55
+ * @deprecated No longer used. Process restart is managed by ProcessIO.
56
+ */
57
+ maxRequestsPerProcess?: number;
58
+ /**
59
+ * @deprecated Use codec.bytesHandling option instead.
60
+ */
61
+ enableJsonFallback?: boolean;
62
+ /**
63
+ * @deprecated Use ProcessIO options instead.
64
+ */
65
+ maxLineLength?: number;
80
66
  }
81
67
  /**
82
68
  * Node.js runtime bridge for executing Python code.
83
69
  *
84
- * By default, runs in single-process mode for correctness-first behavior.
85
- * Configure minProcesses/maxProcesses for process pooling in high-throughput scenarios.
70
+ * NodeBridge provides subprocess-based Python execution with optional pooling
71
+ * for high-throughput workloads. By default, it runs in single-process mode.
72
+ *
73
+ * Features:
74
+ * - Single or multi-process execution via process pooling
75
+ * - Virtual environment support
76
+ * - Full SafeCodec validation (NaN/Infinity rejection, key validation)
77
+ * - Automatic Arrow decoding for DataFrames/ndarrays
78
+ * - Optional result caching for pure functions
79
+ * - Process warmup commands
86
80
  *
87
81
  * @example
88
82
  * ```typescript
89
83
  * // Single-process mode (default)
90
84
  * const bridge = new NodeBridge();
85
+ * await bridge.init();
91
86
  *
87
+ * const result = await bridge.call('math', 'sqrt', [16]);
88
+ * console.log(result); // 4.0
89
+ *
90
+ * await bridge.dispose();
91
+ * ```
92
+ *
93
+ * @example
94
+ * ```typescript
92
95
  * // Multi-process pooling for high throughput
93
96
  * const pooledBridge = new NodeBridge({
94
- * minProcesses: 2,
95
- * maxProcesses: 8,
97
+ * maxProcesses: 4,
98
+ * maxConcurrentPerProcess: 2,
96
99
  * enableCache: true,
97
100
  * });
101
+ * await pooledBridge.init();
98
102
  * ```
99
103
  */
100
- export declare class NodeBridge extends RuntimeBridge {
101
- private processPool;
102
- private roundRobinIndex;
103
- private cleanupTimer?;
104
- private options;
105
- private emitter;
106
- private disposed;
107
- private bridgeInfo?;
108
- private initPromise?;
109
- private stats;
110
- constructor(options?: NodeBridgeOptions);
111
- init(): Promise<void>;
112
- private doInit;
113
- getBridgeInfo(options?: {
114
- refresh?: boolean;
115
- }): Promise<BridgeInfo>;
116
- call<T = unknown>(module: string, functionName: string, args: unknown[], kwargs?: Record<string, unknown>): Promise<T>;
117
- instantiate<T = unknown>(module: string, className: string, args: unknown[], kwargs?: Record<string, unknown>): Promise<T>;
118
- callMethod<T = unknown>(handle: string, methodName: string, args: unknown[], kwargs?: Record<string, unknown>): Promise<T>;
119
- disposeInstance(handle: string): Promise<void>;
120
- /**
121
- * Execute request with intelligent process selection
122
- */
123
- private executeRequest;
124
- /**
125
- * Select optimal worker based on load and performance
126
- */
127
- private selectOptimalWorker;
128
- /**
129
- * Wait for any worker to become available
130
- */
131
- private waitForAvailableWorker;
104
+ export declare class NodeBridge extends BridgeProtocol {
105
+ private readonly resolvedOptions;
106
+ private readonly pooledTransport;
132
107
  /**
133
- * Send request to specific worker
108
+ * Create a new NodeBridge instance.
109
+ *
110
+ * @param options - Configuration options for the bridge
134
111
  */
135
- private sendToWorker;
136
- private quarantineWorker;
112
+ constructor(options?: NodeBridgeOptions);
137
113
  /**
138
- * Spawn new worker process with optimizations
114
+ * Initialize the bridge.
115
+ *
116
+ * Validates the bridge script exists, registers Arrow decoder,
117
+ * and initializes the transport pool (which runs warmup commands per-worker).
139
118
  */
140
- private spawnProcess;
119
+ protected doInit(): Promise<void>;
141
120
  /**
142
- * Setup event handlers for worker process
121
+ * Override call() to add optional caching.
143
122
  */
144
- private setupProcessHandlers;
123
+ call<T = unknown>(module: string, functionName: string, args: unknown[], kwargs?: Record<string, unknown>): Promise<T>;
145
124
  /**
146
- * Handle worker process exit
147
- */
148
- private handleWorkerExit;
125
+ * Get current pool statistics.
126
+ */
127
+ getPoolStats(): {
128
+ workerCount: number;
129
+ queueLength: number;
130
+ totalInFlight: number;
131
+ };
132
+ /**
133
+ * Get bridge statistics.
134
+ *
135
+ * @deprecated Use getPoolStats() instead. This method is provided for
136
+ * backwards compatibility and returns a subset of the previous stats.
137
+ */
138
+ getStats(): {
139
+ totalRequests: number;
140
+ totalTime: number;
141
+ cacheHits: number;
142
+ poolHits: number;
143
+ poolMisses: number;
144
+ processSpawns: number;
145
+ processDeaths: number;
146
+ memoryPeak: number;
147
+ averageTime: number;
148
+ cacheHitRate: number;
149
+ poolSize: number;
150
+ busyWorkers: number;
151
+ };
149
152
  /**
150
- * Warm up processes with configured commands
153
+ * Generate a cache key, returning null if generation fails.
151
154
  */
152
- private warmupProcesses;
153
155
  private safeCacheKey;
154
156
  /**
155
- * Heuristic to determine if function result should be cached
157
+ * Heuristic to determine if function result should be cached.
156
158
  */
157
159
  private isPureFunctionCandidate;
158
- /**
159
- * Update performance statistics
160
- */
161
- private updateStats;
162
- /**
163
- * Get performance statistics
164
- */
165
- getStats(): BridgeStatsSnapshot;
166
- /**
167
- * Cleanup idle processes
168
- */
169
- private cleanup;
170
- /**
171
- * Gracefully terminate a worker
172
- */
173
- private terminateWorker;
174
- /**
175
- * Start cleanup scheduler
176
- */
177
- private startCleanupScheduler;
178
- /**
179
- * Dispose all resources
180
- */
181
- dispose(): Promise<void>;
182
- private buildEnv;
183
- private refreshBridgeInfo;
184
160
  }
185
- /**
186
- * @deprecated Use NodeBridge with minProcesses/maxProcesses options instead.
187
- * This alias is provided for backward compatibility.
188
- */
189
- export { NodeBridge as OptimizedNodeBridge };
190
- /**
191
- * @deprecated Use NodeBridgeOptions instead.
192
- */
193
- export type { NodeBridgeOptions as ProcessPoolOptions };
194
161
  //# sourceMappingURL=node.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/runtime/node.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/runtime/node.ts"],"names":[],"mappings":"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"}