@@ -6,11 +6,12 @@ import { parse } from '@babel/parser';
66import babelGenerator from '@babel/generator' ;
77import babelTraverse from '@babel/traverse' ;
88import R from 'ramda' ;
9- import workerpool from 'workerpool' ;
109
1110import { getEnv , isNativeSupported } from '@cubejs-backend/shared' ;
11+ import { transpileJs } from '@cubejs-backend/native' ;
1212import { UserError } from './UserError' ;
1313import { ErrorReporter } from './ErrorReporter' ;
14+ import { CONTEXT_SYMBOLS } from './CubeSymbols' ;
1415
1516const NATIVE_IS_SUPPORTED = isNativeSupported ( ) ;
1617
@@ -93,36 +94,38 @@ export class DataSchemaCompiler {
9394 const errorsReport = new ErrorReporter ( null , [ ] , this . errorReport ) ;
9495 this . errorsReport = errorsReport ;
9596
96- if ( getEnv ( 'transpilationWorkerThreads' ) ) {
97- const wc = getEnv ( 'transpilationWorkerThreadsCount' ) ;
98- this . workerPool = workerpool . pool (
99- path . join ( __dirname , 'transpilers/transpiler_worker' ) ,
100- wc > 0 ? { maxWorkers : wc } : undefined ,
101- ) ;
102- }
103-
10497 const transpile = async ( ) => {
10598 let cubeNames ;
106- let cubeSymbolsNames ;
99+ let cubeSymbols ;
100+ let transpilerNames ;
107101
108102 if ( getEnv ( 'transpilationWorkerThreads' ) ) {
109103 cubeNames = Object . keys ( this . cubeDictionary . byId ) ;
110104 // We need only cubes and all its member names for transpiling.
111105 // Cubes doesn't change during transpiling, but are changed during compilation phase,
112106 // so we can prepare them once for every phase.
113- // Communication between main and worker threads uses
114- // The structured clone algorithm (@see https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm)
115- // which doesn't allow passing any function objects, so we need to sanitize the symbols.
116- cubeSymbolsNames = Object . fromEntries (
107+ cubeSymbols = Object . fromEntries (
117108 Object . entries ( this . cubeSymbols . symbols )
118109 . map (
119110 ( [ key , value ] ) => [ key , Object . fromEntries (
120111 Object . keys ( value ) . map ( ( k ) => [ k , true ] ) ,
121112 ) ] ,
122113 ) ,
123114 ) ;
115+
116+ // Transpilers are the same for all files within phase.
117+ transpilerNames = this . transpilers . map ( t => t . constructor . name ) ;
118+
119+ // Warming up swc compiler cache
120+ const dummyFile = {
121+ fileName : 'dummy.js' ,
122+ content : ';' ,
123+ } ;
124+
125+ await this . transpileJsFile ( dummyFile , errorsReport , { cubeNames, cubeSymbols, transpilerNames, contextSymbols : CONTEXT_SYMBOLS } ) ;
124126 }
125- const results = await Promise . all ( toCompile . map ( f => this . transpileFile ( f , errorsReport , { cubeNames, cubeSymbolsNames } ) ) ) ;
127+
128+ const results = await Promise . all ( toCompile . map ( f => this . transpileFile ( f , errorsReport , { transpilerNames } ) ) ) ;
126129 return results . filter ( f => ! ! f ) ;
127130 } ;
128131
@@ -138,9 +141,17 @@ export class DataSchemaCompiler {
138141 contextCompilers : this . contextCompilers ,
139142 } ) )
140143 . then ( ( ) => {
141- if ( this . workerPool ) {
142- this . workerPool . terminate ( ) ;
144+ if ( getEnv ( 'transpilationWorkerThreads' ) ) {
145+ // Clean up cache
146+ const dummyFile = {
147+ fileName : 'terminate.js' ,
148+ content : ';' ,
149+ } ;
150+
151+ return this . transpileJsFile ( dummyFile , errorsReport , { cubeNames : [ ] , cubeSymbols : { } , transpilerNames : [ ] , contextSymbols : { } } ) ;
143152 }
153+
154+ return Promise . resolve ( ) ;
144155 } ) ;
145156 }
146157
@@ -182,22 +193,28 @@ export class DataSchemaCompiler {
182193 }
183194 }
184195
185- async transpileJsFile ( file , errorsReport , { cubeNames, cubeSymbolsNames } ) {
196+ async transpileJsFile ( file , errorsReport , { cubeNames, cubeSymbols , contextSymbols , transpilerNames } ) {
186197 try {
187198 if ( getEnv ( 'transpilationWorkerThreads' ) ) {
188- const data = {
199+ const reqData = {
189200 fileName : file . fileName ,
190- content : file . content ,
191- transpilers : this . transpilers . map ( t => t . constructor . name ) ,
192- cubeNames,
193- cubeSymbolsNames,
201+ transpilers : transpilerNames ,
202+ ...( cubeNames && {
203+ metaData : {
204+ cubeNames,
205+ cubeSymbols,
206+ contextSymbols,
207+ } ,
208+ } ) ,
194209 } ;
195210
196- const res = await this . workerPool . exec ( 'transpile' , [ data ] ) ;
211+ errorsReport . inFile ( file ) ;
212+ const res = await transpileJs ( file . content , reqData ) ;
197213 errorsReport . addErrors ( res . errors ) ;
198214 errorsReport . addWarnings ( res . warnings ) ;
215+ errorsReport . exitFile ( ) ;
199216
200- return Object . assign ( { } , file , { content : res . content } ) ;
217+ return Object . assign ( { } , file , { content : res . code } ) ;
201218 } else {
202219 const ast = parse (
203220 file . content ,
@@ -208,11 +225,11 @@ export class DataSchemaCompiler {
208225 } ,
209226 ) ;
210227
228+ errorsReport . inFile ( file ) ;
211229 this . transpilers . forEach ( ( t ) => {
212- errorsReport . inFile ( file ) ;
213230 babelTraverse ( ast , t . traverseObject ( errorsReport ) ) ;
214- errorsReport . exitFile ( ) ;
215231 } ) ;
232+ errorsReport . exitFile ( ) ;
216233
217234 const content = babelGenerator ( ast , { } , file . content ) . code ;
218235 return Object . assign ( { } , file , { content } ) ;
0 commit comments