diff --git a/src/app/api/queue/route.ts b/src/app/api/queue/route.ts
new file mode 100644
index 0000000..3e47b48
--- /dev/null
+++ b/src/app/api/queue/route.ts
@@ -0,0 +1,29 @@
+import InsertQueue from "@/service/insert-queue";
+import { NextRequest, NextResponse } from "next/server";
+
+export async function GET(request: NextRequest) {
+ const insertQueue = InsertQueue.getInstance();
+ const processing = insertQueue.processingItem;
+ const processingTime = insertQueue.processingTime;
+ const queue = insertQueue.queue;
+ if (processing || queue.length > 0) {
+ return NextResponse.json({
+ status: 200,
+ body: {
+ processing,
+ queue,
+ processingTime,
+ },
+ });
+ }
+ if (processing || queue.length == 0) {
+ return NextResponse.json({
+ status: 200,
+ body: {
+ processing,
+ processingTime,
+ },
+ });
+ }
+ return NextResponse.json({ error: "No repositories found" }, { status: 404 });
+}
diff --git a/src/app/get/queue/ProcessingItem.tsx b/src/app/get/queue/ProcessingItem.tsx
new file mode 100644
index 0000000..d8b000e
--- /dev/null
+++ b/src/app/get/queue/ProcessingItem.tsx
@@ -0,0 +1,61 @@
+'use client';
+
+import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
+import React, { useState, useEffect } from "react";
+
+interface ProcessingItemProps {
+ owner: string;
+ repo: string;
+ createdAt: string;
+}
+
+export default function ProcessingItem({
+ owner,
+ repo,
+ createdAt,
+}: ProcessingItemProps) {
+ const [elapsedTime, setElapsedTime] = useState(
+ calculateElapsedTime(createdAt),
+ );
+
+ useEffect(() => {
+ const interval = setInterval(() => {
+ setElapsedTime(calculateElapsedTime(createdAt));
+ }, 1000);
+
+ return () => clearInterval(interval);
+ }, [createdAt]);
+
+ return (
+
+
+
+
+ {owner}/{repo}
+
+
+
+
+ Processing this item for: {elapsedTime}
+
+
+
+
+ );
+}
+
+function calculateElapsedTime(createdAt: string): string {
+ const now = Date.now();
+ const createdTime = new Date(createdAt).getTime();
+ const elapsedTime = now - createdTime;
+
+ const seconds = Math.floor(elapsedTime / 1000);
+ const minutes = Math.floor(seconds / 60);
+ const hours = Math.floor(minutes / 60);
+ const days = Math.floor(hours / 24);
+
+ if (days > 0) return `${days} days`;
+ if (hours > 0) return `${hours} hours`;
+ if (minutes > 0) return `${minutes} minutes`;
+ return `${seconds} seconds`;
+}
diff --git a/src/app/get/queue/page.tsx b/src/app/get/queue/page.tsx
new file mode 100644
index 0000000..bd9d196
--- /dev/null
+++ b/src/app/get/queue/page.tsx
@@ -0,0 +1,93 @@
+'use client';
+
+import { useEffect, useState } from "react";
+import { Card, CardContent, CardHeader } from "@/components/ui/card";
+import { Skeleton } from "@/components/ui/skeleton";
+import { AlertCircle } from 'lucide-react';
+import ProcessingItem from "./ProcessingItem";
+import React from "react";
+
+export default function Page() {
+ const [queue, setQueue] = useState([]);
+ const [processing, setProcessing] = useState(null);
+ const [processingTime, setProcessingTime] = useState("");
+ const [isLoading, setIsLoading] = useState(true);
+
+ useEffect(() => {
+ const fetchData = async () => {
+ setIsLoading(true);
+ const response = await fetch("/api/queue");
+ if (response.ok) {
+ const { body } = await response.json();
+ setQueue(body.queue || []);
+ setProcessing(body.processing || null);
+ setProcessingTime(body.processingTime || "");
+ }
+ setIsLoading(false);
+ };
+ fetchData();
+ }, []);
+
+ if (isLoading) {
+ return ;
+ }
+
+ return (
+
+
Currently Processing
+ {processing ? (
+
+ ) : (
+
+
+ No repository currently being processed
+
+ )}
+
+
Queue
+ {queue.length > 0 ? (
+
+ {queue.map((item, index) => (
+ -
+
+ {item.owner}/{item.repo}
+
+
+ ))}
+
+ ) : (
+
+
+ No repositories in the queue
+
+ )}
+
+ );
+}
+
+function LoadingSkeleton() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
diff --git a/src/components/NavBar.tsx b/src/components/NavBar.tsx
index 7abe376..9d861a4 100644
--- a/src/components/NavBar.tsx
+++ b/src/components/NavBar.tsx
@@ -80,6 +80,15 @@ export default function Navbar() {
+
+
+
+ Queue
+
+
+
@@ -128,6 +137,11 @@ export default function Navbar() {
Add Repo
+
+
+ Queue
+
+
diff --git a/src/service/insert-queue.ts b/src/service/insert-queue.ts
index 1d092ab..c297a26 100644
--- a/src/service/insert-queue.ts
+++ b/src/service/insert-queue.ts
@@ -22,9 +22,10 @@ export default class InsertQueue {
private _isProcessing: boolean = false
private _repoService: InsertRepoService
private _processingItem: InsertItem | null = null
+ private _processingTime: string | null = null
private static _instance?: InsertQueue
private _rateLimitBeforeStop: number = 500
- private _maxQueueSize: number = 10
+ private _maxQueueSize: number = 25
private _repository: Repository
private constructor() {
@@ -45,6 +46,10 @@ export default class InsertQueue {
return this._instance;
}
+ get queue(): InsertItem[] {
+ return this._queue;
+ }
+
/**
* Adds a new item to the queue
*/
@@ -102,6 +107,13 @@ export default class InsertQueue {
return this._processingItem
}
+ /**
+ * Returns the current processing time in UTC timezone
+ */
+ get processingTime(): string | null {
+ return this._processingTime
+ }
+
/**
* Processes the queue, if rate limit is not reached
* if rate limit is reached, it will wait for the reset time
@@ -132,6 +144,7 @@ export default class InsertQueue {
item: InsertItem
): Promise {
console.log(`Processing item: ${item.owner}/${item.repo}`)
+ this._processingTime = new Date().toISOString()
this._processingItem = item
let result: RepositoryData | null = null
try {
@@ -145,6 +158,7 @@ export default class InsertQueue {
}
this._processingItem = null
+ this._processingTime = null
return result
}
}