Init
This commit is contained in:
119
resources/js/Components/SimulationControls.vue
Normal file
119
resources/js/Components/SimulationControls.vue
Normal file
@@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<div class="border border-border/50 rounded-sm overflow-hidden">
|
||||
<button @click="open = !open"
|
||||
class="w-full flex items-center gap-2 px-2 py-1.5 bg-deep/50 hover:bg-deep/80 transition-colors cursor-pointer select-none">
|
||||
<span class="inline-block w-0 h-0 border-l-[3px] border-l-transparent border-r-[3px] border-r-transparent border-t-[4px] border-t-muted transition-transform duration-200"
|
||||
:class="{ '-rotate-90': !open }"></span>
|
||||
<span class="text-[10px] uppercase tracking-wider text-muted">Fault Injection</span>
|
||||
<span v-if="isActive" class="ml-auto w-1.5 h-1.5 rounded-full bg-warn animate-pulse-dot"></span>
|
||||
</button>
|
||||
<div v-show="open" class="px-3 py-2 space-y-2 bg-deep/30">
|
||||
<p class="text-[10px] text-muted/80 leading-relaxed pb-1 border-b border-border/30">
|
||||
Inject faults into activities to test Temporal's retry and error handling.
|
||||
Temporal automatically retries failed activities per the configured retry policy.
|
||||
</p>
|
||||
<!-- Failure Rate -->
|
||||
<div class="space-y-0.5">
|
||||
<div class="flex items-center gap-2">
|
||||
<label class="text-[10px] text-muted w-20 shrink-0">Failure %</label>
|
||||
<input type="range" min="0" max="100" step="5"
|
||||
:value="modelValue.failureRate"
|
||||
@input="update('failureRate', +$event.target.value)"
|
||||
class="flex-1 h-1 accent-danger cursor-pointer">
|
||||
<span class="text-[10px] text-value w-8 text-right">{{ modelValue.failureRate }}%</span>
|
||||
</div>
|
||||
<p class="text-[9px] text-muted/50 pl-[88px]">Chance each activity throws a RuntimeException (retried automatically)</p>
|
||||
</div>
|
||||
|
||||
<!-- Latency -->
|
||||
<div class="space-y-0.5">
|
||||
<div class="flex items-center gap-2">
|
||||
<label class="text-[10px] text-muted w-20 shrink-0">Latency ms</label>
|
||||
<input type="range" min="0" max="2000" step="100"
|
||||
:value="modelValue.latencyMs"
|
||||
@input="update('latencyMs', +$event.target.value)"
|
||||
class="flex-1 h-1 accent-warn cursor-pointer">
|
||||
<span class="text-[10px] text-value w-8 text-right">{{ modelValue.latencyMs }}</span>
|
||||
</div>
|
||||
<p class="text-[9px] text-muted/50 pl-[88px]">Artificial delay added to every activity execution</p>
|
||||
</div>
|
||||
|
||||
<!-- Rate Limiting -->
|
||||
<div class="space-y-0.5">
|
||||
<div class="flex items-center gap-2">
|
||||
<label class="text-[10px] text-muted w-20 shrink-0">Rate limit</label>
|
||||
<button @click="toggleRateLimit"
|
||||
class="px-1.5 py-0.5 text-[9px] uppercase tracking-wider rounded-sm border transition-all cursor-pointer"
|
||||
:class="modelValue.rateLimiting.enabled
|
||||
? 'text-warn border-warn/40 bg-warn/10'
|
||||
: 'text-muted border-border/50'">
|
||||
{{ modelValue.rateLimiting.enabled ? 'ON' : 'OFF' }}
|
||||
</button>
|
||||
</div>
|
||||
<p class="text-[9px] text-muted/50 pl-[88px]">Simulates HTTP 429 responses with nextRetryDelay backoff</p>
|
||||
</div>
|
||||
|
||||
<template v-if="modelValue.rateLimiting.enabled">
|
||||
<div class="flex items-center gap-2 pl-4">
|
||||
<label class="text-[10px] text-muted w-16 shrink-0">Hit %</label>
|
||||
<input type="range" min="0" max="100" step="5"
|
||||
:value="modelValue.rateLimiting.hitChance"
|
||||
@input="updateRL('hitChance', +$event.target.value)"
|
||||
class="flex-1 h-1 accent-warn cursor-pointer">
|
||||
<span class="text-[10px] text-value w-8 text-right">{{ modelValue.rateLimiting.hitChance }}%</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 pl-4">
|
||||
<label class="text-[10px] text-muted w-16 shrink-0">Retry ms</label>
|
||||
<input type="range" min="500" max="5000" step="500"
|
||||
:value="modelValue.rateLimiting.retryAfterMs"
|
||||
@input="updateRL('retryAfterMs', +$event.target.value)"
|
||||
class="flex-1 h-1 accent-warn cursor-pointer">
|
||||
<span class="text-[10px] text-value w-8 text-right">{{ modelValue.rateLimiting.retryAfterMs }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
failureRate: 0,
|
||||
latencyMs: 0,
|
||||
rateLimiting: { enabled: false, hitChance: 25, retryAfterMs: 2000 },
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
const open = ref(false);
|
||||
|
||||
const isActive = computed(() =>
|
||||
props.modelValue.failureRate > 0 ||
|
||||
props.modelValue.latencyMs > 0 ||
|
||||
props.modelValue.rateLimiting.enabled
|
||||
);
|
||||
|
||||
function update(key, value) {
|
||||
emit('update:modelValue', { ...props.modelValue, [key]: value });
|
||||
}
|
||||
|
||||
function toggleRateLimit() {
|
||||
emit('update:modelValue', {
|
||||
...props.modelValue,
|
||||
rateLimiting: { ...props.modelValue.rateLimiting, enabled: !props.modelValue.rateLimiting.enabled },
|
||||
});
|
||||
}
|
||||
|
||||
function updateRL(key, value) {
|
||||
emit('update:modelValue', {
|
||||
...props.modelValue,
|
||||
rateLimiting: { ...props.modelValue.rateLimiting, [key]: value },
|
||||
});
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user