tywrap 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/README.md +65 -31
  2. package/dist/cli.js +49 -2
  3. package/dist/cli.js.map +1 -1
  4. package/dist/config/index.d.ts +11 -7
  5. package/dist/config/index.d.ts.map +1 -1
  6. package/dist/config/index.js +43 -7
  7. package/dist/config/index.js.map +1 -1
  8. package/dist/core/analyzer.d.ts +1 -0
  9. package/dist/core/analyzer.d.ts.map +1 -1
  10. package/dist/core/analyzer.js +47 -12
  11. package/dist/core/analyzer.js.map +1 -1
  12. package/dist/core/annotation-parser.d.ts +8 -0
  13. package/dist/core/annotation-parser.d.ts.map +1 -0
  14. package/dist/core/annotation-parser.js +409 -0
  15. package/dist/core/annotation-parser.js.map +1 -0
  16. package/dist/core/discovery.d.ts +1 -0
  17. package/dist/core/discovery.d.ts.map +1 -1
  18. package/dist/core/discovery.js +9 -9
  19. package/dist/core/discovery.js.map +1 -1
  20. package/dist/core/generator.d.ts +9 -1
  21. package/dist/core/generator.d.ts.map +1 -1
  22. package/dist/core/generator.js +738 -104
  23. package/dist/core/generator.js.map +1 -1
  24. package/dist/core/mapper.d.ts +9 -7
  25. package/dist/core/mapper.d.ts.map +1 -1
  26. package/dist/core/mapper.js +129 -44
  27. package/dist/core/mapper.js.map +1 -1
  28. package/dist/index.d.ts +23 -7
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +23 -3
  31. package/dist/index.js.map +1 -1
  32. package/dist/runtime/base.d.ts +17 -7
  33. package/dist/runtime/base.d.ts.map +1 -1
  34. package/dist/runtime/base.js +18 -1
  35. package/dist/runtime/base.js.map +1 -1
  36. package/dist/runtime/bounded-context.d.ts +252 -0
  37. package/dist/runtime/bounded-context.d.ts.map +1 -0
  38. package/dist/runtime/bounded-context.js +454 -0
  39. package/dist/runtime/bounded-context.js.map +1 -0
  40. package/dist/runtime/bridge-core.d.ts +1 -0
  41. package/dist/runtime/bridge-core.d.ts.map +1 -1
  42. package/dist/runtime/bridge-core.js +52 -17
  43. package/dist/runtime/bridge-core.js.map +1 -1
  44. package/dist/runtime/bridge-protocol.d.ts +184 -0
  45. package/dist/runtime/bridge-protocol.d.ts.map +1 -0
  46. package/dist/runtime/bridge-protocol.js +344 -0
  47. package/dist/runtime/bridge-protocol.js.map +1 -0
  48. package/dist/runtime/disposable.d.ts +40 -0
  49. package/dist/runtime/disposable.d.ts.map +1 -0
  50. package/dist/runtime/disposable.js +49 -0
  51. package/dist/runtime/disposable.js.map +1 -0
  52. package/dist/runtime/errors.d.ts +10 -0
  53. package/dist/runtime/errors.d.ts.map +1 -1
  54. package/dist/runtime/errors.js +9 -0
  55. package/dist/runtime/errors.js.map +1 -1
  56. package/dist/runtime/http-io.d.ts +91 -0
  57. package/dist/runtime/http-io.d.ts.map +1 -0
  58. package/dist/runtime/http-io.js +195 -0
  59. package/dist/runtime/http-io.js.map +1 -0
  60. package/dist/runtime/http.d.ts +48 -13
  61. package/dist/runtime/http.d.ts.map +1 -1
  62. package/dist/runtime/http.js +60 -73
  63. package/dist/runtime/http.js.map +1 -1
  64. package/dist/runtime/node.d.ts +97 -130
  65. package/dist/runtime/node.d.ts.map +1 -1
  66. package/dist/runtime/node.js +392 -521
  67. package/dist/runtime/node.js.map +1 -1
  68. package/dist/runtime/optimized-node.d.ts +1 -1
  69. package/dist/runtime/optimized-node.d.ts.map +1 -1
  70. package/dist/runtime/optimized-node.js +1 -1
  71. package/dist/runtime/optimized-node.js.map +1 -1
  72. package/dist/runtime/pooled-transport.d.ts +135 -0
  73. package/dist/runtime/pooled-transport.d.ts.map +1 -0
  74. package/dist/runtime/pooled-transport.js +177 -0
  75. package/dist/runtime/pooled-transport.js.map +1 -0
  76. package/dist/runtime/process-io.d.ts +209 -0
  77. package/dist/runtime/process-io.d.ts.map +1 -0
  78. package/dist/runtime/process-io.js +729 -0
  79. package/dist/runtime/process-io.js.map +1 -0
  80. package/dist/runtime/pyodide-io.d.ts +154 -0
  81. package/dist/runtime/pyodide-io.d.ts.map +1 -0
  82. package/dist/runtime/pyodide-io.js +459 -0
  83. package/dist/runtime/pyodide-io.js.map +1 -0
  84. package/dist/runtime/pyodide.d.ts +51 -19
  85. package/dist/runtime/pyodide.d.ts.map +1 -1
  86. package/dist/runtime/pyodide.js +57 -186
  87. package/dist/runtime/pyodide.js.map +1 -1
  88. package/dist/runtime/safe-codec.d.ts +103 -0
  89. package/dist/runtime/safe-codec.d.ts.map +1 -0
  90. package/dist/runtime/safe-codec.js +519 -0
  91. package/dist/runtime/safe-codec.js.map +1 -0
  92. package/dist/runtime/transport.d.ts +191 -0
  93. package/dist/runtime/transport.d.ts.map +1 -0
  94. package/dist/runtime/transport.js +86 -0
  95. package/dist/runtime/transport.js.map +1 -0
  96. package/dist/runtime/validators.d.ts +120 -0
  97. package/dist/runtime/validators.d.ts.map +1 -0
  98. package/dist/runtime/validators.js +229 -0
  99. package/dist/runtime/validators.js.map +1 -0
  100. package/dist/runtime/worker-pool.d.ts +208 -0
  101. package/dist/runtime/worker-pool.d.ts.map +1 -0
  102. package/dist/runtime/worker-pool.js +419 -0
  103. package/dist/runtime/worker-pool.js.map +1 -0
  104. package/dist/types/index.d.ts +51 -1
  105. package/dist/types/index.d.ts.map +1 -1
  106. package/dist/tywrap.d.ts.map +1 -1
  107. package/dist/tywrap.js +227 -328
  108. package/dist/tywrap.js.map +1 -1
  109. package/dist/utils/cache.d.ts.map +1 -1
  110. package/dist/utils/cache.js +53 -5
  111. package/dist/utils/cache.js.map +1 -1
  112. package/dist/utils/codec.d.ts.map +1 -1
  113. package/dist/utils/codec.js +114 -1
  114. package/dist/utils/codec.js.map +1 -1
  115. package/dist/utils/ir-cache.d.ts +28 -0
  116. package/dist/utils/ir-cache.d.ts.map +1 -0
  117. package/dist/utils/ir-cache.js +29 -0
  118. package/dist/utils/ir-cache.js.map +1 -0
  119. package/dist/utils/parallel-processor.d.ts +1 -1
  120. package/dist/utils/parallel-processor.d.ts.map +1 -1
  121. package/dist/utils/parallel-processor.js +111 -40
  122. package/dist/utils/parallel-processor.js.map +1 -1
  123. package/dist/utils/runtime.d.ts +5 -1
  124. package/dist/utils/runtime.d.ts.map +1 -1
  125. package/dist/utils/runtime.js +112 -18
  126. package/dist/utils/runtime.js.map +1 -1
  127. package/package.json +40 -18
  128. package/runtime/python_bridge.py +108 -15
  129. package/runtime/safe_codec.py +344 -0
  130. package/src/cli.ts +61 -2
  131. package/src/config/index.ts +63 -17
  132. package/src/core/analyzer.ts +52 -15
  133. package/src/core/annotation-parser.ts +500 -0
  134. package/src/core/discovery.ts +26 -12
  135. package/src/core/generator.ts +956 -116
  136. package/src/core/mapper.ts +158 -51
  137. package/src/index.ts +78 -6
  138. package/src/runtime/base.ts +18 -26
  139. package/src/runtime/bounded-context.ts +608 -0
  140. package/src/runtime/bridge-core.ts +58 -18
  141. package/src/runtime/bridge-protocol.ts +483 -0
  142. package/src/runtime/disposable.ts +65 -0
  143. package/src/runtime/errors.ts +14 -0
  144. package/src/runtime/http-io.ts +245 -0
  145. package/src/runtime/http.ts +76 -115
  146. package/src/runtime/node.ts +563 -676
  147. package/src/runtime/optimized-node.ts +4 -1
  148. package/src/runtime/pooled-transport.ts +263 -0
  149. package/src/runtime/process-io.ts +930 -0
  150. package/src/runtime/pyodide-io.ts +551 -0
  151. package/src/runtime/pyodide.ts +75 -215
  152. package/src/runtime/safe-codec.ts +651 -0
  153. package/src/runtime/transport.ts +278 -0
  154. package/src/runtime/validators.ts +252 -0
  155. package/src/runtime/worker-pool.ts +559 -0
  156. package/src/types/global.d.ts +11 -1
  157. package/src/types/index.ts +63 -0
  158. package/src/tywrap.ts +279 -358
  159. package/src/utils/cache.ts +59 -5
  160. package/src/utils/codec.ts +122 -1
  161. package/src/utils/ir-cache.ts +51 -0
  162. package/src/utils/parallel-processor.ts +119 -43
  163. package/src/utils/runtime.ts +129 -18
