Skip to content

Commit

Permalink
add launch all frontend functionality for sensors
Browse files Browse the repository at this point in the history
  • Loading branch information
dliu27 committed Dec 9, 2024
1 parent aa85f09 commit d934149
Show file tree
Hide file tree
Showing 7 changed files with 447 additions and 11 deletions.
1 change: 1 addition & 0 deletions js_modules/dagster-ui/packages/ui-core/client.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions js_modules/dagster-ui/packages/ui-core/src/app/Telemetry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {gql} from '../apollo-client';

export enum TelemetryAction {
LAUNCH_RUN = 'LAUNCH_RUN',
LAUNCH_MULTIPLE_RUNS = 'LAUNCH_MULTIPLE_RUNS',
GRAPHQL_QUERY_COMPLETED = 'GRAPHQL_QUERY_COMPLETED',
}

Expand Down Expand Up @@ -38,7 +39,7 @@ const LOG_TELEMETRY_MUTATION = gql`
export async function logTelemetry(
pathPrefix: string,
action: TelemetryAction,
metadata: {[key: string]: string | null | undefined} = {},
metadata: {[key: string]: string | string[] | null | undefined} = {},
) {
const graphqlPath = `${pathPrefix || ''}/graphql`;

Expand All @@ -63,7 +64,10 @@ export async function logTelemetry(
export const useTelemetryAction = () => {
const {basePath, telemetryEnabled} = useContext(AppContext);
return useCallback(
(action: TelemetryAction, metadata: {[key: string]: string | null | undefined} = {}) => {
(
action: TelemetryAction,
metadata: {[key: string]: string | string[] | null | undefined} = {},
) => {
if (telemetryEnabled) {
logTelemetry(basePath, action, metadata);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {useCallback} from 'react';
import {useHistory} from 'react-router-dom';

import {showLaunchError} from './showLaunchError';
import {useMutation} from '../apollo-client';
import {TelemetryAction, useTelemetryAction} from '../app/Telemetry';
import {
LAUNCH_MULTIPLE_RUNS_MUTATION,
LaunchBehavior,
handleLaunchMultipleResult,
} from '../runs/RunUtils';
import {
LaunchMultipleRunsMutation,
LaunchMultipleRunsMutationVariables,
} from '../runs/types/RunUtils.types';

export function useLaunchMultipleRunsWithTelemetry() {
const [launchMultipleRuns] = useMutation<
LaunchMultipleRunsMutation,
LaunchMultipleRunsMutationVariables
>(LAUNCH_MULTIPLE_RUNS_MUTATION);

const logTelemetry = useTelemetryAction();
const history = useHistory();

return useCallback(
async (variables: LaunchMultipleRunsMutationVariables, behavior: LaunchBehavior) => {
const executionParamsList = Array.isArray(variables.executionParamsList)
? variables.executionParamsList
: [variables.executionParamsList];
const jobNames = executionParamsList.map((params) => params.selector?.jobName);

if (jobNames.length !== executionParamsList.length || jobNames.includes(undefined)) {
return;
}

const metadata: {[key: string]: string | string[] | null | undefined} = {
jobNames: jobNames.filter((name): name is string => name !== undefined),
opSelection: undefined,
};

let result;
try {
result = (await launchMultipleRuns({variables})).data?.launchMultipleRuns;
if (result) {
handleLaunchMultipleResult(result, history, {behavior});
logTelemetry(
TelemetryAction.LAUNCH_MULTIPLE_RUNS,
metadata as {[key: string]: string | string[] | null | undefined},
);
}

return result;
} catch (error) {
console.error('error', error);
showLaunchError(error as Error);
}
return undefined;
},
[history, launchMultipleRuns, logTelemetry],
);
}
152 changes: 150 additions & 2 deletions js_modules/dagster-ui/packages/ui-core/src/runs/RunUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import {StepSelection} from './StepSelection';
import {TimeElapsed} from './TimeElapsed';
import {RunFragment} from './types/RunFragments.types';
import {RunTableRunFragment} from './types/RunTableRunFragment.types';
import {LaunchPipelineExecutionMutation, RunTimeFragment} from './types/RunUtils.types';
import {
LaunchMultipleRunsMutation,
LaunchPipelineExecutionMutation,
RunTimeFragment,
} from './types/RunUtils.types';
import {Mono} from '../../../ui-components/src';
import {gql} from '../apollo-client';
import {showCustomAlert} from '../app/CustomAlertProvider';
Expand Down Expand Up @@ -107,14 +111,99 @@ export async function handleLaunchResult(

if ('errors' in result) {
message += ` Please fix the following errors:\n\n${result.errors
.map((error) => error.message)
.map((error: {message: any}) => error.message)
.join('\n\n')}`;
}

showCustomAlert({body: message});
}
}

export async function handleLaunchMultipleResult(
result: void | null | LaunchMultipleRunsMutation['launchMultipleRuns'],
history: History<unknown>,
options: {behavior: LaunchBehavior; preserveQuerystring?: boolean},
) {
if (!result) {
showCustomAlert({body: `No data was returned. Did dagster-webserver crash?`});
return;
}
const successfulRunIds: string[] = [];
const failedRunsErrors: {message: string}[] = [];

if (result.__typename === 'PythonError') {
// if launch multiple runs errors out, show the PythonError and return
showCustomAlert({
title: 'Error',
body: <PythonErrorInfo error={result} />,
});
return;
} else if (result.__typename === 'LaunchMultipleRunsResult') {
// show corresponding toasts
const launchMultipleRunsResult = result.launchMultipleRunsResult;

for (const individualResult of launchMultipleRunsResult) {
if (individualResult.__typename === 'LaunchRunSuccess') {
successfulRunIds.push(individualResult.run.id);

const pathname = `/runs/${individualResult.run.id}`;
const search = options.preserveQuerystring ? history.location.search : '';
const openInSameTab = () => history.push({pathname, search});

// using open with multiple runs will spam new tabs
if (options.behavior === 'open') {
openInSameTab();
}
} else if (individualResult.__typename === 'PythonError') {
failedRunsErrors.push({message: individualResult.message});
} else {
let message = `Error launching run.`;
if (
individualResult &&
typeof individualResult === 'object' &&
'errors' in individualResult
) {
const errors = individualResult.errors as {message: string}[];
message += ` Please fix the following errors:\n\n${errors
.map((error) => error.message)
.join('\n\n')}`;
}
if (
individualResult &&
typeof individualResult === 'object' &&
'message' in individualResult
) {
message += `\n\n${individualResult.message}`;
}

failedRunsErrors.push({message});
}
}
}
document.dispatchEvent(new CustomEvent('run-launched'));

// link to runs page filtered to run IDs
const params = new URLSearchParams();
successfulRunIds.forEach((id) => params.append('q[]', `id:${id}`));

const queryString = `/runs?${params.toString()}`;
history.push(queryString);

await showSharedToaster({
intent: 'success',
message: <div>Launched {successfulRunIds.length} runs</div>,
action: {
text: 'View',
href: history.createHref({pathname: queryString}),
},
});

// show list of errors that occurred
if (failedRunsErrors.length > 0) {
showCustomAlert({body: failedRunsErrors.map((e) => e.message).join('\n\n')});
}
}

function getBaseExecutionMetadata(run: RunFragment | RunTableRunFragment) {
const hiddenTagKeys: string[] = [DagsterTag.IsResumeRetry, DagsterTag.StepSelection];

Expand Down Expand Up @@ -204,6 +293,65 @@ export const LAUNCH_PIPELINE_EXECUTION_MUTATION = gql`
${PYTHON_ERROR_FRAGMENT}
`;

export const LAUNCH_MULTIPLE_RUNS_MUTATION = gql`
mutation LaunchMultipleRuns($executionParamsList: [ExecutionParams!]!) {
launchMultipleRuns(executionParamsList: $executionParamsList) {
__typename
... on LaunchMultipleRunsResult {
launchMultipleRunsResult {
__typename
... on InvalidStepError {
invalidStepKey
}
... on InvalidOutputError {
stepKey
invalidOutputName
}
... on LaunchRunSuccess {
run {
id
pipeline {
name
}
tags {
key
value
}
status
runConfigYaml
mode
resolvedOpSelection
}
}
... on ConflictingExecutionParamsError {
message
}
... on PresetNotFoundError {
preset
message
}
... on RunConfigValidationInvalid {
pipelineName
errors {
__typename
message
path
reason
}
}
... on PipelineNotFoundError {
message
pipelineName
}
...PythonErrorFragment
}
}
...PythonErrorFragment
}
}
${PYTHON_ERROR_FRAGMENT}
`;

export const DELETE_MUTATION = gql`
mutation Delete($runId: String!) {
deletePipelineRun(runId: $runId) {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit d934149

Please sign in to comment.