Files
temporalio-test/resources/js/Components/SimulationControls.vue
2026-05-09 01:18:51 +02:00

120 lines
5.7 KiB
Vue

<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>