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
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Pure validation functions for runtime value checking.
3
+ *
4
+ * These functions are used by BoundedContext and can also be used
5
+ * independently for validation in CLI tools, config loading, etc.
6
+ */
7
+ /**
8
+ * Error thrown when validation fails.
9
+ */
10
+ export declare class ValidationError extends Error {
11
+ constructor(message: string);
12
+ }
13
+ /**
14
+ * Check if a value is a finite number (not NaN, not Infinity).
15
+ */
16
+ export declare function isFiniteNumber(value: unknown): value is number;
17
+ /**
18
+ * Check if a value is a positive finite number.
19
+ */
20
+ export declare function isPositiveNumber(value: unknown): value is number;
21
+ /**
22
+ * Check if a value is a non-negative finite number.
23
+ */
24
+ export declare function isNonNegativeNumber(value: unknown): value is number;
25
+ /**
26
+ * Check if a value is a non-empty string.
27
+ */
28
+ export declare function isNonEmptyString(value: unknown): value is string;
29
+ /**
30
+ * Check if a value is a plain object (not null, not array).
31
+ */
32
+ export declare function isPlainObject(value: unknown): value is Record<string, unknown>;
33
+ /**
34
+ * Assert that a value is a finite number.
35
+ *
36
+ * @param value - The value to check
37
+ * @param name - The name of the parameter (for error messages)
38
+ * @returns The value as a number
39
+ * @throws ValidationError if the value is not a finite number
40
+ */
41
+ export declare function assertFiniteNumber(value: unknown, name: string): number;
42
+ /**
43
+ * Assert that a value is a positive number (> 0).
44
+ *
45
+ * @param value - The value to check
46
+ * @param name - The name of the parameter (for error messages)
47
+ * @returns The value as a number
48
+ * @throws ValidationError if the value is not a positive number
49
+ */
50
+ export declare function assertPositive(value: unknown, name: string): number;
51
+ /**
52
+ * Assert that a value is a non-negative number (>= 0).
53
+ *
54
+ * @param value - The value to check
55
+ * @param name - The name of the parameter (for error messages)
56
+ * @returns The value as a number
57
+ * @throws ValidationError if the value is not a non-negative number
58
+ */
59
+ export declare function assertNonNegative(value: unknown, name: string): number;
60
+ /**
61
+ * Assert that a value is a string.
62
+ *
63
+ * @param value - The value to check
64
+ * @param name - The name of the parameter (for error messages)
65
+ * @returns The value as a string
66
+ * @throws ValidationError if the value is not a string
67
+ */
68
+ export declare function assertString(value: unknown, name: string): string;
69
+ /**
70
+ * Assert that a value is a non-empty string.
71
+ *
72
+ * @param value - The value to check
73
+ * @param name - The name of the parameter (for error messages)
74
+ * @returns The value as a string
75
+ * @throws ValidationError if the value is not a non-empty string
76
+ */
77
+ export declare function assertNonEmptyString(value: unknown, name: string): string;
78
+ /**
79
+ * Assert that a value is an array.
80
+ *
81
+ * @param value - The value to check
82
+ * @param name - The name of the parameter (for error messages)
83
+ * @returns The value as an array
84
+ * @throws ValidationError if the value is not an array
85
+ */
86
+ export declare function assertArray<T = unknown>(value: unknown, name: string): T[];
87
+ /**
88
+ * Assert that a value is a plain object (not null, not array).
89
+ *
90
+ * @param value - The value to check
91
+ * @param name - The name of the parameter (for error messages)
92
+ * @returns The value as a Record
93
+ * @throws ValidationError if the value is not a plain object
94
+ */
95
+ export declare function assertObject(value: unknown, name: string): Record<string, unknown>;
96
+ /**
97
+ * Check if a value contains non-finite numbers (NaN, Infinity, -Infinity).
98
+ * Recursively checks arrays and objects.
99
+ *
100
+ * This is used to detect values that cannot be safely serialized to JSON,
101
+ * as JSON.stringify converts NaN/Infinity to null, which can cause
102
+ * silent data corruption.
103
+ *
104
+ * @param value - The value to check
105
+ * @returns True if the value contains NaN or Infinity anywhere
106
+ */
107
+ export declare function containsSpecialFloat(value: unknown): boolean;
108
+ /**
109
+ * Assert that a value does not contain non-finite numbers.
110
+ *
111
+ * @param value - The value to check
112
+ * @param name - The name of the parameter (for error messages)
113
+ * @throws ValidationError if the value contains NaN or Infinity
114
+ */
115
+ export declare function assertNoSpecialFloats(value: unknown, name: string): void;
116
+ /**
117
+ * Sanitize a string for use in a cache key filename.
118
+ * Removes or replaces characters that could cause path traversal or invalid filenames.
119
+ *
120
+ * @param value - The string to sanitize
121
+ * @returns A safe string for use in filenames
122
+ */
123
+ export declare function sanitizeForFilename(value: string): string;
124
+ /**
125
+ * Check if a string looks like a path traversal attempt.
126
+ *
127
+ * @param value - The string to check
128
+ * @returns True if the string contains path traversal patterns
129
+ */
130
+ export declare function containsPathTraversal(value: string): boolean;
131
+ //# sourceMappingURL=validators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../src/runtime/validators.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAMD;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAE9D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEhE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEnE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEhE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE9E;AAMD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMvE;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMnE;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMtE;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKjE;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMzE;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,EAAE,CAK1E;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMlF;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAW5D;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAMxE;AAMD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMzD;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE5D"}
@@ -0,0 +1,219 @@
1
+ /**
2
+ * Pure validation functions for runtime value checking.
3
+ *
4
+ * These functions are used by BoundedContext and can also be used
5
+ * independently for validation in CLI tools, config loading, etc.
6
+ */
7
+ /**
8
+ * Error thrown when validation fails.
9
+ */
10
+ export class ValidationError extends Error {
11
+ constructor(message) {
12
+ super(message);
13
+ this.name = 'ValidationError';
14
+ }
15
+ }
16
+ // ═══════════════════════════════════════════════════════════════════════════
17
+ // TYPE GUARDS
18
+ // ═══════════════════════════════════════════════════════════════════════════
19
+ /**
20
+ * Check if a value is a finite number (not NaN, not Infinity).
21
+ */
22
+ export function isFiniteNumber(value) {
23
+ return typeof value === 'number' && Number.isFinite(value);
24
+ }
25
+ /**
26
+ * Check if a value is a positive finite number.
27
+ */
28
+ export function isPositiveNumber(value) {
29
+ return isFiniteNumber(value) && value > 0;
30
+ }
31
+ /**
32
+ * Check if a value is a non-negative finite number.
33
+ */
34
+ export function isNonNegativeNumber(value) {
35
+ return isFiniteNumber(value) && value >= 0;
36
+ }
37
+ /**
38
+ * Check if a value is a non-empty string.
39
+ */
40
+ export function isNonEmptyString(value) {
41
+ return typeof value === 'string' && value.length > 0;
42
+ }
43
+ /**
44
+ * Check if a value is a plain object (not null, not array).
45
+ */
46
+ export function isPlainObject(value) {
47
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
48
+ }
49
+ // ═══════════════════════════════════════════════════════════════════════════
50
+ // ASSERTIONS
51
+ // ═══════════════════════════════════════════════════════════════════════════
52
+ /**
53
+ * Assert that a value is a finite number.
54
+ *
55
+ * @param value - The value to check
56
+ * @param name - The name of the parameter (for error messages)
57
+ * @returns The value as a number
58
+ * @throws ValidationError if the value is not a finite number
59
+ */
60
+ export function assertFiniteNumber(value, name) {
61
+ if (!isFiniteNumber(value)) {
62
+ const actual = typeof value === 'number' ? String(value) : typeof value;
63
+ throw new ValidationError(`${name} must be a finite number, got: ${actual}`);
64
+ }
65
+ return value;
66
+ }
67
+ /**
68
+ * Assert that a value is a positive number (> 0).
69
+ *
70
+ * @param value - The value to check
71
+ * @param name - The name of the parameter (for error messages)
72
+ * @returns The value as a number
73
+ * @throws ValidationError if the value is not a positive number
74
+ */
75
+ export function assertPositive(value, name) {
76
+ const num = assertFiniteNumber(value, name);
77
+ if (num <= 0) {
78
+ throw new ValidationError(`${name} must be positive, got: ${num}`);
79
+ }
80
+ return num;
81
+ }
82
+ /**
83
+ * Assert that a value is a non-negative number (>= 0).
84
+ *
85
+ * @param value - The value to check
86
+ * @param name - The name of the parameter (for error messages)
87
+ * @returns The value as a number
88
+ * @throws ValidationError if the value is not a non-negative number
89
+ */
90
+ export function assertNonNegative(value, name) {
91
+ const num = assertFiniteNumber(value, name);
92
+ if (num < 0) {
93
+ throw new ValidationError(`${name} must be non-negative, got: ${num}`);
94
+ }
95
+ return num;
96
+ }
97
+ /**
98
+ * Assert that a value is a string.
99
+ *
100
+ * @param value - The value to check
101
+ * @param name - The name of the parameter (for error messages)
102
+ * @returns The value as a string
103
+ * @throws ValidationError if the value is not a string
104
+ */
105
+ export function assertString(value, name) {
106
+ if (typeof value !== 'string') {
107
+ throw new ValidationError(`${name} must be a string, got: ${typeof value}`);
108
+ }
109
+ return value;
110
+ }
111
+ /**
112
+ * Assert that a value is a non-empty string.
113
+ *
114
+ * @param value - The value to check
115
+ * @param name - The name of the parameter (for error messages)
116
+ * @returns The value as a string
117
+ * @throws ValidationError if the value is not a non-empty string
118
+ */
119
+ export function assertNonEmptyString(value, name) {
120
+ const str = assertString(value, name);
121
+ if (str.length === 0) {
122
+ throw new ValidationError(`${name} must not be empty`);
123
+ }
124
+ return str;
125
+ }
126
+ /**
127
+ * Assert that a value is an array.
128
+ *
129
+ * @param value - The value to check
130
+ * @param name - The name of the parameter (for error messages)
131
+ * @returns The value as an array
132
+ * @throws ValidationError if the value is not an array
133
+ */
134
+ export function assertArray(value, name) {
135
+ if (!Array.isArray(value)) {
136
+ throw new ValidationError(`${name} must be an array, got: ${typeof value}`);
137
+ }
138
+ return value;
139
+ }
140
+ /**
141
+ * Assert that a value is a plain object (not null, not array).
142
+ *
143
+ * @param value - The value to check
144
+ * @param name - The name of the parameter (for error messages)
145
+ * @returns The value as a Record
146
+ * @throws ValidationError if the value is not a plain object
147
+ */
148
+ export function assertObject(value, name) {
149
+ if (!isPlainObject(value)) {
150
+ const actual = value === null ? 'null' : Array.isArray(value) ? 'array' : typeof value;
151
+ throw new ValidationError(`${name} must be an object, got: ${actual}`);
152
+ }
153
+ return value;
154
+ }
155
+ // ═══════════════════════════════════════════════════════════════════════════
156
+ // SPECIAL FLOAT DETECTION (for codec validation)
157
+ // ═══════════════════════════════════════════════════════════════════════════
158
+ /**
159
+ * Check if a value contains non-finite numbers (NaN, Infinity, -Infinity).
160
+ * Recursively checks arrays and objects.
161
+ *
162
+ * This is used to detect values that cannot be safely serialized to JSON,
163
+ * as JSON.stringify converts NaN/Infinity to null, which can cause
164
+ * silent data corruption.
165
+ *
166
+ * @param value - The value to check
167
+ * @returns True if the value contains NaN or Infinity anywhere
168
+ */
169
+ export function containsSpecialFloat(value) {
170
+ if (typeof value === 'number') {
171
+ return !Number.isFinite(value);
172
+ }
173
+ if (Array.isArray(value)) {
174
+ return value.some(containsSpecialFloat);
175
+ }
176
+ if (isPlainObject(value)) {
177
+ return Object.values(value).some(containsSpecialFloat);
178
+ }
179
+ return false;
180
+ }
181
+ /**
182
+ * Assert that a value does not contain non-finite numbers.
183
+ *
184
+ * @param value - The value to check
185
+ * @param name - The name of the parameter (for error messages)
186
+ * @throws ValidationError if the value contains NaN or Infinity
187
+ */
188
+ export function assertNoSpecialFloats(value, name) {
189
+ if (containsSpecialFloat(value)) {
190
+ throw new ValidationError(`${name} contains non-finite numbers (NaN or Infinity) which cannot be serialized to JSON`);
191
+ }
192
+ }
193
+ // ═══════════════════════════════════════════════════════════════════════════
194
+ // PATH VALIDATION (for CLI security)
195
+ // ═══════════════════════════════════════════════════════════════════════════
196
+ /**
197
+ * Sanitize a string for use in a cache key filename.
198
+ * Removes or replaces characters that could cause path traversal or invalid filenames.
199
+ *
200
+ * @param value - The string to sanitize
201
+ * @returns A safe string for use in filenames
202
+ */
203
+ export function sanitizeForFilename(value) {
204
+ // Replace path separators and traversal patterns
205
+ return value
206
+ .replace(/\.\./g, '__')
207
+ .replace(/[/\\:*?"<>|]/g, '_')
208
+ .replace(/\s+/g, '_');
209
+ }
210
+ /**
211
+ * Check if a string looks like a path traversal attempt.
212
+ *
213
+ * @param value - The string to check
214
+ * @returns True if the string contains path traversal patterns
215
+ */
216
+ export function containsPathTraversal(value) {
217
+ return value.includes('..') || value.includes('/') || value.includes('\\');
218
+ }
219
+ //# sourceMappingURL=validators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.js","sourceRoot":"","sources":["../../src/runtime/validators.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,8EAA8E;AAC9E,cAAc;AACd,8EAA8E;AAE9E;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC7D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,OAAO,cAAc,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,OAAO,cAAc,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;AACvD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAc,EAAE,IAAY;IAC7D,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC;QACxE,MAAM,IAAI,eAAe,CAAC,GAAG,IAAI,kCAAkC,MAAM,EAAE,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,KAAc,EAAE,IAAY;IACzD,MAAM,GAAG,GAAG,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC5C,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;QACb,MAAM,IAAI,eAAe,CAAC,GAAG,IAAI,2BAA2B,GAAG,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAc,EAAE,IAAY;IAC5D,MAAM,GAAG,GAAG,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC5C,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;QACZ,MAAM,IAAI,eAAe,CAAC,GAAG,IAAI,+BAA+B,GAAG,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,KAAc,EAAE,IAAY;IACvD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,eAAe,CAAC,GAAG,IAAI,2BAA2B,OAAO,KAAK,EAAE,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAc,EAAE,IAAY;IAC/D,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACtC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,eAAe,CAAC,GAAG,IAAI,oBAAoB,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAc,KAAc,EAAE,IAAY;IACnE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,eAAe,CAAC,GAAG,IAAI,2BAA2B,OAAO,KAAK,EAAE,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,KAAY,CAAC;AACtB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,KAAc,EAAE,IAAY;IACvD,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC;QACvF,MAAM,IAAI,eAAe,CAAC,GAAG,IAAI,4BAA4B,MAAM,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,8EAA8E;AAC9E,iDAAiD;AACjD,8EAA8E;AAE9E;;;;;;;;;;GAUG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAc;IACjD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAC1C,CAAC;IACD,IAAI,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAc,EAAE,IAAY;IAChE,IAAI,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,eAAe,CACvB,GAAG,IAAI,mFAAmF,CAC3F,CAAC;IACJ,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,qCAAqC;AACrC,8EAA8E;AAE9E;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,iDAAiD;IACjD,OAAO,KAAK;SACT,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC;SACtB,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC;SAC7B,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAa;IACjD,OAAO,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC7E,CAAC"}
@@ -0,0 +1,196 @@
1
+ /**
2
+ * WorkerPool - Manages multiple Transport instances for concurrent request handling.
3
+ *
4
+ * Provides semaphore-based concurrency control with configurable limits per worker
5
+ * and a wait queue for callers when all workers are at capacity.
6
+ *
7
+ * @see https://github.com/bbopen/tywrap/issues/149
8
+ */
9
+ import { BoundedContext } from './bounded-context.js';
10
+ import type { Transport } from './transport.js';
11
+ /**
12
+ * Configuration options for the WorkerPool.
13
+ */
14
+ export interface WorkerPoolOptions {
15
+ /** Factory function to create transports */
16
+ createTransport: () => Transport;
17
+ /** Maximum number of workers in the pool */
18
+ maxWorkers: number;
19
+ /** Minimum number of workers to pre-spawn during init. Default: 0 (lazy) */
20
+ minWorkers?: number;
21
+ /** Timeout for waiting in queue (ms). Default: 30000 */
22
+ queueTimeoutMs?: number;
23
+ /** Maximum concurrent requests per worker. Default: 1 */
24
+ maxConcurrentPerWorker?: number;
25
+ /**
26
+ * Callback invoked after each worker is created and initialized.
27
+ * Use this for per-worker warmup (e.g., importing modules, running setup).
28
+ */
29
+ onWorkerReady?: (worker: PooledWorker) => Promise<void>;
30
+ }
31
+ /**
32
+ * A pooled worker with its transport and current in-flight request count.
33
+ */
34
+ export interface PooledWorker {
35
+ /** The underlying transport instance */
36
+ transport: Transport;
37
+ /** Number of requests currently being processed by this worker */
38
+ inFlightCount: number;
39
+ }
40
+ /**
41
+ * Pool of Transport workers with semaphore-based concurrency control.
42
+ *
43
+ * Features:
44
+ * - Lazy worker creation (workers created on demand)
45
+ * - Configurable concurrency per worker
46
+ * - Wait queue with timeout for callers when pool is at capacity
47
+ * - Automatic cleanup of timers and workers on disposal
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * const pool = new WorkerPool({
52
+ * createTransport: () => new ProcessIO({ pythonPath: 'python3' }),
53
+ * maxWorkers: 4,
54
+ * maxConcurrentPerWorker: 2,
55
+ * queueTimeoutMs: 5000,
56
+ * });
57
+ *
58
+ * await pool.init();
59
+ *
60
+ * // Use withWorker for automatic acquire/release
61
+ * const result = await pool.withWorker(async (worker) => {
62
+ * return worker.transport.send(message, timeout);
63
+ * });
64
+ *
65
+ * await pool.dispose();
66
+ * ```
67
+ */
68
+ export declare class WorkerPool extends BoundedContext {
69
+ private readonly options;
70
+ private readonly workers;
71
+ private readonly waitQueue;
72
+ /** Tracks workers being created to prevent race condition in acquire() */
73
+ private pendingCreations;
74
+ /**
75
+ * Create a new WorkerPool.
76
+ *
77
+ * @param options - Pool configuration options
78
+ */
79
+ constructor(options: WorkerPoolOptions);
80
+ /**
81
+ * Initialize the pool.
82
+ *
83
+ * If minWorkers > 0, pre-spawns workers during initialization.
84
+ * Otherwise, workers are created lazily on demand.
85
+ */
86
+ protected doInit(): Promise<void>;
87
+ /**
88
+ * Dispose the pool and all workers.
89
+ *
90
+ * - Rejects all waiters in the queue
91
+ * - Disposes all transport instances
92
+ * - Clears internal state
93
+ */
94
+ protected doDispose(): Promise<void>;
95
+ /**
96
+ * Acquire a worker from the pool.
97
+ *
98
+ * This method:
99
+ * - Returns an available worker if one exists (inFlightCount < maxConcurrentPerWorker)
100
+ * - Creates a new worker if under the maxWorkers limit
101
+ * - Waits in queue if all workers are at capacity
102
+ *
103
+ * @returns Promise resolving to a pooled worker
104
+ * @throws BridgeTimeoutError if queue timeout expires
105
+ * @throws BridgeExecutionError if pool is disposed while waiting
106
+ */
107
+ acquire(): Promise<PooledWorker>;
108
+ /**
109
+ * Release a worker back to the pool.
110
+ *
111
+ * Decrements the worker's in-flight count and notifies any waiters
112
+ * that a worker may be available.
113
+ *
114
+ * @param worker - The worker to release
115
+ */
116
+ release(worker: PooledWorker): void;
117
+ /**
118
+ * Execute a function with an acquired worker, automatically releasing afterward.
119
+ *
120
+ * This is the recommended way to use the pool, as it ensures proper cleanup
121
+ * even if the function throws an error.
122
+ *
123
+ * @param fn - Async function to execute with the worker
124
+ * @returns Promise resolving to the function's return value
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * const result = await pool.withWorker(async (worker) => {
129
+ * return worker.transport.send(message, timeout);
130
+ * });
131
+ * ```
132
+ */
133
+ withWorker<T>(fn: (worker: PooledWorker) => Promise<T>): Promise<T>;
134
+ /**
135
+ * Check if an error indicates the worker is dead and should be removed.
136
+ *
137
+ * Fatal errors include:
138
+ * - Process not running
139
+ * - Process exited unexpectedly
140
+ * - Pipe errors (EPIPE)
141
+ * - Connection reset errors (ECONNRESET)
142
+ */
143
+ private isFatalWorkerError;
144
+ /**
145
+ * Remove a worker from the pool.
146
+ *
147
+ * This is called when a worker is detected as dead (crashed, pipe error, etc.).
148
+ * The worker's transport is disposed in the background.
149
+ */
150
+ private removeWorker;
151
+ /**
152
+ * Current number of workers in the pool.
153
+ */
154
+ get workerCount(): number;
155
+ /**
156
+ * Number of callers waiting in the queue.
157
+ */
158
+ get queueLength(): number;
159
+ /**
160
+ * Total number of in-flight requests across all workers.
161
+ */
162
+ get totalInFlight(): number;
163
+ /**
164
+ * Find an available worker with capacity for another request.
165
+ */
166
+ private findAvailableWorker;
167
+ /**
168
+ * Create a new worker and add it to the pool.
169
+ *
170
+ * If onWorkerReady is configured, calls it after the transport is initialized.
171
+ * This is useful for per-worker warmup (importing modules, running setup).
172
+ */
173
+ private createWorker;
174
+ /**
175
+ * Wait in queue for a worker to become available.
176
+ */
177
+ private waitForWorker;
178
+ /**
179
+ * Not implemented - WorkerPool does not execute Python calls directly.
180
+ * Use the BridgeProtocol layer with a pooled worker's transport.
181
+ */
182
+ call<T = unknown>(_module: string, _functionName: string, _args: unknown[], _kwargs?: Record<string, unknown>): Promise<T>;
183
+ /**
184
+ * Not implemented - WorkerPool does not execute Python calls directly.
185
+ */
186
+ instantiate<T = unknown>(_module: string, _className: string, _args: unknown[], _kwargs?: Record<string, unknown>): Promise<T>;
187
+ /**
188
+ * Not implemented - WorkerPool does not execute Python calls directly.
189
+ */
190
+ callMethod<T = unknown>(_handle: string, _methodName: string, _args: unknown[], _kwargs?: Record<string, unknown>): Promise<T>;
191
+ /**
192
+ * Not implemented - WorkerPool does not execute Python calls directly.
193
+ */
194
+ disposeInstance(_handle: string): Promise<void>;
195
+ }
196
+ //# sourceMappingURL=worker-pool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-pool.d.ts","sourceRoot":"","sources":["../../src/runtime/worker-pool.ts"],"names":[],"mappings":"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"}