Skip to content

Commit 41cf2c6

Browse files
committed
Merge with main
2 parents 1e20913 + c769e26 commit 41cf2c6

File tree

5 files changed

+193
-1
lines changed

5 files changed

+193
-1
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { AzureWizardPromptStep, validationUtils } from '@microsoft/vscode-azext-utils';
7+
import { ConnectionType } from '../../../../constants';
8+
import { localize } from '../../../../localize';
9+
import { type IDTSConnectionWizardContext } from './IDTSConnectionWizardContext';
10+
11+
export class DTSConnectionCustomPromptStep<T extends IDTSConnectionWizardContext> extends AzureWizardPromptStep<T> {
12+
public async prompt(context: T): Promise<void> {
13+
context.newDTSConnectionSetting = (await context.ui.showInputBox({
14+
prompt: localize('customDTSConnectionPrompt', 'Provide a custom DTS connection string.'),
15+
validateInput: (value: string | undefined) => this.validateInput(value)
16+
})).trim();
17+
}
18+
19+
public shouldPrompt(context: T): boolean {
20+
return !context.newDTSConnectionSetting && context.dtsConnectionType === ConnectionType.Custom;
21+
}
22+
23+
private validateInput(name: string | undefined): string | undefined {
24+
name = name ? name.trim() : '';
25+
if (!validationUtils.hasValidCharLength(name)) {
26+
return validationUtils.getInvalidCharLengthMessage();
27+
}
28+
return undefined;
29+
}
30+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { AzureWizardPromptStep, type AzureWizardExecuteStep, type IWizardOptions } from '@microsoft/vscode-azext-utils';
7+
import { type MessageItem } from 'vscode';
8+
import { ConnectionType } from '../../../../constants';
9+
import { useEmulator } from '../../../../constants-nls';
10+
import { localize } from '../../../../localize';
11+
import { DTSConnectionCustomPromptStep } from './DTSConnectionCustomPromptStep';
12+
import { DTSConnectionSetSettingStep } from './DTSConnectionSetSettingStep';
13+
import { DTSEmulatorStartStep } from './DTSEmulatorStartStep';
14+
import { DTSHubNameCustomPromptStep } from './DTSHubNameCustomPromptStep';
15+
import { DTSHubNameSetSettingStep } from './DTSHubNameSetSettingStep';
16+
import { type IDTSConnectionWizardContext } from './IDTSConnectionWizardContext';
17+
18+
export class DTSConnectionTypeListStep<T extends IDTSConnectionWizardContext> extends AzureWizardPromptStep<T> {
19+
constructor(readonly connectionTypes: Set<ConnectionType>) {
20+
super();
21+
}
22+
23+
public async prompt(context: T): Promise<void> {
24+
const connectAzureButton = { title: localize('connectAzureTaskScheduler', 'Connect Azure Task Scheduler'), data: ConnectionType.Azure };
25+
const connectEmulatorButton = { title: useEmulator, data: ConnectionType.Emulator };
26+
const connectCustomDTSButton = { title: localize('connectCustomTaskScheduler', 'Manually Set a Connection String'), data: ConnectionType.Custom };
27+
28+
const buttons: MessageItem[] = [];
29+
if (this.connectionTypes.has(ConnectionType.Azure)) {
30+
buttons.push(connectAzureButton);
31+
}
32+
if (this.connectionTypes.has(ConnectionType.Emulator)) {
33+
buttons.push(connectEmulatorButton);
34+
}
35+
if (this.connectionTypes.has(ConnectionType.Custom)) {
36+
buttons.push(connectCustomDTSButton);
37+
}
38+
39+
const message: string = localize('selectDTSConnection', 'Durable Functions needs to be configured to use a Durable Task Scheduler.');
40+
context.dtsConnectionType = (await context.ui.showWarningMessage(message, { modal: true }, ...buttons) as {
41+
title: string;
42+
data: ConnectionType;
43+
}).data;
44+
45+
context.telemetry.properties.dtsConnectionType = context.dtsConnectionType;
46+
}
47+
48+
public shouldPrompt(context: T): boolean {
49+
return !context.dtsConnectionType;
50+
}
51+
52+
public async getSubWizard(context: T): Promise<IWizardOptions<T> | undefined> {
53+
const promptSteps: AzureWizardPromptStep<T>[] = [];
54+
const executeSteps: AzureWizardExecuteStep<T>[] = [];
55+
56+
switch (context.dtsConnectionType) {
57+
case ConnectionType.Azure:
58+
throw new Error('Needs implementation.');
59+
case ConnectionType.Emulator:
60+
executeSteps.push(new DTSEmulatorStartStep());
61+
break;
62+
case ConnectionType.Custom:
63+
promptSteps.push(
64+
new DTSConnectionCustomPromptStep(),
65+
new DTSHubNameCustomPromptStep(),
66+
);
67+
break;
68+
}
69+
70+
executeSteps.push(
71+
new DTSConnectionSetSettingStep(),
72+
new DTSHubNameSetSettingStep(),
73+
);
74+
75+
return { promptSteps, executeSteps };
76+
}
77+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { AzureWizardExecuteStep, nonNullValue } from '@microsoft/vscode-azext-utils';
7+
import { commands, window } from 'vscode';
8+
import { ConnectionType } from '../../../../constants';
9+
import { ext } from '../../../../extensionVariables';
10+
import { localize } from '../../../../localize';
11+
import { type DurableTaskSchedulerEmulator } from '../../../../tree/durableTaskScheduler/DurableTaskSchedulerEmulatorClient';
12+
import { type IDTSConnectionWizardContext } from './IDTSConnectionWizardContext';
13+
14+
export class DTSEmulatorStartStep<T extends IDTSConnectionWizardContext> extends AzureWizardExecuteStep<T> {
15+
public priority: number = 200;
16+
17+
public async execute(context: T): Promise<void> {
18+
const emulatorId: string = nonNullValue(
19+
await commands.executeCommand('azureFunctions.durableTaskScheduler.startEmulator'),
20+
localize('failedToStartEmulator', 'Internal error: Failed to start DTS emulator.'),
21+
);
22+
23+
const emulators: DurableTaskSchedulerEmulator[] = nonNullValue(
24+
await commands.executeCommand('azureFunctions.durableTaskScheduler.getEmulators'),
25+
localize('failedToGetEmulators', 'Internal error: Failed to retrieve the list of DTS emulators.'),
26+
);
27+
28+
const emulator: DurableTaskSchedulerEmulator = nonNullValue(
29+
emulators.find(e => e.id === emulatorId),
30+
localize('couldNotFindEmulator', 'Internal error: Failed to retrieve info on the started DTS emulator.'),
31+
);
32+
33+
const { schedulerEndpoint, dashboardEndpoint } = emulator;
34+
35+
const message: string = localize('emulatorStartedMessage', `Durable Task Scheduler (DTS) emulator has been started by your container client at "{0}". Its dashboard is available at "{1}".`, schedulerEndpoint.toString(), dashboardEndpoint.toString());
36+
void window.showInformationMessage(message);
37+
ext.outputChannel.appendLog(message);
38+
39+
context.newDTSConnectionSetting = `Endpoint=${emulator.schedulerEndpoint};Authentication=None`;
40+
context.newDTSHubNameConnectionSetting = 'default';
41+
}
42+
43+
public shouldExecute(context: T): boolean {
44+
return !context.newDTSConnectionSetting && context.dtsConnectionType === ConnectionType.Emulator;
45+
}
46+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { AzureWizardPromptStep, validationUtils, type IActionContext } from '@microsoft/vscode-azext-utils';
7+
import * as path from 'path';
8+
import { ConnectionKey, ConnectionType, localSettingsFileName } from '../../../../constants';
9+
import { getLocalSettingsJson } from '../../../../funcConfig/local.settings';
10+
import { localize } from '../../../../localize';
11+
import { type IDTSConnectionWizardContext } from './IDTSConnectionWizardContext';
12+
13+
export class DTSHubNameCustomPromptStep<T extends IDTSConnectionWizardContext> extends AzureWizardPromptStep<T> {
14+
public async prompt(context: T): Promise<void> {
15+
context.newDTSHubNameConnectionSetting = (await context.ui.showInputBox({
16+
prompt: localize('customDTSConnectionPrompt', 'Provide the custom DTS hub name.'),
17+
value: await getDTSHubName(context, context.projectPath),
18+
validateInput: (value: string) => this.validateInput(value)
19+
})).trim();
20+
}
21+
22+
public shouldPrompt(context: T): boolean {
23+
return !context.newDTSHubNameConnectionSetting && context.dtsConnectionType === ConnectionType.Custom;
24+
}
25+
26+
private validateInput(name: string): string | undefined {
27+
name = name.trim();
28+
29+
if (!validationUtils.hasValidCharLength(name)) {
30+
return validationUtils.getInvalidCharLengthMessage();
31+
}
32+
return undefined;
33+
}
34+
}
35+
36+
async function getDTSHubName(context: IActionContext, projectPath: string): Promise<string | undefined> {
37+
const localSettingsJson = await getLocalSettingsJson(context, path.join(projectPath, localSettingsFileName));
38+
return localSettingsJson.Values?.[ConnectionKey.DTSHub];
39+
}

src/debug/durable/validateDTSConnectionPreDebug.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,6 @@ export async function isAliveConnection(context: IActionContext, dtsConnection:
5656
} catch (e) {
5757
// Even if we get back an error, if we can read a status code, the connection provided a response and is still alive
5858
const statusCode = (e as { statusCode?: number })?.statusCode;
59-
return statusCode ? true : false;
59+
return !!statusCode;
6060
}
6161
}

0 commit comments

Comments
 (0)