279 lines
8.1 KiB
Vue
279 lines
8.1 KiB
Vue
<template>
|
|
<div>
|
|
<LayoutsBreadcrumb />
|
|
|
|
<!-- Header Section -->
|
|
<rs-card class="mb-6">
|
|
<template #header>
|
|
<div class="flex items-center">
|
|
<Icon class="mr-2 text-primary" name="ic:outline-schedule"></Icon>
|
|
<h1 class="text-xl font-bold text-primary">Queue & Scheduler</h1>
|
|
</div>
|
|
</template>
|
|
<template #body>
|
|
<p class="text-gray-600">
|
|
Controls how messages and background tasks are managed — crucial for
|
|
reliability, scalability, and timing precision in any notification or
|
|
event-driven system.
|
|
</p>
|
|
</template>
|
|
</rs-card>
|
|
|
|
<!-- Quick Stats -->
|
|
<div class="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-4 gap-6 mb-6">
|
|
<rs-card
|
|
v-for="(stat, index) in quickStats"
|
|
:key="index"
|
|
class="transition-all duration-300 hover:shadow-lg"
|
|
>
|
|
<div class="pt-5 pb-3 px-5 flex items-center gap-4">
|
|
<div
|
|
class="p-5 flex justify-center items-center bg-primary/20 rounded-2xl transition-all duration-300 hover:bg-primary/30"
|
|
>
|
|
<Icon class="text-primary text-3xl" :name="stat.icon"></Icon>
|
|
</div>
|
|
<div class="flex-1 truncate">
|
|
<span class="block font-bold text-2xl leading-tight text-primary">
|
|
{{ stat.value }}
|
|
</span>
|
|
<span class="text-sm font-medium text-gray-600">
|
|
{{ stat.title }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</rs-card>
|
|
</div>
|
|
|
|
<!-- Feature Cards -->
|
|
<div class="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-6">
|
|
<rs-card
|
|
v-for="(feature, index) in features"
|
|
:key="index"
|
|
class="transition-all duration-300 hover:shadow-lg cursor-pointer"
|
|
@click="navigateTo(feature.path)"
|
|
>
|
|
<template #header>
|
|
<div class="flex items-center">
|
|
<Icon class="mr-2 text-primary" :name="feature.icon"></Icon>
|
|
<h3 class="text-lg font-semibold text-primary">{{ feature.title }}</h3>
|
|
</div>
|
|
</template>
|
|
<template #body>
|
|
<p class="text-gray-600 mb-4">{{ feature.description }}</p>
|
|
<div class="space-y-2">
|
|
<div
|
|
v-for="(useCase, idx) in feature.useCases"
|
|
:key="idx"
|
|
class="flex items-start"
|
|
>
|
|
<Icon
|
|
class="mr-2 mt-1 text-green-500 text-sm"
|
|
name="ic:outline-check-circle"
|
|
></Icon>
|
|
<span class="text-sm text-gray-700">{{ useCase }}</span>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<template #footer>
|
|
<div class="flex justify-end">
|
|
<rs-button variant="outline" size="sm">
|
|
<Icon class="mr-1" name="ic:outline-arrow-forward"></Icon>
|
|
Open
|
|
</rs-button>
|
|
</div>
|
|
</template>
|
|
</rs-card>
|
|
</div>
|
|
|
|
<!-- Recent Activity -->
|
|
<rs-card class="mt-6">
|
|
<template #header>
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex items-center">
|
|
<Icon class="mr-2 text-primary" name="ic:outline-history"></Icon>
|
|
<h3 class="text-lg font-semibold text-primary">Recent Queue Activity</h3>
|
|
</div>
|
|
<rs-button
|
|
variant="outline"
|
|
size="sm"
|
|
@click="navigateTo('/notification/queue-scheduler/monitor')"
|
|
>
|
|
View All
|
|
</rs-button>
|
|
</div>
|
|
</template>
|
|
<template #body>
|
|
<div class="space-y-3">
|
|
<div
|
|
v-for="(activity, index) in recentActivity"
|
|
:key="index"
|
|
class="flex items-center justify-between p-3 bg-gray-50 rounded-lg"
|
|
>
|
|
<div class="flex items-center">
|
|
<div
|
|
class="w-3 h-3 rounded-full mr-3"
|
|
:class="{
|
|
'bg-green-500': activity.status === 'completed',
|
|
'bg-yellow-500': activity.status === 'processing',
|
|
'bg-red-500': activity.status === 'failed',
|
|
'bg-blue-500': activity.status === 'pending',
|
|
}"
|
|
></div>
|
|
<div>
|
|
<p class="font-medium">{{ activity.job }}</p>
|
|
<p class="text-sm text-gray-600">{{ activity.description }}</p>
|
|
</div>
|
|
</div>
|
|
<div class="text-right">
|
|
<p class="text-sm font-medium capitalize">{{ activity.status }}</p>
|
|
<p class="text-xs text-gray-500">{{ activity.time }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</rs-card>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
definePageMeta({
|
|
title: "Queue & Scheduler",
|
|
middleware: ["auth"],
|
|
requiresAuth: true,
|
|
breadcrumb: [
|
|
{
|
|
name: "Notification",
|
|
path: "/notification",
|
|
},
|
|
{
|
|
name: "Queue & Scheduler",
|
|
path: "/notification/queue-scheduler",
|
|
},
|
|
],
|
|
});
|
|
|
|
// Quick stats data
|
|
const quickStats = ref([
|
|
{
|
|
title: "Active Jobs",
|
|
value: "1,247",
|
|
icon: "ic:outline-work",
|
|
},
|
|
{
|
|
title: "Completed Today",
|
|
value: "8,932",
|
|
icon: "ic:outline-check-circle",
|
|
},
|
|
{
|
|
title: "Failed Jobs",
|
|
value: "23",
|
|
icon: "ic:outline-error",
|
|
},
|
|
{
|
|
title: "Avg Processing Time",
|
|
value: "2.3s",
|
|
icon: "ic:outline-timer",
|
|
},
|
|
]);
|
|
|
|
// Feature cards data
|
|
const features = ref([
|
|
{
|
|
title: "Queue Monitor",
|
|
description:
|
|
"Displays a live overview of all queued jobs — what's currently pending, processing, succeeded, or failed.",
|
|
icon: "ic:outline-monitor",
|
|
path: "/notification/queue-scheduler/monitor",
|
|
useCases: [
|
|
"Monitor load spikes and backlogs in real-time",
|
|
"Track job status with auto-refresh",
|
|
"Filter by job type, channel, and status",
|
|
],
|
|
},
|
|
{
|
|
title: "Batch Processing",
|
|
description:
|
|
"Schedule or trigger the processing of large groups of messages in one go.",
|
|
icon: "ic:outline-batch-prediction",
|
|
path: "/notification/queue-scheduler/batch",
|
|
useCases: [
|
|
"Send newsletters and campaigns",
|
|
"Process messages in chunks (500 per batch)",
|
|
"Schedule batches for optimal timing",
|
|
],
|
|
},
|
|
{
|
|
title: "Retry & Dead Letter",
|
|
description:
|
|
"Handles failed jobs with retry logic and dead letter queue for permanent failures.",
|
|
icon: "ic:outline-refresh",
|
|
path: "/notification/queue-scheduler/retry",
|
|
useCases: [
|
|
"Auto/manual retry of failed messages",
|
|
"Store permanently failed messages",
|
|
"Debug with detailed error reasons",
|
|
],
|
|
},
|
|
{
|
|
title: "Timezone Handling",
|
|
description:
|
|
"Ensures messages are delivered at the right local time for each recipient.",
|
|
icon: "ic:outline-schedule",
|
|
path: "/notification/queue-scheduler/timezone",
|
|
useCases: [
|
|
"Schedule birthday messages at 9AM local time",
|
|
"Avoid 2AM push alerts across timezones",
|
|
"UTC + offset logic for global delivery",
|
|
],
|
|
},
|
|
{
|
|
title: "Rate Limiting",
|
|
description:
|
|
"Throttles how many messages/jobs can be processed per second/minute/hour.",
|
|
icon: "ic:outline-speed",
|
|
path: "/notification/queue-scheduler/rate-limit",
|
|
useCases: [
|
|
"Avoid hitting API limits (Twilio, SendGrid)",
|
|
"Prevent spammy behavior and blacklisting",
|
|
"Global and per-channel rate controls",
|
|
],
|
|
},
|
|
]);
|
|
|
|
// Recent activity data
|
|
const recentActivity = ref([
|
|
{
|
|
job: "Email Campaign #1247",
|
|
description: "Newsletter to 50,000 subscribers",
|
|
status: "completed",
|
|
time: "2 minutes ago",
|
|
},
|
|
{
|
|
job: "SMS Batch #892",
|
|
description: "OTP messages to 1,200 users",
|
|
status: "processing",
|
|
time: "5 minutes ago",
|
|
},
|
|
{
|
|
job: "Push Notification #445",
|
|
description: "App update notification",
|
|
status: "failed",
|
|
time: "8 minutes ago",
|
|
},
|
|
{
|
|
job: "Webhook Delivery #223",
|
|
description: "Order confirmation webhooks",
|
|
status: "pending",
|
|
time: "12 minutes ago",
|
|
},
|
|
{
|
|
job: "Birthday Reminders",
|
|
description: "Daily birthday notifications",
|
|
status: "completed",
|
|
time: "1 hour ago",
|
|
},
|
|
]);
|
|
</script>
|
|
|
|
<style lang="scss" scoped></style>
|