Skip to content

Commit

Permalink
Merge pull request #113 from datacoves/DCV-1654-switch-dbt-osmosis-to…
Browse files Browse the repository at this point in the history
…-dbt-core-interface

Dcv 1654 switch dbt osmosis to dbt core interface
  • Loading branch information
RobertOstermann authored Sep 12, 2023
2 parents 62e0cda + 761b07e commit 54b39e0
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 128 deletions.
17 changes: 9 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@
"sqlfluff.linter.lintEntireProject": {
"type": "boolean",
"default": false,
"markdownDescription": "Determines if the linter will lint the workspaces on startup and configuration changes. Does not work with `dbt-osmosis`."
"markdownDescription": "Determines if the linter will lint the workspaces on startup and configuration changes. Does not work with `dbt-core-interface`."
},
"sqlfluff.linter.languages": {
"type": "array",
Expand Down Expand Up @@ -391,20 +391,20 @@
"Do not run the linter."
]
},
"sqlfluff.osmosis.enabled": {
"sqlfluff.dbtInterface.enabled": {
"type": "boolean",
"default": false,
"markdownDescription": "Enable this if `dbt-osmosis` is installed. This disables all other options except for `sqlfluff.config`."
"markdownDescription": "Enable this if `dbt-core-interface` is installed. This disables all other options except for `sqlfluff.config`."
},
"sqlfluff.osmosis.host": {
"sqlfluff.dbtInterface.host": {
"type": "string",
"default": "localhost",
"description": "The host for the osmosis server."
"description": "The host for the dbt-interface server."
},
"sqlfluff.osmosis.port": {
"sqlfluff.dbtInterface.port": {
"type": "number",
"default": 8581,
"description": "The port for the osmosis server."
"description": "The port for the dbt-interface server."
}
}
}
Expand All @@ -423,7 +423,8 @@
"esbuild": "npm run -S esbuild-base -- --sourcemap",
"esbuild-watch": "npm run -S esbuild-base -- --sourcemap --watch",
"postbuild": "copyfiles \"./test/suite/test_sql/**/*.sql\" \"./out\" && copyfiles \"./test/.sqlfluff\" \"./out\"",
"deploy": "vsce publish"
"deploy": "vsce publish",
"build-vsix": "vsce package"
},
"dependencies": {
"dotenv": "^16.3.1",
Expand Down
2 changes: 1 addition & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const activate = (context: vscode.ExtensionContext) => {

linterSelectors.forEach(selector => {
// Register the code actions
if (!Configuration.osmosisEnabled()) {
if (!Configuration.dbtInterfaceEnabled()) {
const codeActionProvider = vscode.languages.registerCodeActionsProvider(selector, new QuickFixProvider(), {
providedCodeActionKinds: QuickFixProvider.providedCodeActionKind,
});
Expand Down
17 changes: 9 additions & 8 deletions src/features/helper/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default class Configuration {
if (
event.affectsConfiguration("sqlfluff.format.languages") ||
event.affectsConfiguration("sqlfluff.linter.languages") ||
event.affectsConfiguration("sqlfluff.osmosis.enabled") ||
event.affectsConfiguration("sqlfluff.dbtInterface.enabled") ||
event.affectsConfiguration("sqlfluff.experimental.format.executeInTerminal")
) {
const action = "Reload";
Expand Down Expand Up @@ -396,22 +396,23 @@ export default class Configuration {
}
// #endregion

// #region Osmosis
public static osmosisEnabled(): boolean {
/* DBT Interface */

public static dbtInterfaceEnabled(): boolean {
return vscode.workspace
.getConfiguration("sqlfluff.osmosis")
.getConfiguration("sqlfluff.dbtInterface")
.get<boolean>("enabled", false);
}

public static osmosisHost(): string {
public static dbtInterfaceHost(): string {
return vscode.workspace
.getConfiguration("sqlfluff.osmosis")
.getConfiguration("sqlfluff.dbtInterface")
.get<string>("host", "localhost");
}

public static osmosisPort(): number {
public static dbtInterfacePort(): number {
return vscode.workspace
.getConfiguration("sqlfluff.osmosis")
.getConfiguration("sqlfluff.dbtInterface")
.get<number>("port", 8581);
}
// #endregion
Expand Down
148 changes: 148 additions & 0 deletions src/features/helper/dbtInterface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import AbortController from "node-abort-controller";
import fetch, { Response } from "node-fetch";
import { AbortSignal } from "node-fetch/externals";

import Configuration from "./configuration";
import Utilities from "./utilities";

export interface DbtInterfaceRunResult {
column_names: string[],
rows: any[][],
raw_sql: string,
compiled_sql: string,
}

export interface DbtInterfaceCompileResult {
result: string;
}

export interface DbtInterfaceResetResult {
result: string;
}

export enum DbtInterfaceFullReparse {
True = "true",
False = "false"
}

export enum DbtInterfaceErrorCode {
FailedToReachServer = -1,
CompileSqlFailure = 1,
ExecuteSqlFailure = 2,
ProjectParseFailure = 3,
}

export interface DbtInterfaceErrorContainer {
error: {
code: DbtInterfaceErrorCode,
message: string,
data: { [index: string]: (string | number); },
};
}

export class DbtInterface {
private sql: string | undefined;
private sql_path: string | undefined;
private extra_config_path: string;

constructor(sql: string | undefined, sql_path: string | undefined, extra_config_path: string) {
this.sql = sql;
this.sql_path = sql_path;
this.extra_config_path = extra_config_path;
}

public getLintURL(): string {
let url = `http://${Configuration.dbtInterfaceHost()}:${Configuration.dbtInterfacePort()}/lint?sql_path=${this.sql_path}`;
if (this.sql !== undefined) {
url = `http://${Configuration.dbtInterfaceHost()}:${Configuration.dbtInterfacePort()}/lint?`;
}

if (this.extra_config_path) {
url += `&extra_config_path=${this.extra_config_path}`;
}

return url;
}

public async healthCheck(): Promise<any> {
const abortController = new AbortController();
const timeoutHandler = setTimeout(() => {
abortController.abort();
}, 1000);
try {
const response = await fetch(
`http://${Configuration.dbtInterfaceHost()}:${Configuration.dbtInterfacePort()}/health`,
{
method: "GET",
signal: abortController.signal as AbortSignal
},
);
if (response.status === 200) {
return true;
} else {
return false;
}
} catch (e) {
return false;
} finally {
clearTimeout(timeoutHandler);
}
}

public async lint<T>(timeout = 25000) {
const failedToReachServerError: DbtInterfaceErrorContainer = {
error: {
code: DbtInterfaceErrorCode.FailedToReachServer,
message: "Query failed to reach dbt sync server.",
data: {
"error": `Is the server listening on the http://${Configuration.dbtInterfaceHost()}:${Configuration.dbtInterfacePort()} address?`,
},
},
};

const projectNotRegisteredError: DbtInterfaceErrorContainer = {
error: {
code: DbtInterfaceErrorCode.FailedToReachServer,
message: "dbt project not registered",
data: {
"error": "",
},
},
};

if (!await this.healthCheck()) {
Utilities.appendHyphenatedLine();
Utilities.outputChannel.appendLine("Unhealthy dbt project:");
Utilities.appendHyphenatedLine();
return projectNotRegisteredError;
}

const abortController = new AbortController();
const timeoutHandler = setTimeout(() => {
abortController.abort();
}, timeout);
let response: Response;

try {
response = await fetch(
encodeURI(this.getLintURL()),
{
method: "POST",
signal: abortController.signal as AbortSignal,
body: this.sql,
},
);
} catch (error) {
Utilities.appendHyphenatedLine();
Utilities.outputChannel.appendLine("Raw dbt-omsosis /lint error response:");
Utilities.appendHyphenatedLine();
Utilities.outputChannel.appendLine(error as string);
Utilities.appendHyphenatedLine();

clearTimeout(timeoutHandler);
return failedToReachServerError;
}
clearTimeout(timeoutHandler);
return await response.json() as T;
}
}
105 changes: 0 additions & 105 deletions src/features/helper/osmosis.ts

This file was deleted.

12 changes: 6 additions & 6 deletions src/features/providers/sqlfluff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { StringDecoder } from "string_decoder";
import * as vscode from "vscode";

import Configuration from "../helper/configuration";
import { DbtInterface } from "../helper/dbtInterface";
import { LineDecoder } from "../helper/lineDecoder";
import { Osmosis } from "../helper/osmosis";
import Utilities from "../helper/utilities";
import FilePath from "./linter/types/filePath";
import CommandOptions from "./types/commandOptions";
Expand Down Expand Up @@ -51,15 +51,15 @@ export default class SQLFluff {
finalArgs.push(targetFileRelativePath);
}

if (Configuration.osmosisEnabled() && command === CommandType.LINT) {
const osmosis = new Osmosis(
if (Configuration.dbtInterfaceEnabled() && command === CommandType.LINT) {
const dbtInterface = new DbtInterface(
shouldUseStdin ? options.fileContents : undefined,
options.workspacePath ?? options.filePath,
Configuration.config(),
);

Utilities.outputChannel.appendLine("\n--------------------Executing Command--------------------\n");
Utilities.outputChannel.appendLine(osmosis.getURL());
Utilities.outputChannel.appendLine(dbtInterface.getLintURL());
if (shouldUseStdin) {
Utilities.outputChannel.appendLine("\n-----Request Body-----\n");
if (options.fileContents) {
Expand All @@ -71,7 +71,7 @@ export default class SQLFluff {

Utilities.appendHyphenatedLine();

const response: any = await osmosis.lint();
const response: any = await dbtInterface.lint();
const output: FilePath[] = [
{
filepath: options.filePath,
Expand All @@ -88,7 +88,7 @@ export default class SQLFluff {
const code = response?.error?.code ?? 0;
const succeeded = code === 0;
if (!succeeded && !Configuration.suppressNotifications()) {
const message = response?.error?.message ?? "DBT-Osmosis linting error.";
const message = response?.error?.message ?? "DBT-Interface linting error.";
const detail = response?.error?.data?.error ?? "";

vscode.window.showErrorMessage([message, detail].join("\n"));
Expand Down

0 comments on commit 54b39e0

Please sign in to comment.