Skip to content

Commit eeb0d72

Browse files
committed
feat(simulator): add bus logs
1 parent 51811b1 commit eeb0d72

File tree

4 files changed

+174
-33
lines changed

4 files changed

+174
-33
lines changed

simulator/inertia/app/app.ts

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
/// <reference path="../../adonisrc.ts" />
22
/// <reference path="../../config/inertia.ts" />
33

4-
import '@unocss/reset/tailwind-compat.css'
54
import 'virtual:uno.css'
65
import 'primeicons/primeicons.css'
76

simulator/inertia/pages/home.vue

+122-31
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,32 @@
11
<script setup lang="ts">
22
import { Head, router, usePoll } from '@inertiajs/vue3'
3+
import Badge from 'primevue/badge'
34
import Button from 'primevue/button'
45
import Card from 'primevue/card'
6+
import ScrollPanel from 'primevue/scrollpanel'
7+
import ToggleSwitch from 'primevue/toggleswitch'
58
69
defineProps<{
710
correctValue: number
8-
caches: Array<{ name: string; result: any }>
11+
caches: Array<{ name: string; result: any; busId: string }>
912
state: { bus: boolean; l2: boolean }
13+
sentMessages: Array<any>
14+
receivedMessages: Array<any>
1015
}>()
1116
1217
usePoll(1500, { async: true })
1318
1419
function setCacheValue(name: string, value: any) {
15-
router.post('/set', { name, value })
20+
router.post('/set', { name, value }, { preserveScroll: true })
21+
}
22+
23+
function deleteCacheValue(name: string) {
24+
router.post('/delete', { name }, { preserveScroll: true })
25+
}
26+
27+
const severities = ['secondary', 'success', 'info', 'warn', 'danger', 'contrast']
28+
function getCacheColor(name: string) {
29+
return severities[(name.at(-1) as any) % severities.length]
1630
}
1731
</script>
1832