@@ -18,4 +18,7 @@
18
18
  *
19
19
  * This file is maintained for backward compatibility only.
20
20
  */
21
- export { NodeBridge as OptimizedNodeBridge, type NodeBridgeOptions as ProcessPoolOptions } from './node.js';
21
+ export {
22
+ NodeBridge as OptimizedNodeBridge,
23
+ type NodeBridgeOptions as ProcessPoolOptions,
24
+ } from './node.js';
@@ -0,0 +1,263 @@
1
+ /**
2
+ * PooledTransport - Transport adapter that wraps WorkerPool for multi-process support.
3
+ *
4
+ * This transport implements the Transport interface by delegating to a WorkerPool
5
+ * of ProcessIO transports. Each send() acquires a worker, sends the message,
6
+ * and releases the worker back to the pool.
7
+ *
8
+ * @see https://github.com/bbopen/tywrap/issues/149
9
+ */
10
+
11
+ import { BoundedContext } from './bounded-context.js';
12
+ import { BridgeDisposedError, BridgeExecutionError } from './errors.js';
13
+ import type { Transport } from './transport.js';
14
+ import { WorkerPool, type PooledWorker } from './worker-pool.js';
15
+
16
+ // =============================================================================
17
+ // TYPES
18
+ // =============================================================================
19
+
20
+ /**
21
+ * Options for creating a PooledTransport.
22
+ */
23
+ export interface PooledTransportOptions {
24
+ /** Factory function to create transports for each worker */
25
+ createTransport: () => Transport;
26
+
27
+ /** Maximum number of workers in the pool. Default: 1 */
28
+ maxWorkers?: number;
29
+
30
+ /** Minimum number of workers to pre-spawn during init. Default: 0 (lazy) */
31
+ minWorkers?: number;
32
+
33
+ /** Timeout for waiting in queue (ms). Default: 30000 */
34
+ queueTimeoutMs?: number;
35
+
36
+ /** Maximum concurrent requests per worker. Default: 10 */
37
+ maxConcurrentPerWorker?: number;
38
+
39
+ /**
40
+ * Callback invoked after each worker is created and initialized.
41
+ * Use this for per-worker warmup (e.g., importing modules, running setup).
42
+ */
43
+ onWorkerReady?: (worker: PooledWorker) => Promise<void>;
44
+
45
+ /**
46
+ * Optional callback used only for background replacement workers.
47
+ */
48
+ onReplacementWorkerReady?: (worker: PooledWorker) => Promise<void>;
49
+ }
50
+
51
+ // =============================================================================
52
+ // POOLED TRANSPORT
53
+ // =============================================================================
54
+
55
+ /**
56
+ * Transport adapter that wraps WorkerPool for multi-process message handling.
57
+ *
58
+ * PooledTransport presents a single Transport interface while internally
59
+ * distributing requests across multiple worker transports (typically ProcessIO).
60
+ *
61
+ * Features:
62
+ * - Lazy worker creation (transports created on demand)
63
+ * - Configurable pool size and concurrency per worker
64
+ * - Automatic worker acquisition and release
65
+ * - Queue timeout for backpressure management
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * const transport = new PooledTransport({
70
+ * createTransport: () => new ProcessIO({
71
+ * bridgeScript: '/path/to/bridge.py',
72
+ * }),
73
+ * maxWorkers: 4,
74
+ * maxConcurrentPerWorker: 2,
75
+ * });
76
+ *
77
+ * await transport.init();
78
+ *
79
+ * // send() automatically uses pool
80
+ * const response = await transport.send(message, timeout);
81
+ *
82
+ * await transport.dispose();
83
+ * ```
84
+ */
85
+ export class PooledTransport extends BoundedContext implements Transport {
86
+ private readonly poolOptions: Omit<
87
+ Required<PooledTransportOptions>,
88
+ 'onWorkerReady' | 'onReplacementWorkerReady'
89
+ > & {
90
+ onWorkerReady?: (worker: PooledWorker) => Promise<void>;
91
+ onReplacementWorkerReady?: (worker: PooledWorker) => Promise<void>;
92
+ };
93
+ private pool?: WorkerPool;
94
+
95
+ /**
96
+ * Create a new PooledTransport.
97
+ *
98
+ * @param options - Pool configuration options
99
+ */
100
+ constructor(options: PooledTransportOptions) {
101
+ super();
102
+
103
+ if (typeof options.createTransport !== 'function') {
104
+ throw new BridgeExecutionError('createTransport must be a function');
105
+ }
106
+
107
+ this.poolOptions = {
108
+ createTransport: options.createTransport,
109
+ maxWorkers: options.maxWorkers ?? 1,
110
+ minWorkers: options.minWorkers ?? 0,
111
+ queueTimeoutMs: options.queueTimeoutMs ?? 30000,
112
+ maxConcurrentPerWorker: options.maxConcurrentPerWorker ?? 10,
113
+ onWorkerReady: options.onWorkerReady,
114
+ onReplacementWorkerReady: options.onReplacementWorkerReady,
115
+ };
116
+ }
117
+
118
+ // ===========================================================================
119
+ // LIFECYCLE
120
+ // ===========================================================================
121
+
122
+ /**
123
+ * Initialize the pooled transport.
124
+ *
125
+ * Creates and initializes the internal WorkerPool.
126
+ * If minWorkers > 0, workers are pre-spawned during init.
127
+ */
128
+ protected async doInit(): Promise<void> {
129
+ this.pool = new WorkerPool({
130
+ createTransport: this.poolOptions.createTransport,
131
+ maxWorkers: this.poolOptions.maxWorkers,
132
+ minWorkers: this.poolOptions.minWorkers,
133
+ queueTimeoutMs: this.poolOptions.queueTimeoutMs,
134
+ maxConcurrentPerWorker: this.poolOptions.maxConcurrentPerWorker,
135
+ onWorkerReady: this.poolOptions.onWorkerReady,
136
+ onReplacementWorkerReady: this.poolOptions.onReplacementWorkerReady,
137
+ });
138
+
139
+ await this.pool.init();
140
+ }
141
+
142
+ /**
143
+ * Dispose the pooled transport.
144
+ *
145
+ * Disposes the internal WorkerPool, which disposes all workers.
146
+ */
147
+ protected async doDispose(): Promise<void> {
148
+ if (this.pool) {
149
+ await this.pool.dispose();
150
+ this.pool = undefined;
151
+ }
152
+ }
153
+
154
+ // ===========================================================================
155
+ // TRANSPORT INTERFACE
156
+ // ===========================================================================
157
+
158
+ /**
159
+ * Send a message through a pooled worker.
160
+ *
161
+ * This method:
162
+ * 1. Acquires a worker from the pool (waiting if necessary)
163
+ * 2. Sends the message through the worker's transport
164
+ * 3. Releases the worker back to the pool
165
+ *
166
+ * @param message - The JSON-encoded protocol message
167
+ * @param timeoutMs - Timeout in milliseconds (0 = no timeout)
168
+ * @param signal - Optional AbortSignal for cancellation
169
+ * @returns The raw JSON response string
170
+ *
171
+ * @throws BridgeDisposedError if transport is disposed
172
+ * @throws BridgeTimeoutError if queue timeout or request timeout expires
173
+ */
174
+ async send(message: string, timeoutMs: number, signal?: AbortSignal): Promise<string> {
175
+ if (this.isDisposed || !this.pool) {
176
+ throw new BridgeDisposedError('Transport has been disposed');
177
+ }
178
+
179
+ return this.pool.withWorker(async worker => {
180
+ return worker.transport.send(message, timeoutMs, signal);
181
+ });
182
+ }
183
+
184
+ // ===========================================================================
185
+ // POOL STATISTICS
186
+ // ===========================================================================
187
+
188
+ /**
189
+ * Current number of workers in the pool.
190
+ */
191
+ get workerCount(): number {
192
+ return this.pool?.workerCount ?? 0;
193
+ }
194
+
195
+ /**
196
+ * Number of callers waiting in the queue.
197
+ */
198
+ get queueLength(): number {
199
+ return this.pool?.queueLength ?? 0;
200
+ }
201
+
202
+ /**
203
+ * Total number of in-flight requests across all workers.
204
+ */
205
+ get totalInFlight(): number {
206
+ return this.pool?.totalInFlight ?? 0;
207
+ }
208
+
209
+ // ===========================================================================
210
+ // RUNTIME EXECUTION (Not implemented - PooledTransport is just a transport)
211
+ // ===========================================================================
212
+
213
+ /**
214
+ * Not implemented - PooledTransport is a transport, use BridgeProtocol.
215
+ */
216
+ async call<T = unknown>(
217
+ _module: string,
218
+ _functionName: string,
219
+ _args: unknown[],
220
+ _kwargs?: Record<string, unknown>
221
+ ): Promise<T> {
222
+ throw new BridgeExecutionError(
223
+ 'PooledTransport is a transport, use BridgeProtocol for operations'
224
+ );
225
+ }
226
+
227
+ /**
228
+ * Not implemented - PooledTransport is a transport, use BridgeProtocol.
229
+ */
230
+ async instantiate<T = unknown>(
231
+ _module: string,
232
+ _className: string,
233
+ _args: unknown[],
234
+ _kwargs?: Record<string, unknown>
235
+ ): Promise<T> {
236
+ throw new BridgeExecutionError(
237
+ 'PooledTransport is a transport, use BridgeProtocol for operations'
238
+ );
239
+ }
240
+
241
+ /**
242
+ * Not implemented - PooledTransport is a transport, use BridgeProtocol.
243
+ */
244
+ async callMethod<T = unknown>(
245
+ _handle: string,
246
+ _methodName: string,
247
+ _args: unknown[],
248
+ _kwargs?: Record<string, unknown>
249
+ ): Promise<T> {
250
+ throw new BridgeExecutionError(
251
+ 'PooledTransport is a transport, use BridgeProtocol for operations'
252
+ );
253
+ }
254
+
255
+ /**
256
+ * Not implemented - PooledTransport is a transport, use BridgeProtocol.
257
+ */
258
+ async disposeInstance(_handle: string): Promise<void> {
259
+ throw new BridgeExecutionError(
260
+ 'PooledTransport is a transport, use BridgeProtocol for operations'
261
+ );
262
+ }
263
+ }