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(sdk): in-place app updates in simulator #5821

Merged
merged 35 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
ce4ca6f
feat(sdk): in-place app updates in simulator [WIP]
eladb Feb 29, 2024
8c4f8e5
add some comments
eladb Feb 29, 2024
e77ea85
Merge branch 'main' into eladb/sim-update
MarkMcCulloh Feb 29, 2024
f460393
chore: self mutation (build.diff)
monadabot Feb 29, 2024
3905962
Update simulator.ts
eladb Feb 29, 2024
43a33df
add execution graph and handle dependencies! nice!
eladb Mar 1, 2024
d424811
Update simulator.test.ts
eladb Mar 1, 2024
7391bb3
chore: self mutation (build.diff)
monadabot Mar 1, 2024
b175b8d
manage deps as sets
eladb Mar 1, 2024
827d0ed
fix error
eladb Mar 1, 2024
64315ec
wip
eladb Mar 1, 2024
5ca51b3
stop mutating the desired state
eladb Mar 2, 2024
d61d550
tweak traces
eladb Mar 2, 2024
1464306
no need to copy state across updates anymore
eladb Mar 2, 2024
3d77452
wip
eladb Mar 5, 2024
ab8cadb
fix linting error
eladb Mar 6, 2024
7c469e9
wip
eladb Mar 6, 2024
c821dfd
wip
eladb Mar 6, 2024
61c2d96
Merge remote-tracking branch 'origin/main' into eladb/sim-update
eladb Mar 6, 2024
357ea4b
wip
eladb Mar 6, 2024
82f2f17
chore: self mutation (e2e-1of2.diff)
monadabot Mar 6, 2024
f58c812
Merge remote-tracking branch 'origin/main' into eladb/sim-update
eladb Mar 7, 2024
e14bfdd
Merge remote-tracking branch 'origin/main' into eladb/sim-update
eladb Mar 11, 2024
f838531
wip
eladb Mar 11, 2024
b8e82a9
wip
eladb Mar 11, 2024
0cc66ec
Merge remote-tracking branch 'origin/main' into eladb/sim-update
eladb Mar 12, 2024
ff385d3
update
eladb Mar 12, 2024
75bf900
add resolve retry loop to support dynamic dependencies like sim.State
eladb Mar 12, 2024
fce33d8
chore: self mutation (e2e-2of2.diff)
monadabot Mar 12, 2024
f37134a
fix api async cleanup
eladb Mar 12, 2024
f8dbfda
update error message
eladb Mar 12, 2024
0e177f8
chore: self mutation (e2e-2of2.diff)
monadabot Mar 12, 2024
4073c05
remove only the api state
eladb Mar 12, 2024
fc86e4d
wip
eladb Mar 12, 2024
b56c97a
skip console function resource test
polamoros Mar 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions libs/wingsdk/src/simulator/graph.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { resolveTokens } from "./tokens";

export interface Definition {
path: string;
deps?: string[];
props?: Record<string, any>;
}

class Node<T extends Definition> {
public readonly dependencies = new Set<string>();
public readonly dependents = new Set<string>();
constructor(public readonly def: T) {}

public get path() {
return this.def.path;
eladb marked this conversation as resolved.
Show resolved Hide resolved
}
}

export class Graph<T extends Definition> {
private byPath: Record<string, Node<T>> = {};

constructor(resources: T[] = []) {
for (const resource of resources) {
this.byPath[resource.path] = new Node(resource);
}

// build the dependency graph
for (const resource of resources) {
const consumer = resource.path;

// add explicit dependencies
for (const dep of resource.deps ?? []) {
this.recordDependency(consumer, dep);
}

// add implicit dependencies (e.g. from tokens in props)
const implicitDeps: string[] = [];

// collect all tokens from the props object (recursive) the "resolver" here is just a dummy
// function that collects all tokens and returns a dummy value (we don't care about the
// result).
resolveTokens(resource.props ?? {}, (token) => {
implicitDeps.push(token.path);
return "[T]"; // <-- we don't really use the result, just need to return something
});

// now add all implicit dependencies
for (const dep of implicitDeps) {
this.recordDependency(consumer, dep);
}
}
}

public get nodes(): Node<T>[] {
return Object.values(this.byPath);
}

public find(path: string): Node<T> {
const node = this.byPath[path];
if (!node) {
throw new Error(`node not found: ${path}`);
}

return node;
}

private recordDependency(consumer: string, producer: string) {
this.find(consumer).dependencies.add(producer);
this.find(producer).dependents.add(consumer);

// check for cyclic dependencies
this.detectCycles(consumer);
this.detectCycles(producer);
}

private detectCycles(root: string) {
const visited = new Set<string>();
const stack = new Set<string>();

const visit = (path: string) => {
if (stack.has(path)) {
throw new Error(
`cyclic dependency detected: ${[...stack, path].join(" -> ")}`
);
}

if (visited.has(path)) {
return;
}

visited.add(path);
stack.add(path);

for (const dep of this.find(path).dependencies) {
visit(dep);
}

stack.delete(path);
};

visit(root);
}
}
Loading
Loading