feat: add Redis-backed SSE updates

This commit is contained in:
2026-07-24 21:31:47 +07:00 Unverified
parent 5cc7edaa13
commit 29df784aeb
22 changed files with 912 additions and 96 deletions
+27 -1
View File
@@ -9,6 +9,7 @@ import { eq } from "drizzle-orm";
import { revalidatePath } from "next/cache";
import { requireAdmin } from "@/lib/auth";
import { sanitizeHtml } from "@/lib/sanitize-html";
import { sse } from "@/lib/sse";
export async function createQuestion(
formId: string,
@@ -30,6 +31,11 @@ export async function createQuestion(
options: data.options ?? [],
allowOther: false,
});
void sse.forms.pub("update", {
formId,
entity: "question",
action: "created",
});
revalidatePath("/form");
revalidatePath("/admin/form");
}
@@ -62,6 +68,11 @@ export async function updateQuestion(
};
await db.update(questions).set(nextData).where(eq(questions.id, id));
void sse.forms.pub("update", {
formId,
entity: "question",
action: "updated",
});
revalidatePath("/form");
revalidatePath("/admin/form");
}
@@ -96,7 +107,12 @@ export async function bulkUpdateQuestions(
.where(eq(questions.id, u.id))
)
);
void sse.forms.pub("update", {
formId,
entity: "question",
action: "updated",
});
revalidatePath("/form");
revalidatePath("/admin/form");
}
@@ -123,6 +139,11 @@ export async function deleteQuestion(id: string, formId: string) {
await deleteImageFile(q.imageUrl);
}
await db.delete(questions).where(eq(questions.id, id));
void sse.forms.pub("update", {
formId,
entity: "question",
action: "deleted",
});
revalidatePath("/form");
revalidatePath(`/admin/form/${formId}`);
}
@@ -140,6 +161,11 @@ export async function reorderQuestions(
.where(eq(questions.id, id))
)
);
void sse.forms.pub("update", {
formId,
entity: "question",
action: "updated",
});
revalidatePath("/form");
revalidatePath(`/admin/form/${formId}`);
}
+25
View File
@@ -7,6 +7,7 @@ import { revalidatePath } from "next/cache";
import { getServerSession } from "next-auth";
import { authOptions } from "@/app/api/auth/[...nextauth]/route";
import { requireAdmin, requireDiscordId, requireFormAccess } from "@/lib/auth";
import { sse } from "@/lib/sse";
export async function submitForm(
formId: string,
@@ -148,6 +149,11 @@ export async function submitForm(
}
}
void sse.submissions.pub("update", {
formId,
submissionId: result.submissionId,
action: result.isUpdate ? "updated" : "created",
});
revalidatePath(`/admin/form/${formId}/result`);
return { ok: true };
}
@@ -155,7 +161,18 @@ export async function submitForm(
export async function deleteSubmission(id: string) {
await requireAdmin();
const submission = await db.query.submissions.findFirst({
where: (submission, { eq }) => eq(submission.id, id),
columns: { formId: true },
});
await db.delete(submissions).where(eq(submissions.id, id));
if (submission) {
void sse.submissions.pub("update", {
formId: submission.formId,
submissionId: id,
action: "deleted",
});
}
revalidatePath("/admin/form");
return { ok: true };
}
@@ -164,6 +181,10 @@ export async function deleteAllSubmissions(formId: string) {
await requireAdmin();
await db.delete(submissions).where(eq(submissions.formId, formId));
void sse.submissions.pub("update", {
formId,
action: "deleted",
});
revalidatePath(`/admin/form/${formId}/result`);
return { ok: true };
}
@@ -179,6 +200,10 @@ export async function deleteOwnSubmission(formId: string) {
eq(submissions.userDiscordId, discordId)
)
);
void sse.submissions.pub("update", {
formId,
action: "deleted",
});
revalidatePath(`/form`);
revalidatePath(`/admin/form/${formId}/result`);
return { ok: true };