@flink-app/flink 2.0.0-alpha.51 → 2.0.0-alpha.53
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.
- package/CHANGELOG.md +44 -0
- package/cli/build.ts +17 -12
- package/dist/cli/build.js +13 -2
- package/dist/src/TypeScriptCompiler.d.ts +18 -0
- package/dist/src/TypeScriptCompiler.js +232 -103
- package/dist/src/workers/SchemaGeneratorWorker.d.ts +1 -0
- package/dist/src/workers/SchemaGeneratorWorker.js +49 -0
- package/dist/src/workers/WorkerPool.d.ts +60 -0
- package/dist/src/workers/WorkerPool.js +306 -0
- package/package.json +1 -1
- package/src/TypeScriptCompiler.ts +162 -34
- package/src/workers/SchemaGeneratorWorker.ts +63 -0
- package/src/workers/WorkerPool.ts +287 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,49 @@
|
|
|
1
1
|
# @flink-app/flink
|
|
2
2
|
|
|
3
|
+
## 2.0.0-alpha.53
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 333aa52: feat: add worker thread parallelization for JSON schema generation
|
|
8
|
+
|
|
9
|
+
Implements worker thread pool for parallel JSON schema generation during compilation, providing significant speedup for large projects with 50+ schemas.
|
|
10
|
+
|
|
11
|
+
**Key features:**
|
|
12
|
+
|
|
13
|
+
- Worker pool with automatic sizing based on CPU cores and memory
|
|
14
|
+
- Parallel schema generation using ts-json-schema-generator
|
|
15
|
+
- Automatic fallback to single-threaded mode for small projects (<50 schemas)
|
|
16
|
+
- Configurable via environment variables:
|
|
17
|
+
- `FLINK_USE_WORKERS=false` to disable workers entirely
|
|
18
|
+
- `FLINK_WORKER_THRESHOLD=N` to customize the schema count threshold
|
|
19
|
+
- Graceful error handling with automatic cleanup
|
|
20
|
+
- Identical output to single-threaded mode (verified)
|
|
21
|
+
|
|
22
|
+
**Performance:**
|
|
23
|
+
|
|
24
|
+
- Projects with 50+ schemas: ~2-2.5x speedup expected
|
|
25
|
+
- Projects with <50 schemas: Uses efficient single-threaded mode (no overhead)
|
|
26
|
+
- Memory overhead: ~80-160MB for worker pool (scales with CPU count)
|
|
27
|
+
|
|
28
|
+
**Usage:**
|
|
29
|
+
No configuration needed - workers are automatically enabled for large projects. To disable:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
FLINK_USE_WORKERS=false flink build
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
To customize threshold:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
FLINK_WORKER_THRESHOLD=30 flink build
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## 2.0.0-alpha.52
|
|
42
|
+
|
|
43
|
+
### Patch Changes
|
|
44
|
+
|
|
45
|
+
- fe9f8f2: Improved compilation performance by parallelizing handler schema extraction. Projects with many handlers (90+) will see 3-10x faster build times.
|
|
46
|
+
|
|
3
47
|
## 2.0.0-alpha.51
|
|
4
48
|
|
|
5
49
|
## 2.0.0-alpha.50
|
package/cli/build.ts
CHANGED
|
@@ -40,16 +40,21 @@ module.exports = async function run(args: string[]) {
|
|
|
40
40
|
process.exit(1);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
43
|
+
try {
|
|
44
|
+
await Promise.all([
|
|
45
|
+
compiler.parseRepos(),
|
|
46
|
+
compiler.parseHandlers(exclude.split(",")),
|
|
47
|
+
compiler.parseTools(),
|
|
48
|
+
compiler.parseAgents(),
|
|
49
|
+
compiler.parseJobs(),
|
|
50
|
+
compiler.generateStartScript(),
|
|
51
|
+
]);
|
|
52
|
+
|
|
53
|
+
console.log(`Compilation done, took ${Date.now() - startTime}ms`);
|
|
54
|
+
|
|
55
|
+
compiler.emit();
|
|
56
|
+
} finally {
|
|
57
|
+
// Cleanup worker pool and other resources
|
|
58
|
+
await compiler.cleanup();
|
|
59
|
+
}
|
|
55
60
|
};
|
package/dist/cli/build.js
CHANGED
|
@@ -65,6 +65,9 @@ module.exports = function run(args) {
|
|
|
65
65
|
if (!compiler.getPreEmitDiagnostics()) {
|
|
66
66
|
process.exit(1);
|
|
67
67
|
}
|
|
68
|
+
_a.label = 2;
|
|
69
|
+
case 2:
|
|
70
|
+
_a.trys.push([2, , 4, 6]);
|
|
68
71
|
return [4 /*yield*/, Promise.all([
|
|
69
72
|
compiler.parseRepos(),
|
|
70
73
|
compiler.parseHandlers(exclude.split(",")),
|
|
@@ -73,11 +76,19 @@ module.exports = function run(args) {
|
|
|
73
76
|
compiler.parseJobs(),
|
|
74
77
|
compiler.generateStartScript(),
|
|
75
78
|
])];
|
|
76
|
-
case
|
|
79
|
+
case 3:
|
|
77
80
|
_a.sent();
|
|
78
81
|
console.log("Compilation done, took ".concat(Date.now() - startTime, "ms"));
|
|
79
82
|
compiler.emit();
|
|
80
|
-
return [
|
|
83
|
+
return [3 /*break*/, 6];
|
|
84
|
+
case 4:
|
|
85
|
+
// Cleanup worker pool and other resources
|
|
86
|
+
return [4 /*yield*/, compiler.cleanup()];
|
|
87
|
+
case 5:
|
|
88
|
+
// Cleanup worker pool and other resources
|
|
89
|
+
_a.sent();
|
|
90
|
+
return [7 /*endfinally*/];
|
|
91
|
+
case 6: return [2 /*return*/];
|
|
81
92
|
}
|
|
82
93
|
});
|
|
83
94
|
});
|
|
@@ -4,6 +4,11 @@ declare class TypeScriptCompiler {
|
|
|
4
4
|
private project;
|
|
5
5
|
private schemaGenerator?;
|
|
6
6
|
private isEsm;
|
|
7
|
+
/**
|
|
8
|
+
* Worker pool for parallel JSON schema generation.
|
|
9
|
+
* Initialized on first use, terminated on cleanup.
|
|
10
|
+
*/
|
|
11
|
+
private workerPool?;
|
|
7
12
|
/**
|
|
8
13
|
* Parsed typescript schemas that will be added to intermediate
|
|
9
14
|
* schemas.ts file.
|
|
@@ -17,6 +22,11 @@ declare class TypeScriptCompiler {
|
|
|
17
22
|
* This will be added to file in a batch for performance reasons.
|
|
18
23
|
*/
|
|
19
24
|
private tsSchemasSymbolsToImports;
|
|
25
|
+
/**
|
|
26
|
+
* Cache for schema analysis to avoid reprocessing the same types.
|
|
27
|
+
* Key: schema type text, Value: generated schema interface name
|
|
28
|
+
*/
|
|
29
|
+
private schemaCache;
|
|
20
30
|
constructor(cwd: string);
|
|
21
31
|
/**
|
|
22
32
|
* Loads additional source paths from tsconfig.json's flink configuration.
|
|
@@ -138,6 +148,10 @@ declare class TypeScriptCompiler {
|
|
|
138
148
|
private saveIntermediateTsSchema;
|
|
139
149
|
private initJsonSchemaGenerator;
|
|
140
150
|
private generateAndSaveJsonSchemas;
|
|
151
|
+
/**
|
|
152
|
+
* Generate schemas sequentially (single-threaded fallback)
|
|
153
|
+
*/
|
|
154
|
+
private generateSchemasSequentially;
|
|
141
155
|
private generateJsonSchema;
|
|
142
156
|
private extractSchemaTypeFromHandler;
|
|
143
157
|
/**
|
|
@@ -164,5 +178,9 @@ declare class TypeScriptCompiler {
|
|
|
164
178
|
* Scans project for jobs so they can be registered during start.
|
|
165
179
|
*/
|
|
166
180
|
parseJobs(): Promise<SourceFile>;
|
|
181
|
+
/**
|
|
182
|
+
* Cleanup resources, including worker pool
|
|
183
|
+
*/
|
|
184
|
+
cleanup(): Promise<void>;
|
|
167
185
|
}
|
|
168
186
|
export default TypeScriptCompiler;
|
|
@@ -90,6 +90,7 @@ var ts_morph_1 = require("ts-morph");
|
|
|
90
90
|
var FsUtils_1 = require("./FsUtils");
|
|
91
91
|
var TypeScriptUtils_1 = require("./TypeScriptUtils");
|
|
92
92
|
var utils_1 = require("./utils");
|
|
93
|
+
var WorkerPool_1 = require("./workers/WorkerPool");
|
|
93
94
|
var TypeScriptCompiler = /** @class */ (function () {
|
|
94
95
|
function TypeScriptCompiler(cwd) {
|
|
95
96
|
this.cwd = cwd;
|
|
@@ -106,6 +107,11 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
106
107
|
* This will be added to file in a batch for performance reasons.
|
|
107
108
|
*/
|
|
108
109
|
this.tsSchemasSymbolsToImports = [];
|
|
110
|
+
/**
|
|
111
|
+
* Cache for schema analysis to avoid reprocessing the same types.
|
|
112
|
+
* Key: schema type text, Value: generated schema interface name
|
|
113
|
+
*/
|
|
114
|
+
this.schemaCache = new Map();
|
|
109
115
|
// Detect if project is using ESM based solely on package.json "type": "module"
|
|
110
116
|
this.isEsm = this.isEsmProject(cwd);
|
|
111
117
|
var compilerOptions = {
|
|
@@ -385,20 +391,24 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
385
391
|
*/
|
|
386
392
|
TypeScriptCompiler.prototype.parseHandlers = function () {
|
|
387
393
|
return __awaiter(this, arguments, void 0, function (excludeDirs) {
|
|
388
|
-
var generatedFile, handlersArr, handlers, schemaFilePath, jsonSchemas;
|
|
394
|
+
var startTime, generatedFile, handlersArr, handlers, handlerParseTime, schemaGenStartTime, schemaFilePath, jsonSchemas, schemaGenTime;
|
|
389
395
|
if (excludeDirs === void 0) { excludeDirs = []; }
|
|
390
396
|
return __generator(this, function (_a) {
|
|
391
397
|
switch (_a.label) {
|
|
392
398
|
case 0:
|
|
399
|
+
startTime = Date.now();
|
|
393
400
|
generatedFile = this.createSourceFile(["generatedHandlers.ts"], "// Generated ".concat(new Date(), "\nimport { autoRegisteredHandlers, HttpMethod } from \"@flink-app/flink\";\nexport const handlers = [];\nautoRegisteredHandlers.push(...handlers);\n "));
|
|
394
401
|
handlersArr = generatedFile.getVariableDeclarationOrThrow("handlers").getFirstDescendantByKindOrThrow(ts_morph_1.SyntaxKind.ArrayLiteralExpression);
|
|
395
402
|
return [4 /*yield*/, this.parseHandlerDir(generatedFile, handlersArr)];
|
|
396
403
|
case 1:
|
|
397
404
|
handlers = _a.sent();
|
|
405
|
+
handlerParseTime = Date.now() - startTime;
|
|
406
|
+
console.log("\u2713 Handler parsing completed in ".concat(handlerParseTime, "ms"));
|
|
398
407
|
generatedFile.addImportDeclarations(handlers.imports);
|
|
399
408
|
return [4 /*yield*/, generatedFile.save()];
|
|
400
409
|
case 2:
|
|
401
410
|
_a.sent();
|
|
411
|
+
schemaGenStartTime = Date.now();
|
|
402
412
|
return [4 /*yield*/, this.createIntermediateSchemaFile()];
|
|
403
413
|
case 3:
|
|
404
414
|
schemaFilePath = _a.sent();
|
|
@@ -406,6 +416,8 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
406
416
|
case 4:
|
|
407
417
|
jsonSchemas = _a.sent();
|
|
408
418
|
this.appendSchemasToHandlerSourceFiles(handlers.schemasToGenerate, jsonSchemas);
|
|
419
|
+
schemaGenTime = Date.now() - schemaGenStartTime;
|
|
420
|
+
console.log("\u2713 Schema generation completed in ".concat(schemaGenTime, "ms"));
|
|
409
421
|
return [2 /*return*/, generatedFile];
|
|
410
422
|
}
|
|
411
423
|
});
|
|
@@ -416,93 +428,111 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
416
428
|
*/
|
|
417
429
|
TypeScriptCompiler.prototype.parseHandlerDir = function (generatedFile, handlersArr) {
|
|
418
430
|
return __awaiter(this, void 0, void 0, function () {
|
|
419
|
-
var imports,
|
|
420
|
-
|
|
421
|
-
|
|
431
|
+
var imports, schemasToGenerate, handlerFiles, handlerResults, autoRegisterIndex, _i, handlerResults_1, result, sf, isAutoRegister, namespaceImport, assumedHttpMethod, schemaTypes, existingVars;
|
|
432
|
+
var _this = this;
|
|
433
|
+
return __generator(this, function (_a) {
|
|
434
|
+
switch (_a.label) {
|
|
422
435
|
case 0:
|
|
423
436
|
imports = [];
|
|
424
|
-
i = 0;
|
|
425
437
|
schemasToGenerate = [];
|
|
426
|
-
|
|
427
|
-
|
|
438
|
+
handlerFiles = this.project.getSourceFiles().filter(function (sf) { return sf.getFilePath().includes("src/handlers/"); });
|
|
439
|
+
console.log("Processing ".concat(handlerFiles.length, " handlers..."));
|
|
440
|
+
return [4 /*yield*/, Promise.all(handlerFiles.map(function (sf, index) { return __awaiter(_this, void 0, void 0, function () {
|
|
441
|
+
var startTime, isAutoRegister, namespaceImport, assumedHttpMethod, schemaTypes, _a, elapsed;
|
|
442
|
+
return __generator(this, function (_b) {
|
|
443
|
+
switch (_b.label) {
|
|
444
|
+
case 0:
|
|
445
|
+
startTime = Date.now();
|
|
446
|
+
isAutoRegister = this.isAutoRegisterableHandler(sf);
|
|
447
|
+
namespaceImport = sf.getBaseNameWithoutExtension().replace(/\./g, "_") + "_" + index;
|
|
448
|
+
assumedHttpMethod = (0, utils_1.getHttpMethodFromHandlerName)(sf.getBaseName());
|
|
449
|
+
console.log("[".concat(index + 1, "/").concat(handlerFiles.length, "] Processing ").concat(sf.getBaseName(), "..."));
|
|
450
|
+
if (!isAutoRegister) return [3 /*break*/, 2];
|
|
451
|
+
return [4 /*yield*/, this.extractSchemasFromHandlerSourceFile(sf)];
|
|
452
|
+
case 1:
|
|
453
|
+
_a = _b.sent();
|
|
454
|
+
return [3 /*break*/, 3];
|
|
455
|
+
case 2:
|
|
456
|
+
_a = undefined;
|
|
457
|
+
_b.label = 3;
|
|
458
|
+
case 3:
|
|
459
|
+
schemaTypes = _a;
|
|
460
|
+
elapsed = Date.now() - startTime;
|
|
461
|
+
if (elapsed > 100) {
|
|
462
|
+
console.log(" \u2514\u2500 Completed in ".concat(elapsed, "ms"));
|
|
463
|
+
}
|
|
464
|
+
return [2 /*return*/, {
|
|
465
|
+
sf: sf,
|
|
466
|
+
isAutoRegister: isAutoRegister,
|
|
467
|
+
namespaceImport: namespaceImport,
|
|
468
|
+
assumedHttpMethod: assumedHttpMethod,
|
|
469
|
+
schemaTypes: schemaTypes,
|
|
470
|
+
index: index,
|
|
471
|
+
}];
|
|
472
|
+
}
|
|
473
|
+
});
|
|
474
|
+
}); }))];
|
|
428
475
|
case 1:
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
var description = _a.description, name = _a.name;
|
|
484
|
-
return "{description: \"".concat(description, "\", name: \"").concat(name, "\"}");
|
|
485
|
-
})
|
|
486
|
-
.join(","), "]"),
|
|
487
|
-
},
|
|
488
|
-
],
|
|
489
|
-
});
|
|
490
|
-
if (isAutoRegister) {
|
|
491
|
-
handlersArr.insertElement(i, "{handler: ".concat(namespaceImport, ", assumedHttpMethod: ").concat(assumedHttpMethod ? "HttpMethod." + assumedHttpMethod : undefined, "}"));
|
|
492
|
-
i++;
|
|
493
|
-
// Add schemas to generate list
|
|
494
|
-
if (schemaTypes) {
|
|
495
|
-
schemasToGenerate.push(__assign(__assign({}, schemaTypes), { sourceFile: sf }));
|
|
476
|
+
handlerResults = _a.sent();
|
|
477
|
+
autoRegisterIndex = 0;
|
|
478
|
+
for (_i = 0, handlerResults_1 = handlerResults; _i < handlerResults_1.length; _i++) {
|
|
479
|
+
result = handlerResults_1[_i];
|
|
480
|
+
sf = result.sf, isAutoRegister = result.isAutoRegister, namespaceImport = result.namespaceImport, assumedHttpMethod = result.assumedHttpMethod, schemaTypes = result.schemaTypes;
|
|
481
|
+
imports.push({
|
|
482
|
+
defaultImport: "* as " + namespaceImport,
|
|
483
|
+
moduleSpecifier: this.getModuleSpecifier(generatedFile, sf),
|
|
484
|
+
});
|
|
485
|
+
existingVars = sf.getVariableStatements().filter(function (vs) {
|
|
486
|
+
var varNames = vs.getDeclarations().map(function (d) { return d.getName(); });
|
|
487
|
+
return varNames.some(function (name) { return ["__assumedHttpMethod", "__file", "__query", "__params"].includes(name); });
|
|
488
|
+
});
|
|
489
|
+
existingVars.forEach(function (v) { return v.remove(); });
|
|
490
|
+
// Append schemas and metadata to source file that will be part of emitted dist bundle (javascript)
|
|
491
|
+
sf.addVariableStatement({
|
|
492
|
+
declarationKind: ts_morph_1.VariableDeclarationKind.Const,
|
|
493
|
+
isExported: true,
|
|
494
|
+
declarations: [
|
|
495
|
+
{
|
|
496
|
+
name: "__assumedHttpMethod",
|
|
497
|
+
initializer: "\"".concat(assumedHttpMethod || "", "\""),
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
name: "__file",
|
|
501
|
+
initializer: "\"".concat(sf.getBaseName(), "\""),
|
|
502
|
+
},
|
|
503
|
+
{
|
|
504
|
+
name: "__query",
|
|
505
|
+
initializer: "[".concat(((schemaTypes === null || schemaTypes === void 0 ? void 0 : schemaTypes.queryMetadata) || [])
|
|
506
|
+
.map(function (_a) {
|
|
507
|
+
var description = _a.description, name = _a.name;
|
|
508
|
+
return "{description: \"".concat(description, "\", name: \"").concat(name, "\"}");
|
|
509
|
+
})
|
|
510
|
+
.join(","), "]"),
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
name: "__params",
|
|
514
|
+
initializer: "[".concat(((schemaTypes === null || schemaTypes === void 0 ? void 0 : schemaTypes.paramsMetadata) || [])
|
|
515
|
+
.map(function (_a) {
|
|
516
|
+
var description = _a.description, name = _a.name;
|
|
517
|
+
return "{description: \"".concat(description, "\", name: \"").concat(name, "\"}");
|
|
518
|
+
})
|
|
519
|
+
.join(","), "]"),
|
|
520
|
+
},
|
|
521
|
+
],
|
|
522
|
+
});
|
|
523
|
+
if (isAutoRegister) {
|
|
524
|
+
handlersArr.insertElement(autoRegisterIndex, "{handler: ".concat(namespaceImport, ", assumedHttpMethod: ").concat(assumedHttpMethod ? "HttpMethod." + assumedHttpMethod : undefined, "}"));
|
|
525
|
+
autoRegisterIndex++;
|
|
526
|
+
// Add schemas to generate list
|
|
527
|
+
if (schemaTypes) {
|
|
528
|
+
schemasToGenerate.push(__assign(__assign({}, schemaTypes), { sourceFile: sf }));
|
|
529
|
+
}
|
|
496
530
|
}
|
|
497
531
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
case 6: return [2 /*return*/, {
|
|
503
|
-
imports: imports,
|
|
504
|
-
schemasToGenerate: schemasToGenerate,
|
|
505
|
-
}];
|
|
532
|
+
return [2 /*return*/, {
|
|
533
|
+
imports: imports,
|
|
534
|
+
schemasToGenerate: schemasToGenerate,
|
|
535
|
+
}];
|
|
506
536
|
}
|
|
507
537
|
});
|
|
508
538
|
});
|
|
@@ -884,7 +914,7 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
884
914
|
};
|
|
885
915
|
TypeScriptCompiler.prototype.saveIntermediateTsSchema = function (schema, handlerFile, suffix) {
|
|
886
916
|
return __awaiter(this, void 0, void 0, function () {
|
|
887
|
-
var schemaText, handlerFileName, generatedSchemaInterfaceStr, schemaInterfaceName, schemaSymbol, interfaceName, declaration, _i, _a, typeToImport, typeSymbol, declaredTypeSymbol, _b, _c, prop, propDecl, propText, interfaceNameMatches, _d, interfaceNameMatches_1, match, referencedInterfaceName, referencedInterfaceDecl, arrayTypeArg, schemaSymbol, interfaceName, declaration, props, _e, _f, typeToImport, typeSymbol, declaredTypeSymbol, schemaSymbol, declarations, declaration, propertySignatures, _g, _h, prop, propType, typeSymbol, typeDeclaration, elementType, elementSymbol, elementDeclaration, currentPropTypeText, interfaceNameMatches, _j, interfaceNameMatches_2, match, interfaceName, interfaceDecl, typeArgs, _k, typeArgs_1, typeArg, argSymbol, argDeclaration, _l, _m, typeToImport, typeSymbol, declaredTypeSymbol;
|
|
917
|
+
var schemaText, cacheKey, handlerFileName, generatedSchemaInterfaceStr, schemaInterfaceName, schemaSymbol, interfaceName, declaration, _i, _a, typeToImport, typeSymbol, declaredTypeSymbol, _b, _c, prop, propDecl, propText, interfaceNameMatches, _d, interfaceNameMatches_1, match, referencedInterfaceName, referencedInterfaceDecl, arrayTypeArg, schemaSymbol, interfaceName, declaration, props, _e, _f, typeToImport, typeSymbol, declaredTypeSymbol, schemaSymbol, declarations, declaration, propertySignatures, _g, _h, prop, propType, typeSymbol, typeDeclaration, elementType, elementSymbol, elementDeclaration, currentPropTypeText, interfaceNameMatches, _j, interfaceNameMatches_2, match, interfaceName, interfaceDecl, typeArgs, _k, typeArgs_1, typeArg, argSymbol, argDeclaration, _l, _m, typeToImport, typeSymbol, declaredTypeSymbol;
|
|
888
918
|
return __generator(this, function (_o) {
|
|
889
919
|
if (schema.isAny()) {
|
|
890
920
|
return [2 /*return*/]; // 'any' indicates that no schema is used
|
|
@@ -893,6 +923,10 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
893
923
|
if (schemaText === "void" || schemaText === "undefined") {
|
|
894
924
|
return [2 /*return*/];
|
|
895
925
|
}
|
|
926
|
+
cacheKey = "".concat(handlerFile.getFilePath(), ":").concat(schemaText, ":").concat(suffix);
|
|
927
|
+
if (this.schemaCache.has(cacheKey)) {
|
|
928
|
+
return [2 /*return*/, this.schemaCache.get(cacheKey)];
|
|
929
|
+
}
|
|
896
930
|
handlerFileName = handlerFile.getBaseNameWithoutExtension().replace(/\./g, "_");
|
|
897
931
|
generatedSchemaInterfaceStr = "";
|
|
898
932
|
schemaInterfaceName = "".concat(handlerFileName, "_").concat(suffix);
|
|
@@ -1067,8 +1101,10 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
1067
1101
|
}
|
|
1068
1102
|
if (generatedSchemaInterfaceStr) {
|
|
1069
1103
|
this.parsedTsSchemas.push(generatedSchemaInterfaceStr);
|
|
1104
|
+
this.schemaCache.set(cacheKey, schemaInterfaceName);
|
|
1070
1105
|
return [2 /*return*/, schemaInterfaceName];
|
|
1071
1106
|
}
|
|
1107
|
+
this.schemaCache.set(cacheKey, undefined);
|
|
1072
1108
|
return [2 /*return*/];
|
|
1073
1109
|
});
|
|
1074
1110
|
});
|
|
@@ -1132,43 +1168,117 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
1132
1168
|
};
|
|
1133
1169
|
TypeScriptCompiler.prototype.generateAndSaveJsonSchemas = function (schemas, schemaFilePath) {
|
|
1134
1170
|
return __awaiter(this, void 0, void 0, function () {
|
|
1135
|
-
var
|
|
1136
|
-
var
|
|
1137
|
-
return __generator(this, function (
|
|
1138
|
-
switch (
|
|
1171
|
+
var tsconfigPath, useWorkers, workerThreshold, schemaTypes, _i, schemas_1, _a, reqSchemaType, resSchemaType, definitions, workerScriptPath, stats, startTime, results, duration, _b, results_1, result, error_1, mergedSchemas, filePath;
|
|
1172
|
+
var _this = this;
|
|
1173
|
+
return __generator(this, function (_c) {
|
|
1174
|
+
switch (_c.label) {
|
|
1139
1175
|
case 0:
|
|
1140
1176
|
// Reset schema generator to use the newly created intermediate schema file
|
|
1141
1177
|
this.schemaGenerator = undefined;
|
|
1142
|
-
|
|
1178
|
+
tsconfigPath = (0, path_1.join)(this.cwd, "tsconfig.json");
|
|
1179
|
+
useWorkers = process.env.FLINK_USE_WORKERS !== "false";
|
|
1180
|
+
workerThreshold = parseInt(process.env.FLINK_WORKER_THRESHOLD || "50", 10);
|
|
1181
|
+
schemaTypes = [];
|
|
1143
1182
|
for (_i = 0, schemas_1 = schemas; _i < schemas_1.length; _i++) {
|
|
1144
1183
|
_a = schemas_1[_i], reqSchemaType = _a.reqSchemaType, resSchemaType = _a.resSchemaType;
|
|
1145
|
-
if (reqSchemaType)
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
jsonSchemas.push({ definitions: (_c = {}, _c[resSchemaType] = this.generateJsonSchema(resSchemaType, schemaFilePath), _c) });
|
|
1150
|
-
}
|
|
1184
|
+
if (reqSchemaType)
|
|
1185
|
+
schemaTypes.push(reqSchemaType);
|
|
1186
|
+
if (resSchemaType)
|
|
1187
|
+
schemaTypes.push(resSchemaType);
|
|
1151
1188
|
}
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1189
|
+
definitions = {};
|
|
1190
|
+
if (!(useWorkers && schemaTypes.length >= workerThreshold)) return [3 /*break*/, 10];
|
|
1191
|
+
_c.label = 1;
|
|
1192
|
+
case 1:
|
|
1193
|
+
_c.trys.push([1, 5, , 9]);
|
|
1194
|
+
if (!!this.workerPool) return [3 /*break*/, 3];
|
|
1195
|
+
workerScriptPath = (0, path_1.join)(__dirname, "workers", "SchemaGeneratorWorker.js");
|
|
1196
|
+
this.workerPool = new WorkerPool_1.WorkerPool(workerScriptPath);
|
|
1197
|
+
return [4 /*yield*/, this.workerPool.initialize()];
|
|
1198
|
+
case 2:
|
|
1199
|
+
_c.sent();
|
|
1200
|
+
stats = this.workerPool.getStats();
|
|
1201
|
+
console.log("\u2713 Worker pool initialized with ".concat(stats.poolSize, " workers"));
|
|
1202
|
+
_c.label = 3;
|
|
1203
|
+
case 3:
|
|
1204
|
+
startTime = Date.now();
|
|
1205
|
+
return [4 /*yield*/, Promise.all(schemaTypes.map(function (typeName) {
|
|
1206
|
+
return _this.workerPool.execute({ schemaFilePath: schemaFilePath, typeName: typeName, tsconfigPath: tsconfigPath });
|
|
1207
|
+
}))];
|
|
1208
|
+
case 4:
|
|
1209
|
+
results = _c.sent();
|
|
1210
|
+
duration = Date.now() - startTime;
|
|
1211
|
+
console.log("\u2713 Generated ".concat(schemaTypes.length, " schemas in ").concat(duration, "ms using workers"));
|
|
1212
|
+
// Merge results
|
|
1213
|
+
for (_b = 0, results_1 = results; _b < results_1.length; _b++) {
|
|
1214
|
+
result = results_1[_b];
|
|
1215
|
+
if (result.error) {
|
|
1216
|
+
throw new Error("Schema generation failed for ".concat(result.typeName, ": ").concat(result.error));
|
|
1155
1217
|
}
|
|
1156
|
-
|
|
1157
|
-
}
|
|
1218
|
+
definitions[result.typeName] = result.schema;
|
|
1219
|
+
}
|
|
1220
|
+
return [3 /*break*/, 9];
|
|
1221
|
+
case 5:
|
|
1222
|
+
error_1 = _c.sent();
|
|
1223
|
+
console.warn("Worker pool failed, falling back to single-threaded mode:", error_1.message);
|
|
1224
|
+
if (!this.workerPool) return [3 /*break*/, 7];
|
|
1225
|
+
return [4 /*yield*/, this.workerPool.terminate().catch(function () { })];
|
|
1226
|
+
case 6:
|
|
1227
|
+
_c.sent();
|
|
1228
|
+
this.workerPool = undefined;
|
|
1229
|
+
_c.label = 7;
|
|
1230
|
+
case 7: return [4 /*yield*/, this.generateSchemasSequentially(schemas, schemaFilePath)];
|
|
1231
|
+
case 8:
|
|
1232
|
+
// Fall back to single-threaded generation
|
|
1233
|
+
definitions = _c.sent();
|
|
1234
|
+
return [3 /*break*/, 9];
|
|
1235
|
+
case 9: return [3 /*break*/, 12];
|
|
1236
|
+
case 10:
|
|
1237
|
+
// Use single-threaded generation for small schema counts or when workers disabled
|
|
1238
|
+
if (!useWorkers) {
|
|
1239
|
+
console.log("✓ Workers disabled, using single-threaded schema generation");
|
|
1240
|
+
}
|
|
1241
|
+
return [4 /*yield*/, this.generateSchemasSequentially(schemas, schemaFilePath)];
|
|
1242
|
+
case 11:
|
|
1243
|
+
definitions = _c.sent();
|
|
1244
|
+
_c.label = 12;
|
|
1245
|
+
case 12:
|
|
1246
|
+
mergedSchemas = {
|
|
1158
1247
|
$schema: "http://json-schema.org/draft-07/schema#",
|
|
1159
1248
|
$ref: "#/definitions/Schemas",
|
|
1160
|
-
definitions:
|
|
1161
|
-
}
|
|
1249
|
+
definitions: definitions,
|
|
1250
|
+
};
|
|
1162
1251
|
filePath = (0, path_1.join)(this.cwd, ".flink", "schemas", "schemas.json");
|
|
1163
1252
|
return [4 /*yield*/, (0, FsUtils_1.writeJsonFile)(filePath, mergedSchemas)];
|
|
1164
|
-
case
|
|
1165
|
-
|
|
1253
|
+
case 13:
|
|
1254
|
+
_c.sent();
|
|
1166
1255
|
this.project.addSourceFileAtPath(filePath);
|
|
1167
1256
|
return [2 /*return*/, mergedSchemas];
|
|
1168
1257
|
}
|
|
1169
1258
|
});
|
|
1170
1259
|
});
|
|
1171
1260
|
};
|
|
1261
|
+
/**
|
|
1262
|
+
* Generate schemas sequentially (single-threaded fallback)
|
|
1263
|
+
*/
|
|
1264
|
+
TypeScriptCompiler.prototype.generateSchemasSequentially = function (schemas, schemaFilePath) {
|
|
1265
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1266
|
+
var definitions, _i, schemas_2, _a, reqSchemaType, resSchemaType;
|
|
1267
|
+
return __generator(this, function (_b) {
|
|
1268
|
+
definitions = {};
|
|
1269
|
+
for (_i = 0, schemas_2 = schemas; _i < schemas_2.length; _i++) {
|
|
1270
|
+
_a = schemas_2[_i], reqSchemaType = _a.reqSchemaType, resSchemaType = _a.resSchemaType;
|
|
1271
|
+
if (reqSchemaType) {
|
|
1272
|
+
definitions[reqSchemaType] = this.generateJsonSchema(reqSchemaType, schemaFilePath);
|
|
1273
|
+
}
|
|
1274
|
+
if (resSchemaType) {
|
|
1275
|
+
definitions[resSchemaType] = this.generateJsonSchema(resSchemaType, schemaFilePath);
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
return [2 /*return*/, definitions];
|
|
1279
|
+
});
|
|
1280
|
+
});
|
|
1281
|
+
};
|
|
1172
1282
|
TypeScriptCompiler.prototype.generateJsonSchema = function (typeName, schemaFilePath) {
|
|
1173
1283
|
if (!this.schemaGenerator) {
|
|
1174
1284
|
this.schemaGenerator = this.initJsonSchemaGenerator(schemaFilePath);
|
|
@@ -1349,6 +1459,25 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
1349
1459
|
});
|
|
1350
1460
|
});
|
|
1351
1461
|
};
|
|
1462
|
+
/**
|
|
1463
|
+
* Cleanup resources, including worker pool
|
|
1464
|
+
*/
|
|
1465
|
+
TypeScriptCompiler.prototype.cleanup = function () {
|
|
1466
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1467
|
+
return __generator(this, function (_a) {
|
|
1468
|
+
switch (_a.label) {
|
|
1469
|
+
case 0:
|
|
1470
|
+
if (!this.workerPool) return [3 /*break*/, 2];
|
|
1471
|
+
return [4 /*yield*/, this.workerPool.terminate()];
|
|
1472
|
+
case 1:
|
|
1473
|
+
_a.sent();
|
|
1474
|
+
this.workerPool = undefined;
|
|
1475
|
+
_a.label = 2;
|
|
1476
|
+
case 2: return [2 /*return*/];
|
|
1477
|
+
}
|
|
1478
|
+
});
|
|
1479
|
+
});
|
|
1480
|
+
};
|
|
1352
1481
|
return TypeScriptCompiler;
|
|
1353
1482
|
}());
|
|
1354
1483
|
exports.default = TypeScriptCompiler;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|