View management
This commit is contained in:
@@ -2,6 +2,7 @@ import { WebSocketServer, WebSocket } from "ws";
|
||||
import Redis from "ioredis";
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { LiveRunEvent } from "@/modules/live-run/types";
|
||||
import { getLiveRun, updateLiveRunViews } from "@/modules/live-run/core";
|
||||
|
||||
export function GET(req: NextRequest) {
|
||||
const headers = new Headers();
|
||||
@@ -16,6 +17,9 @@ export function UPGRADE(client: WebSocket, server: WebSocketServer) {
|
||||
|
||||
client.once("message", async (message) => {
|
||||
runId = message.toString();
|
||||
|
||||
await updateLiveRunViews(runId, 1);
|
||||
|
||||
let lastEvent: LiveRunEvent | null = null;
|
||||
|
||||
const sendText = async () => {
|
||||
@@ -57,6 +61,7 @@ export function UPGRADE(client: WebSocket, server: WebSocketServer) {
|
||||
client.once("close", async () => {
|
||||
if (runId) await subscriber.unsubscribe(`liveRun:${runId}`);
|
||||
subscriber.quit();
|
||||
await updateLiveRunViews(runId, -1);
|
||||
});
|
||||
|
||||
client.on("error", (err) => {
|
||||
|
||||
@@ -4,7 +4,13 @@ import { LiveRun } from "@/modules/live-run/types";
|
||||
import { Eye } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export default function RunTimer({ run }: { run: LiveRun }) {
|
||||
export default function RunTimer({
|
||||
run,
|
||||
views,
|
||||
}: {
|
||||
run: LiveRun;
|
||||
views: number | null;
|
||||
}) {
|
||||
const [time, setTime] = useState("00:00:00");
|
||||
|
||||
useEffect(() => {
|
||||
@@ -29,7 +35,7 @@ export default function RunTimer({ run }: { run: LiveRun }) {
|
||||
</p>
|
||||
<p className="text-muted-foreground flex gap-1 items-center">
|
||||
<Eye className="w-4 h-4" />
|
||||
{run.views}
|
||||
{views || run.views}
|
||||
</p>
|
||||
</span>
|
||||
</CardContent>
|
||||
|
||||
@@ -7,7 +7,7 @@ import { FileTree } from "./components/FileTree";
|
||||
import { File } from "lucide-react";
|
||||
import Editor from "./components/Editor";
|
||||
import useAction, { useActionInterval } from "@/hook/use-action";
|
||||
import { getLiveRun } from "@/modules/live-run/actions";
|
||||
import { getLiveRun, getLiveRunViews } from "@/modules/live-run/actions";
|
||||
import ProblemCard from "@/app/problems/components/ProblemCard";
|
||||
import ProfileCard from "./components/ProfileCard";
|
||||
import { getProblem } from "@/modules/problems/actions";
|
||||
@@ -18,6 +18,9 @@ export default function Run() {
|
||||
const params = useParams<{ runId: string }>();
|
||||
|
||||
const [run] = useAction(() => getLiveRun(params.runId), [params]);
|
||||
const [views] = useActionInterval(() => getLiveRunViews(params.runId), 2500, [
|
||||
params,
|
||||
]);
|
||||
|
||||
const [problem] = useAction(
|
||||
async () => (run?.id ? getProblem(run.problem) : null),
|
||||
@@ -55,7 +58,7 @@ export default function Run() {
|
||||
</div>
|
||||
|
||||
<div className="flex-1 animate-fade-in opacity-0 stagger-2">
|
||||
{run && <RunTimer run={run} />}
|
||||
{run && <RunTimer run={run} views={views} />}
|
||||
</div>
|
||||
|
||||
<div className="flex-2">
|
||||
|
||||
@@ -10,3 +10,7 @@ export async function getLiveRuns(): Promise<LiveRun[]> {
|
||||
export async function getLiveRun(id: string): Promise<LiveRun | null> {
|
||||
return Core.getLiveRun(id);
|
||||
}
|
||||
|
||||
export async function getLiveRunViews(id: string): Promise<number | null> {
|
||||
return Core.getLiveRunViews(id);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,29 @@ export async function getLiveRun(id: string): Promise<LiveRun | null> {
|
||||
return JSON.parse(data) as LiveRun;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get live run views from Redis
|
||||
*/
|
||||
export async function getLiveRunViews(id: string): Promise<number | null> {
|
||||
const run = await getLiveRun(id);
|
||||
if (!run) return null;
|
||||
return run.views;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get live run views from Redis
|
||||
*/
|
||||
export async function updateLiveRunViews(
|
||||
id: string,
|
||||
increment: number,
|
||||
): Promise<number | null> {
|
||||
const run = await getLiveRun(id);
|
||||
if (!run) return null;
|
||||
run.views += increment;
|
||||
await redis.set(`liveRun:${run.id}`, JSON.stringify(run));
|
||||
return run.views;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all live runs
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user