@@ -25,27 +39,44 @@ function setCacheValue(name: string, value: any) {
2539
<template #subtitle>Cache Coherence Simulator</template>
2640

2741
<template #content>
28-
<p class="mt-4 text-sm">
29-
Correct Value :
30-
{{ correctValue }}
31-
</p>
32-
33-
<div class="flex gap-4 mt-4">
34-
<Button
35-
size="small"
36-
@click="router.post('/state', { bus: !state.bus })"
37-
:severity="state.bus ? 'danger' : 'success'"
38-
>
39-
{{ state.bus ? 'Disable' : 'Enable' }} Bus
40-
</Button>
41-
42-
<Button
43-
size="small"
44-
@click="router.post('/state', { l2: !state.l2 })"
45-
:severity="state.l2 ? 'danger' : 'success'"
46-
>
47-
{{ state.l2 ? 'Disable' : 'Enable' }} L2
48-
</Button>
42+
<div class="grid grid-cols-[200px_200px] items-center gap-4 mt-4">
43+
<span>Correct Value :</span>
44+
<span class="font-semibold text-2xl">
45+
{{ correctValue }}
46+
</span>
47+
<div class="flex items-center gap-2">
48+
<span>
49+
<i
50+
class="pi"
51+
:class="{
52+
'text-green-500 pi-check-circle': state.bus,
53+
'text-red-500 pi-times-circle': !state.bus,
54+
}"
55+
/>
56+
</span>
57+
<span>Bus is {{ state.bus ? 'enabled' : 'disabled' }}</span>
58+
</div>
59+
<ToggleSwitch
60+
v-model="state.bus"
61+
@change="router.post('/state', { bus: state.bus }, { preserveScroll: true })"
62+
/>
63+
64+
<div class="flex items-center gap-2">
65+
<span>
66+
<i
67+
class="pi"
68+
:class="{
69+
'text-green-500 pi-check-circle': state.l2,
70+
'text-red-500 pi-times-circle': !state.l2,
71+
}"
72+
/>
73+
</span>
74+
<span>L2 is {{ state.l2 ? 'enabled' : 'disabled' }}</span>
75+
</div>
76+
<ToggleSwitch
77+
v-model="state.l2"
78+
@change="router.post('/state', { l2: state.l2 }, { preserveScroll: true })"
79+
/>
4980
</div>
5081
</template>
5182
</Card>
@@ -55,24 +86,84 @@ function setCacheValue(name: string, value: any) {
5586
<template #title>
5687
<div class="flex gap-4 items-center justify-between font-light">
5788
<span>Node {{ cache.name }}</span>
58-
<Button
59-
size="small"
60-
variant="outlined"
61-
severity="info"
62-
icon="pi pi-plus"
63-
@click="setCacheValue(cache.name, cache.result + 1)"
64-
/>
89+
<div class="flex gap-2">
90+
<Button
91+
size="small"
92+
variant="outlined"
93+
severity="info"
94+
icon="pi pi-plus"
95+
@click="setCacheValue(cache.name, cache.result + 1)"
96+
/>
97+
<Button
98+
size="small"
99+
variant="outlined"
100+
severity="danger"
101+
icon="pi pi-trash"
102+
@click="deleteCacheValue(cache.name)"
103+
/>
104+
</div>
65105
</div>
66106
</template>
67107
<template #content>
68108
<div>
69109
Current Value :
70110
<span class="text-lg font-semibold">{{ cache.result }}</span>
71111
</div>
72-
73112
<div class="flex gap-2 mt-2"></div>
74113
</template>
75114
</Card>
76115
</div>
116+
117+
<Card class="mt-4">
118+
<template #title>Bus logs</template>
119+
120+
<template #content>
121+
<div class="grid grid-cols-2 gap-2">
122+
<div>
123+
<p>Sent messages</p>
124+
<ScrollPanel style="width: 100%; height: 300px">
125+
<div class="p-2 grid gap-2">
126+
<div v-for="(log, idx) in sentMessages" :key="idx" class="flex items-center gap-2">
127+
<Badge size="small" :severity="getCacheColor(log.cacheName)">
128+
{{ log.cacheName }}
129+
</Badge>
130+
131+
<Badge size="small" :severity="log.message.type === 'set' ? 'info' : 'danger'">
132+
{{ log.message.type }}
133+
</Badge>
134+
135+
<span>{{ new Date(log.timestamp).toLocaleTimeString() }}</span>
136+
<span class="text-xs text-[var(--p-slate-300)]">{{ log.message }}</span>
137+
</div>
138+
</div>
139+
</ScrollPanel>
140+
</div>
141+
142+
<div>
143+
<p>Received messages</p>
144+
<ScrollPanel style="width: 100%; height: 300px">
145+
<div class="p-2 grid gap-2">
146+
<div
147+
v-for="(log, idx) in receivedMessages"
148+
:key="idx"
149+
class="flex items-center gap-2"
150+
>
151+
<Badge size="small" :severity="getCacheColor(log.cacheName)">
152+
{{ log.cacheName }}
153+
</Badge>
154+
155+
<Badge size="small" :severity="log.message.type === 'set' ? 'info' : 'danger'">
156+
{{ log.message.type }}
157+
</Badge>
158+
159+
<span>{{ new Date(log.timestamp).toLocaleTimeString() }}</span>
160+
<span class="text-xs text-[var(--p-slate-300)]">{{ log.message }}</span>
161+
</div>
162+
</div>
163+
</ScrollPanel>
164+
</div>
165+
</div>
166+
</template>
167+
</Card>
77168
</div>
78169
</template>

simulator/start/chaos/chaos_bus.ts

+25-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@ import type { Serializable, SubscribeHandler, Transport } from '@boringnode/bus/
22

33
import { ChaosInjector } from './chaos_injector.js'
44

5+
interface BusMessage {
6+
channel: string
7+
message: Serializable
8+
busId: string
9+
timestamp: number
10+
}
11+
512
export class ChaosBus implements Transport {
613
/**
714
* The inner transport driver that is wrapped
@@ -14,6 +21,9 @@ export class ChaosBus implements Transport {
1421
#chaosInjector: ChaosInjector
1522
id!: string
1623

24+
sentMessages: Array<BusMessage> = []
25+
receivedMessages: Array<BusMessage> = []
26+
1727
constructor(innerTransport: Transport) {
1828
this.#innerTransport = innerTransport
1929
this.#chaosInjector = new ChaosInjector()
@@ -48,11 +58,25 @@ export class ChaosBus implements Transport {
4858

4959
async publish(channel: string, message: Serializable) {
5060
await this.#chaosInjector.injectChaos()
61+
this.sentMessages.push({
62+
channel,
63+
message,
64+
busId: this.id,
65+
timestamp: Date.now(),
66+
})
5167
return this.#innerTransport.publish(channel, message)
5268
}
5369

5470
async subscribe<T extends Serializable>(channel: string, handler: SubscribeHandler<T>) {
55-
return this.#innerTransport.subscribe(channel, handler)
71+
return this.#innerTransport.subscribe(channel, (message) => {
72+
this.receivedMessages.push({
73+
channel,
74+
message,
75+
busId: this.id,
76+
timestamp: Date.now(),
77+
})
78+
return handler(message as any)
79+
})
5680
}
5781

5882
unsubscribe(channel: string) {

simulator/start/routes.ts

+27
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,20 @@ router.get('/', async ({ inertia }) => {
7171
correctValue: await trueCache.get({ key: 'value', defaultValue: 0 }),
7272
caches: await Promise.all(results),
7373
state,
74+
sentMessages: [...nodes.entries()]
75+
.map(([key, cache]) =>
76+
cache.bus.sentMessages.map((message) => ({ ...message, cacheName: key })),
77+
)
78+
.flat()
79+
.sort((a, b) => b.timestamp - a.timestamp)
80+
.slice(0, 40),
81+
receivedMessages: [...nodes.entries()]
82+
.map(([key, cache]) =>
83+
cache.bus.receivedMessages.map((message) => ({ ...message, cacheName: key })),
84+
)
85+
.flat()
86+
.sort((a, b) => b.timestamp - a.timestamp)
87+
.slice(0, 40),
7488
})
7589
})
7690

@@ -88,6 +102,19 @@ router.post('/set', async ({ request, response }) => {
88102
return response.redirect().toPath('/')
89103
})
90104

105+
router.post('/delete', async ({ request, response }) => {
106+
const cacheName = request.input('name')
107+
108+
if (!nodes.has(cacheName)) {
109+
return response.status(400).send('Invalid cache name')
110+
}
111+
112+
const cache = nodes.get(cacheName)
113+
await cache?.bento.delete({ key: 'value' })
114+
115+
return response.redirect().toPath('/')
116+
})
117+
91118
const stateSchema = vine.compile(
92119
vine.object({
93120
bus: vine.boolean().optional(),

0 commit comments

Comments
 (0)