Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions packages/cubejs-backend-native/js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,14 @@

export interface TransformConfig {
fileName: string;
fileContent: string;
transpilers: string[];
compilerId: string;
metaData?: {
cubeNames: string[];
cubeSymbols: Record<string, Record<string, boolean>>;
contextSymbols: Record<string, string>;
stage: 0 | 1 | 2 | 3;
}
}

Expand Down Expand Up @@ -495,11 +497,11 @@
return native.getFinalQueryResultMulti(transformDataArr, rows, responseData);
};

export const transpileJs = async (content: String, metadata: TransformConfig): Promise<TransformResponse> => {
export const transpileJs = async (transpileRequests: TransformConfig[]): Promise<TransformResponse[]> => {
const native = loadNative();

if (native.transpileJs) {
return native.transpileJs(content, metadata);
return native.transpileJs(transpileRequests);

Check warning on line 504 in packages/cubejs-backend-native/js/index.ts

View check run for this annotation

Codecov / codecov/patch

packages/cubejs-backend-native/js/index.ts#L504

Added line #L504 was not covered by tests
}

throw new Error('TranspileJs native implementation not found!');
Expand Down
108 changes: 94 additions & 14 deletions packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import crypto from 'crypto';
import vm from 'vm';
import fs from 'fs';
import os from 'os';
import path from 'path';
import syntaxCheck from 'syntax-error';
import { parse } from '@babel/parser';
Expand All @@ -21,6 +22,21 @@

const JINJA_SYNTAX = /{%|%}|{{|}}/ig;

const getThreadsCount = () => {
const envThreads = getEnv('transpilationWorkerThreadsCount');
if (envThreads > 0) {
return envThreads;

Check warning on line 28 in packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js

View check run for this annotation

Codecov / codecov/patch

packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js#L28

Added line #L28 was not covered by tests
}

const cpuCount = os.cpus()?.length;
if (cpuCount) {
// there's no practical boost above 5 threads even if you have more cores.
return Math.min(Math.max(1, cpuCount - 1), 5);
}

return 3; // Default (like the workerpool do)

Check warning on line 37 in packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js

View check run for this annotation

Codecov / codecov/patch

packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js#L37

Added line #L37 was not covered by tests
};

export class DataSchemaCompiler {
constructor(repository, options = {}) {
this.repository = repository;
Expand Down Expand Up @@ -100,6 +116,7 @@

const transpilationWorkerThreads = getEnv('transpilationWorkerThreads');
const transpilationNative = getEnv('transpilationNative');
const transpilationNativeThreadsCount = getThreadsCount();
const { compilerId } = this;

if (!transpilationNative && transpilationWorkerThreads) {
Expand All @@ -110,7 +127,11 @@
);
}

const transpile = async () => {
/**
* @param stage Number
* @returns {Promise<*>}
*/
const transpile = async (stage) => {
let cubeNames;
let cubeSymbols;
let transpilerNames;
Expand Down Expand Up @@ -145,9 +166,28 @@
content: ';',
};

await this.transpileJsFile(dummyFile, errorsReport, { cubeNames, cubeSymbols, transpilerNames, contextSymbols: CONTEXT_SYMBOLS, compilerId });
await this.transpileJsFile(dummyFile, errorsReport, { cubeNames, cubeSymbols, transpilerNames, contextSymbols: CONTEXT_SYMBOLS, compilerId, stage });

Check warning on line 169 in packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js

View check run for this annotation

Codecov / codecov/patch

packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js#L169

Added line #L169 was not covered by tests

const nonJsFilesTasks = toCompile.filter(file => !file.fileName.endsWith('.js'))
.map(f => this.transpileFile(f, errorsReport, { transpilerNames, compilerId }));

Check warning on line 172 in packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js

View check run for this annotation

Codecov / codecov/patch

packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js#L171-L172

Added lines #L171 - L172 were not covered by tests

const jsFiles = toCompile.filter(file => file.fileName.endsWith('.js'));

Check warning on line 174 in packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js

View check run for this annotation

Codecov / codecov/patch

packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js#L174

Added line #L174 was not covered by tests
let jsChunks;
if (jsFiles.length < transpilationNativeThreadsCount * transpilationNativeThreadsCount) {
jsChunks = [jsFiles];

Check warning on line 177 in packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js

View check run for this annotation

Codecov / codecov/patch

packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js#L177

Added line #L177 was not covered by tests
} else {
const baseSize = Math.floor(jsFiles.length / transpilationNativeThreadsCount);
jsChunks = [];
for (let i = 0; i < transpilationNativeThreadsCount; i++) {

Check warning on line 181 in packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js

View check run for this annotation

Codecov / codecov/patch

packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js#L179-L181

Added lines #L179 - L181 were not covered by tests
// For the last part, we take the remaining files so we don't lose the extra ones.
const start = i * baseSize;

Check warning on line 183 in packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js

View check run for this annotation

Codecov / codecov/patch

packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js#L183

Added line #L183 was not covered by tests
const end = (i === transpilationNativeThreadsCount - 1) ? jsFiles.length : start + baseSize;
jsChunks.push(jsFiles.slice(start, end));

Check warning on line 185 in packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js

View check run for this annotation

Codecov / codecov/patch

packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js#L185

Added line #L185 was not covered by tests
}
}
const JsFilesTasks = jsChunks.map(chunk => this.transpileJsFilesBulk(chunk, errorsReport, { transpilerNames, compilerId }));

Check warning on line 188 in packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js

View check run for this annotation

Codecov / codecov/patch

packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js#L188

Added line #L188 was not covered by tests

results = await Promise.all(toCompile.map(f => this.transpileFile(f, errorsReport, { transpilerNames, compilerId })));
results = (await Promise.all([...nonJsFilesTasks, ...JsFilesTasks])).flat();

Check warning on line 190 in packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js

View check run for this annotation

Codecov / codecov/patch

packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js#L190

Added line #L190 was not covered by tests
} else if (transpilationWorkerThreads) {
results = await Promise.all(toCompile.map(f => this.transpileFile(f, errorsReport, { cubeNames, cubeSymbols, transpilerNames })));
} else {
Expand All @@ -157,17 +197,17 @@
return results.filter(f => !!f);
};

const compilePhase = async (compilers) => this.compileCubeFiles(compilers, await transpile(), errorsReport);
const compilePhase = async (compilers, stage) => this.compileCubeFiles(compilers, await transpile(stage), errorsReport);

return compilePhase({ cubeCompilers: this.cubeNameCompilers })
.then(() => compilePhase({ cubeCompilers: this.preTranspileCubeCompilers.concat([this.viewCompilationGate]) }))
return compilePhase({ cubeCompilers: this.cubeNameCompilers }, 0)
.then(() => compilePhase({ cubeCompilers: this.preTranspileCubeCompilers.concat([this.viewCompilationGate]) }, 1))
.then(() => (this.viewCompilationGate.shouldCompileViews() ?
compilePhase({ cubeCompilers: this.viewCompilers })
compilePhase({ cubeCompilers: this.viewCompilers }, 2)
: Promise.resolve()))
.then(() => compilePhase({
cubeCompilers: this.cubeCompilers,
contextCompilers: this.contextCompilers,
}))
}, 3))
.then(() => {
if (transpilationNative) {
// Clean up cache
Expand All @@ -179,7 +219,7 @@
return this.transpileJsFile(
dummyFile,
errorsReport,
{ cubeNames: [], cubeSymbols: {}, transpilerNames: [], contextSymbols: {}, compilerId: this.compilerId }
{ cubeNames: [], cubeSymbols: {}, transpilerNames: [], contextSymbols: {}, compilerId: this.compilerId, stage: 0 }
);
} else if (transpilationWorkerThreads && this.workerPool) {
this.workerPool.terminate();
Expand Down Expand Up @@ -227,29 +267,69 @@
}
}

async transpileJsFile(file, errorsReport, { cubeNames, cubeSymbols, contextSymbols, transpilerNames, compilerId }) {
/**
* Right now it is used only for transpilation in native,
* so no checks for transpilation type inside this method
*/
async transpileJsFilesBulk(files, errorsReport, { cubeNames, cubeSymbols, contextSymbols, transpilerNames, compilerId, stage }) {

Check warning on line 274 in packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js

View check run for this annotation

Codecov / codecov/patch

packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js#L274

Added line #L274 was not covered by tests
// for bulk processing this data may be optimized even more by passing transpilerNames, compilerId only once for a bulk
// but this requires more complex logic to be implemented in the native side.
// And comparing to the file content sizes, a few bytes of JSON data is not a big deal here
const reqDataArr = files.map(file => ({

Check warning on line 278 in packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js

View check run for this annotation

Codecov / codecov/patch

packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js#L278

Added line #L278 was not covered by tests
fileName: file.fileName,
fileContent: file.content,
transpilers: transpilerNames,
compilerId,
...(cubeNames && {
metaData: {
cubeNames,
cubeSymbols,
contextSymbols,
stage
},
}),
}));
const res = await transpileJs(reqDataArr);

Check warning on line 292 in packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js

View check run for this annotation

Codecov / codecov/patch

packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js#L292

Added line #L292 was not covered by tests

return files.map((file, index) => {
errorsReport.inFile(file);

Check warning on line 295 in packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js

View check run for this annotation

Codecov / codecov/patch

packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js#L294-L295

Added lines #L294 - L295 were not covered by tests
if (!res[index]) { // This should not happen in theory but just to be safe
errorsReport.error(`No transpilation result received for the file ${file.fileName}.`);
return undefined;

Check warning on line 298 in packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js

View check run for this annotation

Codecov / codecov/patch

packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js#L297-L298

Added lines #L297 - L298 were not covered by tests
}
errorsReport.addErrors(res[index].errors);
errorsReport.addWarnings(res[index].warnings);
errorsReport.exitFile();

Check warning on line 302 in packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js

View check run for this annotation

Codecov / codecov/patch

packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js#L300-L302

Added lines #L300 - L302 were not covered by tests

return { ...file, content: res[index].code };

Check warning on line 304 in packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js

View check run for this annotation

Codecov / codecov/patch

packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js#L304

Added line #L304 was not covered by tests
});
}

async transpileJsFile(file, errorsReport, { cubeNames, cubeSymbols, contextSymbols, transpilerNames, compilerId, stage }) {
try {
if (getEnv('transpilationNative')) {
const reqData = {
fileName: file.fileName,
fileContent: file.content,
transpilers: transpilerNames,
compilerId,
...(cubeNames && {
metaData: {
cubeNames,
cubeSymbols,
contextSymbols,
stage
},
}),
};

errorsReport.inFile(file);
const res = await transpileJs(file.content, reqData);
errorsReport.addErrors(res.errors);
errorsReport.addWarnings(res.warnings);
const res = await transpileJs([reqData]);
errorsReport.addErrors(res[0].errors);
errorsReport.addWarnings(res[0].warnings);

Check warning on line 329 in packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js

View check run for this annotation

Codecov / codecov/patch

packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js#L327-L329

Added lines #L327 - L329 were not covered by tests
errorsReport.exitFile();

return { ...file, content: res.code };
return { ...file, content: res[0].code };

Check warning on line 332 in packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js

View check run for this annotation

Codecov / codecov/patch

packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js#L332

Added line #L332 was not covered by tests
} else if (getEnv('transpilationWorkerThreads')) {
const data = {
fileName: file.fileName,
Expand Down
Loading