Skip to content

Commit

Permalink
feat(console): implement resource running state indicators (#6643)
Browse files Browse the repository at this point in the history
Closes #6622.
  • Loading branch information
skyrpex authored Jun 25, 2024
1 parent 1a813ea commit 7b3093d
Show file tree
Hide file tree
Showing 35 changed files with 660 additions and 378 deletions.
9 changes: 9 additions & 0 deletions apps/wing-console/console/app/demo/main.w
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
bring cloud;
bring ex;
bring ui;
bring util;
bring sim;

let errorService = new cloud.Service(inflight () => {}) as "ErrorService";

let errorResource = new sim.Resource(inflight () => {
util.sleep(5s);
throw "Oops";
}) as "ErrorResource" in errorService;

// @see https://github.com/winglang/wing/issues/4237 it crashes the Console preview env.
//let secret = new cloud.Secret(name: "my-secret");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@ export const TreeItem = ({

useEffect(() => {
if (selected) {
ref.current?.scrollIntoView();
ref.current?.scrollIntoView({
block: "nearest",
});
}
}, [selected, ref]);

Expand Down
1 change: 0 additions & 1 deletion apps/wing-console/console/server/src/expressServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ export const createExpressServer = async ({
"/trpc",
trpcExpress.createExpressMiddleware({
router,
batching: { enabled: false },
createContext,
}),
);
Expand Down
11 changes: 9 additions & 2 deletions apps/wing-console/console/server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ export type {
export type { Trace, State } from "./types.js";
export type { LogInterface } from "./utils/LogInterface.js";
export type { LogEntry, LogLevel } from "./consoleLogger.js";
export type { ExplorerItem } from "./router/app.js";
export type { ExplorerItem, MapItem } from "./router/app.js";
export type { WingSimulatorSchema, BaseResourceSchema } from "./wingsdk.js";
export type { Updater, UpdaterStatus } from "./updater.js";
export type { Config } from "./config.js";
export type { Router } from "./router/index.js";
export type { HostUtils } from "./hostUtils.js";
export type { RouterContext } from "./utils/createRouter.js";
export type { RouterMeta } from "./utils/createRouter.js";
export type { MapNode, MapEdge } from "./router/app.js";
export type { MapEdge } from "./router/app.js";
export type { InternalTestResult } from "./router/test.js";
export type { Column } from "./router/table.js";
export type { NodeDisplay } from "./utils/constructTreeNodeMap.js";
Expand Down Expand Up @@ -149,6 +149,13 @@ export const createConsoleServer = async ({
if (onTrace) {
simulator.on("trace", onTrace);
}
simulator.on("resourceLifecycleEvent", async (event) => {
await Promise.all([
invalidateQuery("app.map"),
invalidateQuery("app.explorerTree"),
invalidateQuery("app.nodeMetadata"),
]);
});
compiler.on("compiled", ({ simfile }) => {
if (!isStarting) {
simulator.start(simfile);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import type { ConstructTreeNodeMap } from "../utils/constructTreeNodeMap.js";

type RunningState = "starting" | "started" | "stopping" | "stopped" | "error";

const RunningStateOrder = {
started: 0,
stopped: 1,
starting: 2,
stopping: 3,
error: 4,
} as const;

export const getHierarchichalRunningState = (
path: string,
nodeMap: ConstructTreeNodeMap,
): RunningState => {
const node = nodeMap.get(path);
if (!node) {
return "stopped";
}

const runningState = (node?.resourceConfig?.attrs?.["runningState"] ??
"started") as RunningState;

if (node.children?.length > 0) {
const childrenRunningStates = node.children.map((child) =>
getHierarchichalRunningState(child, nodeMap),
);

// eslint-disable-next-line unicorn/no-array-reduce
const highestRunningState = childrenRunningStates.reduce<RunningState>(
(highest, current) => {
return RunningStateOrder[current] > RunningStateOrder[highest]
? current
: highest;
},
"started",
);

return RunningStateOrder[highestRunningState] >
RunningStateOrder[runningState]
? highestRunningState
: runningState;
}

return runningState;
};
101 changes: 47 additions & 54 deletions apps/wing-console/console/server/src/router/app.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { TRPCError } from "@trpc/server";
import { observable } from "@trpc/server/observable";
import type { UIComponent } from "@winglang/sdk/lib/core/tree.js";
import type { ResourceRunningState } from "@winglang/sdk/lib/simulator/simulator.js";
import uniqby from "lodash.uniqby";
import { z } from "zod";

Expand All @@ -16,6 +18,8 @@ import type { FileLink } from "../utils/createRouter.js";
import { createProcedure, createRouter } from "../utils/createRouter.js";
import type { Simulator } from "../wingsdk.js";

import { getHierarchichalRunningState } from "./app.get-hierarchichal-running-state.js";

const isTest = /(\/test$|\/test:([^/\\])+$)/;
const isTestHandler = /(\/test$|\/test:.*\/Handler$)/;

Expand All @@ -29,6 +33,12 @@ export interface ExplorerItem {
type?: string;
childItems?: ExplorerItem[];
display?: NodeDisplay;
hierarchichalRunningState: ResourceRunningState;
}

export interface MapItem extends ConstructTreeNode {
hierarchichalRunningState: ResourceRunningState;
children?: Record<string, MapItem>;
}

const shakeTree = (tree: ConstructTreeNode): ConstructTreeNode => {
Expand Down Expand Up @@ -159,9 +169,11 @@ export const createAppRouter = () => {
.query(async ({ ctx, input }) => {
const simulator = await ctx.simulator();
const { tree } = simulator.tree().rawData();
const nodeMap = buildConstructTreeNodeMap(shakeTree(tree), simulator);
return createExplorerItemFromConstructTreeNode(
shakeTree(tree),
simulator,
nodeMap,
input?.showTests,
input?.includeHiddens,
);
Expand All @@ -177,9 +189,11 @@ export const createAppRouter = () => {
.query(async ({ ctx, input }) => {
const simulator = await ctx.simulator();
const { tree } = simulator.tree().rawData();
const nodeMap = buildConstructTreeNodeMap(shakeTree(tree), simulator);
const node = createExplorerItemFromConstructTreeNode(
shakeTree(tree),
simulator,
nodeMap,
input?.showTests,
);

Expand All @@ -202,7 +216,7 @@ export const createAppRouter = () => {
.query(async ({ ctx, input }) => {
const simulator = await ctx.simulator();
const { tree } = simulator.tree().rawData();
const nodeMap = buildConstructTreeNodeMap(shakeTree(tree));
const nodeMap = buildConstructTreeNodeMap(shakeTree(tree), simulator);

let breadcrumbs: Array<{
id: string;
Expand Down Expand Up @@ -230,7 +244,7 @@ export const createAppRouter = () => {
.query(async ({ ctx, input }) => {
const simulator = await ctx.simulator();
const { tree } = simulator.tree().rawData();
const nodeMap = buildConstructTreeNodeMap(shakeTree(tree));
const nodeMap = buildConstructTreeNodeMap(shakeTree(tree), simulator);
const node = nodeMap.get(input.path);
if (!node) {
throw new TRPCError({
Expand Down Expand Up @@ -268,7 +282,7 @@ export const createAppRouter = () => {
const simulator = await ctx.simulator();

const { tree } = simulator.tree().rawData();
const nodeMap = buildConstructTreeNodeMap(shakeTree(tree));
const nodeMap = buildConstructTreeNodeMap(shakeTree(tree), simulator);
const node = nodeMap.get(path);
if (!node) {
throw new TRPCError({
Expand Down Expand Up @@ -298,6 +312,10 @@ export const createAppRouter = () => {
type: getResourceType(node, simulator),
props: config?.props,
attributes: config?.attrs,
hierarchichalRunningState: getHierarchichalRunningState(
node.path,
nodeMap,
),
},
inbound: connections
.filter(({ target }) => {
Expand Down Expand Up @@ -354,7 +372,7 @@ export const createAppRouter = () => {
const simulator = await ctx.simulator();

const { tree } = simulator.tree().rawData();
const nodeMap = buildConstructTreeNodeMap(shakeTree(tree));
const nodeMap = buildConstructTreeNodeMap(shakeTree(tree), simulator);

let [, sourcePath, _sourceInflight, , targetPath, targetInflight] =
edgeId.match(/^(.+?)#(.*?)#(.*?)#(.+?)#(.*?)#(.*?)$/i) ?? [];
Expand Down Expand Up @@ -422,9 +440,29 @@ export const createAppRouter = () => {

const { tree } = simulator.tree().rawData();
const connections = simulator.connections();
const nodeMap = buildConstructTreeNodeMap(shakeTree(tree), simulator);

const enrichTreeNode = (node: ConstructTreeNode): MapItem => {
const children: Record<string, MapItem> | undefined = node.children
? {}
: undefined;
if (children) {
for (const [childId, child] of Object.entries(node.children ?? {})) {
children[childId] = enrichTreeNode(child);
}
}
return {
...node,
hierarchichalRunningState: getHierarchichalRunningState(
node.path,
nodeMap,
),
children,
} as MapItem;
};

return {
tree,
tree: enrichTreeNode(tree),
connections,
};
}),
Expand Down Expand Up @@ -470,11 +508,7 @@ export const createAppRouter = () => {
.query(async ({ input, ctx }) => {
const simulator = await ctx.simulator();
const ui = simulator.getResourceUI(input.resourcePath);
return ui as Array<{
kind: string;
label: string;
handler: string | Record<string, string>;
}>;
return ui as Array<UIComponent>;
}),

"app.analytics": createProcedure.query(async ({ ctx }) => {
Expand Down Expand Up @@ -523,6 +557,7 @@ export const createAppRouter = () => {
function createExplorerItemFromConstructTreeNode(
node: ConstructTreeNode,
simulator: Simulator,
nodeMap: ConstructTreeNodeMap,
showTests = false,
includeHiddens = false,
): ExplorerItem {
Expand All @@ -538,6 +573,7 @@ function createExplorerItemFromConstructTreeNode(
label,
type: getResourceType(node, simulator),
display: node.display,
hierarchichalRunningState: getHierarchichalRunningState(node.path, nodeMap),
childItems: node.children
? Object.values(node.children)
.filter((node) => {
Expand All @@ -550,6 +586,7 @@ function createExplorerItemFromConstructTreeNode(
createExplorerItemFromConstructTreeNode(
node,
simulator,
nodeMap,
showTests,
includeHiddens,
),
Expand All @@ -558,50 +595,6 @@ function createExplorerItemFromConstructTreeNode(
};
}

export interface MapNode {
id: string;
data: {
label?: string;
type?: string;
path?: string;
display?: NodeDisplay;
};
children?: MapNode[];
}

function createMapNodeFromConstructTreeNode(
node: ConstructTreeNode,
simulator: Simulator,
showTests = false,
): MapNode {
return {
id: node.path,
data: {
label: node.id,
type: getResourceType(node, simulator),
path: node.path,
display: node.display,
},
children: node.children
? Object.values(node.children)
.filter((node) => {
if (node.display?.hidden) {
return false;
}

if (!showTests && matchTest(node.path)) {
return false;
}

return true;
})
.map((node) =>
createMapNodeFromConstructTreeNode(node, simulator, showTests),
)
: undefined,
};
}

export interface MapEdge {
id: string;
source: string;
Expand Down
1 change: 1 addition & 0 deletions apps/wing-console/console/server/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export type { Trace } from "@winglang/sdk/lib/std/test-runner.js";
export type { ResourceLifecycleEvent } from "@winglang/sdk/lib/simulator/simulator.js";

export type State = "compiling" | "loadingSimulator" | "success" | "error";
12 changes: 10 additions & 2 deletions apps/wing-console/console/server/src/utils/constructTreeNodeMap.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { BaseResourceSchema, Simulator } from "../wingsdk.js";

import type { ConstructInfo, ConstructTreeNode } from "./construct-tree.js";

export interface NodeDisplay {
Expand All @@ -7,6 +9,7 @@ export interface NodeDisplay {
hidden?: boolean;
color?: string;
icon?: string;
expanded?: boolean;
}

export interface NodeConnection {
Expand All @@ -23,6 +26,7 @@ export interface Node {
attributes: Record<string, any> | undefined;
children: string[];
display?: NodeDisplay;
resourceConfig?: BaseResourceSchema;
}

export interface ConstructTreeNodeRecord {
Expand Down Expand Up @@ -51,7 +55,7 @@ function visitChildren(
}
}

function buildNodeMapFromRecord(
export function buildNodeMapFromRecord(
nodeRecord: ConstructTreeNodeRecord,
): ConstructTreeNodeMap {
return {
Expand All @@ -74,7 +78,10 @@ function buildNodeMapFromRecord(
};
}

export function buildConstructTreeNodeMap(node: ConstructTreeNode) {
export function buildConstructTreeNodeMap(
node: ConstructTreeNode,
simulator: Simulator,
) {
let nodeRecord: ConstructTreeNodeRecord = {};

visitChildren(undefined, node, (parent, node) => {
Expand All @@ -88,6 +95,7 @@ export function buildConstructTreeNodeMap(node: ConstructTreeNode) {
attributes: node.attributes,
constructInfo: node.constructInfo,
display: node.display,
resourceConfig: simulator.tryGetResourceConfig(node.path),
};

if (!parent) {
Expand Down
Loading

0 comments on commit 7b3093d

Please sign in to comment.