Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(FIR-37168): testConnection doesn't reset autostop timer #122

Merged
merged 11 commits into from
Oct 15, 2024
12 changes: 11 additions & 1 deletion src/connection/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ export abstract class Connection {

abstract resolveEngineEndpoint(): Promise<string>;

abstract testConnection(): Promise<void>;

protected getRequestUrl(executeQueryOptions: ExecuteQueryOptions): string {
const params = this.getBaseParameters(executeQueryOptions);

Expand Down Expand Up @@ -81,7 +83,15 @@ export abstract class Connection {
const strSettings = Object.entries(settings ?? {}).reduce<
Record<string, string>
>((acc, [key, value]) => {
if (value !== undefined) {
if (key === "internal") {
// Unwrap internal settings from array
const internalSettings = value as Record<string, string | number>[];
internalSettings.forEach(setting => {
Object.entries(setting).forEach(([internalKey, internalValue]) => {
acc[internalKey] = internalValue.toString();
});
});
} else if (value !== undefined) {
acc[key] = value.toString();
}
return acc;
Expand Down
4 changes: 4 additions & 0 deletions src/connection/connection_v1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,8 @@ export class ConnectionV1 extends BaseConnection {
}
return this.accountInfo;
}

async testConnection() {
await this.execute("select 1");
}
}
5 changes: 5 additions & 0 deletions src/connection/connection_v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,9 @@ export class ConnectionV2 extends BaseConnection {

return this.engineEndpoint;
}

async testConnection() {
const settings = { internal: [{ auto_start_stop_control: "ignore" }] };
await this.execute("select 1", { settings });
}
}
2 changes: 1 addition & 1 deletion src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ export class FireboltCore {
const connection = makeConnection(this.context, connectionOptions);
await auth.authenticate();
await connection.resolveEngineEndpoint();
await connection.execute("select 1");
await connection.testConnection();
}
}
3 changes: 2 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ export enum OutputFormat {

export type QuerySettings = Record<
string,
string | number | boolean | undefined
string | number | boolean | undefined | Record<string, string | number>[]
> & {
output_format?: OutputFormat;
internal?: Record<string, string | number>[];
};

export type RowParser = (row: string, isLastRow: boolean) => any;
Expand Down
30 changes: 30 additions & 0 deletions test/unit/connection.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,36 @@ INFO: SYNTAX_ERROR - Unexpected character at {"failingLine":42,"startOffset":120
expect(searchParamsUsed.get("param")).toEqual("value");
});

it("handles settings in execute", async () => {
server.use(
rest.post(`https://some_engine.com`, async (req, res, ctx) => {
const body = await req.text();
const urlParams = Object.fromEntries(req.url.searchParams.entries());
expect(urlParams).toHaveProperty("param");
if (body.startsWith("SELECT 1")) {
return res(ctx.json(emptyResponse));
}
})
);

const connectionParams: ConnectionOptions = {
auth: {
client_id: "dummy",
client_secret: "dummy"
},
database: "dummy",
engineName: "dummy",
account: "my_account"
};
const firebolt = Firebolt({
apiEndpoint
});

const connection = await firebolt.connect(connectionParams);
await connection.execute("SELECT 1", { settings: { param: "value" } });
});


it("handles invalid set statements correctly", async () => {
let searchParamsUsed = new URLSearchParams();
let searchParamsUsed2 = new URLSearchParams();
Expand Down
28 changes: 27 additions & 1 deletion test/unit/v1/connection.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { rest } from "msw";
import { ConnectionOptions, Firebolt } from "../../../src";
import { ConnectionV1 } from "../../../src/connection/connection_v1";


const apiEndpoint = "fake.api.com";
const accountName = "my_account";

Expand Down Expand Up @@ -136,6 +135,33 @@ describe("Connection v1", () => {
).resolveAccountInfo();
expect(account_info.id).toBe("some_account");
});
it("testConnection works", async () => {
// override select 1 response and check within it that query parameter is not set
server.use(
rest.post(`https://some_engine.com/`, (req, res, ctx) => {
const urlParams = Object.fromEntries(req.url.searchParams.entries());
expect(urlParams).not.toContain("auto_start_stop_control");
return res(ctx.json(selectOneResponse));
})
);

const firebolt = Firebolt({ apiEndpoint });

const connectionParams: ConnectionOptions = {
auth: {
username: "user",
password: "pass"
},
database: "dummy",
engineName: "dummy",
account: accountName
};

const connection = await firebolt.connect(connectionParams);
await connection.testConnection();
// also test the method from core
await firebolt.testConnection(connectionParams);
});
it("Can run set statements", async () => {
const param = "my_var";
const value = "1";
Expand Down
46 changes: 46 additions & 0 deletions test/unit/v2/connection.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,52 @@ describe("Connection V2", () => {

expect(engineUrlCalls).toBe(1);
});
it("testConnection works", async () => {
const firebolt = Firebolt({
apiEndpoint
});

server.use(
rest.post(`https://id.fake.firebolt.io/oauth/token`, (req, res, ctx) => {
return res(
ctx.json({
access_token: "fake_access_token"
})
);
}),
rest.get(
`https://api.fake.firebolt.io/web/v3/account/my_account/engineUrl`,
(req, res, ctx) => {
return res(
ctx.json({
engineUrl: "https://some_system_engine.com"
})
);
}
),
rest.post(
`https://some_system_engine.com/${QUERY_URL}`,
(req, res, ctx) => {
const urlParams = Object.fromEntries(req.url.searchParams.entries());
expect(urlParams).toHaveProperty("auto_start_stop_control");
return res(ctx.json(engineUrlResponse));
}
)
);

const connectionParams: ConnectionOptions = {
auth: {
client_id: "dummy",
client_secret: "dummy"
},
account: "my_account"
};

const connection = await firebolt.connect(connectionParams);
await connection.testConnection();
// also test the method from core
await firebolt.testConnection(connectionParams);
});
it("respects useCache option", async () => {
const firebolt = Firebolt({
apiEndpoint
Expand Down