Skip to content

Commit 34f0724

Browse files
committed
✨ display message mutators for given message
1 parent 12519b9 commit 34f0724

File tree

5 files changed

+170
-0
lines changed

5 files changed

+170
-0
lines changed

simulator/src/main/java/byzzbench/simulator/controller/SimulatorController.java

+26
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@
33
import byzzbench.simulator.Replica;
44
import byzzbench.simulator.service.SimulatorService;
55
import byzzbench.simulator.transport.Event;
6+
import byzzbench.simulator.transport.MessageEvent;
67
import byzzbench.simulator.transport.MessageMutator;
78
import lombok.RequiredArgsConstructor;
89
import org.springframework.web.bind.annotation.*;
910

1011
import java.io.Serializable;
1112
import java.util.List;
13+
import java.util.Map;
1214
import java.util.Optional;
1315
import java.util.Set;
16+
import java.util.stream.Collectors;
1417

1518
@RestController
1619
@RequiredArgsConstructor
@@ -94,6 +97,29 @@ public Event getMessage(@PathVariable Long eventId) {
9497
return simulatorService.getScenarioExecutor().getTransport().getEvents().get(eventId);
9598
}
9699

100+
@GetMapping("/event/{eventId}/mutators")
101+
public Set<Long> getMessageMutators(@PathVariable Long eventId) {
102+
Event e = simulatorService.getScenarioExecutor().getTransport().getEvents().get(eventId);
103+
104+
// if it is not a message, return an empty set
105+
if (!(e instanceof MessageEvent)) {
106+
return Set.of();
107+
}
108+
109+
Set<Map.Entry<Long, MessageMutator>> messageMutators = simulatorService.getScenarioExecutor().getTransport()
110+
.getMutators().entrySet()
111+
.stream()
112+
// filter mutators that can be applied to the message
113+
.filter(entry -> entry.getValue().getInputClasses().contains(((MessageEvent) e).getPayload().getClass()))
114+
//.map(entry -> entry.getKey())
115+
.collect(Collectors.toSet());
116+
117+
System.out.println("Message Mutators for " + e + ": " + messageMutators);
118+
119+
// return their keys
120+
return messageMutators.stream().map(Map.Entry::getKey).collect(Collectors.toSet());
121+
}
122+
97123
@PostMapping("/event/{eventId}/deliver")
98124
public void deliverMessage(@PathVariable Long eventId) throws Exception {
99125
simulatorService.getScenarioExecutor().getTransport().deliverEvent(eventId);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
"use client";
2+
3+
import { MutateMessageMenuEntry } from "@/components/messages/MutateMessageMenu/MutateMessageMenuEntry";
4+
import {
5+
useDropMessage,
6+
useGetMessageMutators,
7+
} from "@/lib/byzzbench-client/generated";
8+
import { ActionIcon, Burger, Menu, rem } from "@mantine/core";
9+
import { showNotification } from "@mantine/notifications";
10+
import { IconSend, IconTrash } from "@tabler/icons-react";
11+
import { useQueryClient } from "@tanstack/react-query";
12+
import React from "react";
13+
14+
type MutateMessageMenuProps = {
15+
messageId: number;
16+
};
17+
18+
export const MutateMessageMenu = ({ messageId }: MutateMessageMenuProps) => {
19+
const queryClient = useQueryClient();
20+
const { data } = useGetMessageMutators(messageId);
21+
const { mutate: dropMessage } = useDropMessage(messageId);
22+
23+
return (
24+
<Menu>
25+
<Menu.Target>
26+
<Burger />
27+
</Menu.Target>
28+
<Menu.Dropdown>
29+
<Menu.Label>Mutate and Deliver</Menu.Label>
30+
{data?.data.map((mutator) => (
31+
<MutateMessageMenuEntry key={mutator} mutatorId={mutator} />
32+
))}
33+
34+
<Menu.Divider />
35+
36+
<Menu.Label>Danger zone</Menu.Label>
37+
<Menu.Item
38+
color="red"
39+
leftSection={
40+
<IconTrash style={{ width: rem(14), height: rem(14) }} />
41+
}
42+
onClick={(e) => {
43+
e.preventDefault();
44+
dropMessage(null as never, {
45+
onSuccess: () => {
46+
showNotification({
47+
message: `Message ${messageId} dropped`,
48+
});
49+
},
50+
onError: () => {
51+
showNotification({
52+
message: "Failed to drop message",
53+
color: "red",
54+
});
55+
},
56+
onSettled: async () => {
57+
await queryClient.invalidateQueries();
58+
},
59+
});
60+
}}
61+
>
62+
Drop message
63+
</Menu.Item>
64+
</Menu.Dropdown>
65+
</Menu>
66+
);
67+
68+
return (
69+
<ActionIcon
70+
onClick={(e) => {
71+
e.preventDefault();
72+
const mutate = (a: any, b: any) => {};
73+
mutate(null as never, {
74+
onSuccess: () => {
75+
showNotification({
76+
message: `Message ${messageId} delivered`,
77+
});
78+
},
79+
onError: () => {
80+
showNotification({
81+
message: "Failed to deliver message",
82+
color: "red",
83+
});
84+
},
85+
onSettled: async () => {
86+
await queryClient.invalidateQueries();
87+
},
88+
});
89+
}}
90+
>
91+
<IconSend />
92+
</ActionIcon>
93+
);
94+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
"use client";
2+
3+
import { useGetMutator } from "@/lib/byzzbench-client/generated";
4+
import { Menu, rem } from "@mantine/core";
5+
import { IconBug } from "@tabler/icons-react";
6+
import { useQueryClient } from "@tanstack/react-query";
7+
import React from "react";
8+
9+
type MutateMessageMenuEntryProps = {
10+
mutatorId: number;
11+
};
12+
13+
export const MutateMessageMenuEntry = ({
14+
mutatorId,
15+
}: MutateMessageMenuEntryProps) => {
16+
const queryClient = useQueryClient();
17+
const { data } = useGetMutator(mutatorId);
18+
19+
return (
20+
<Menu.Item
21+
leftSection={<IconBug style={{ width: rem(14), height: rem(14) }} />}
22+
key={data?.data.name}
23+
/*
24+
onClick={() => {
25+
mutator.mutate(null as never, {
26+
onSuccess: () => {
27+
showNotification({
28+
message: `Message ${messageId} mutated`,
29+
});
30+
},
31+
onError: () => {
32+
showNotification({
33+
message: "Failed to mutate message",
34+
color: "red",
35+
});
36+
},
37+
onSettled: async () => {
38+
await queryClient.invalidateQueries();
39+
},
40+
});
41+
}}*/
42+
>
43+
{data?.data.name}
44+
</Menu.Item>
45+
);
46+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from "./MutateMessageMenu";
2+
export * from "./MutateMessageMenuEntry";

webui/components/messages/NodeMailbox/NodeMailboxEntry.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
DeliverMessageActionIcon,
33
DropMessageActionIcon,
44
} from "@/components/messages";
5+
import { MutateMessageMenu } from "@/components/messages/MutateMessageMenu";
56
import { NodeStateNavLink } from "@/components/NodeStateNavLink";
67
import { useGetMessage } from "@/lib/byzzbench-client/generated";
78
import { Badge, Collapse, Container, Group, Text } from "@mantine/core";
@@ -54,6 +55,7 @@ export const NodeMailboxEntry = ({ messageId }: { messageId: number }) => {
5455
<Group gap="xs" wrap="nowrap">
5556
<DeliverMessageActionIcon messageId={messageId} />
5657
<DropMessageActionIcon messageId={messageId} />
58+
<MutateMessageMenu messageId={messageId} />
5759
</Group>
5860
)}
5961
</Group>

0 commit comments

Comments
 (0)