fix(videos): fan out posts that self-heal to READY via polling

getByPostId's self-heal path (client polls while PROCESSING, checks
Mux directly) set status/muxPlaybackId on READY but never called
fanOutPost, unlike the mux webhook handler's video.asset.ready case.
Videos that self-healed this way played fine but never entered any
pet's feed. Found via a live upload test after the replica rollout.
This commit is contained in:
admin committed 2026-08-16 13:07:31 +02:00
1 parent 1e060e9179
commit faf8ee98b0
1 file changed
+17 -1
+17 -1
View File
@@ -4,6 +4,8 @@ import { TRPCError } from "@trpc/server";
import { router, protectedProcedure } from "@/trpc/init";
import { mux } from "@/lib/mux";
import { assertPetOwnership } from "@/lib/assert-pet-ownership";
import { redis } from "@/lib/redis";
import { fanOutPost } from "@/lib/feed-helpers";
const MAX_VIDEO_DURATION_SECS = 180; // 3 min hard cap — Mux rejects longer via passthrough check
@@ -80,6 +82,7 @@ export const videosRouter = router({
.query(async ({ ctx, input }) => {
const videoPost = await ctx.prisma.videoPost.findUnique({
where: { postId: input.postId },
include: { post: { select: { petId: true, createdAt: true } } },
});
if (!videoPost) throw new TRPCError({ code: "NOT_FOUND" });
@@ -95,7 +98,7 @@ export const videosRouter = router({
if (assetId) {
const asset = await mux.video.assets.retrieve(assetId);
if (asset.status === "ready" && asset.playback_ids?.[0]) {
return await ctx.prisma.videoPost.update({
const updated = await ctx.prisma.videoPost.update({
where: { postId: input.postId },
data: {
status: "READY",
@@ -105,6 +108,19 @@ export const videosRouter = router({
aspectRatio: asset.aspect_ratio ?? null,
},
});
// Mirrors the mux/route.ts webhook handler's fan-out on
// video.asset.ready — without this, a video that self-heals
// here (webhook delayed or unreachable) never enters any
// pet's feed even though it plays fine. zadd is idempotent,
// so this is safe to run again if the real webhook also lands.
await fanOutPost(
redis,
input.postId,
videoPost.post.petId,
videoPost.post.createdAt,
ctx.prisma
).catch((err) => console.error("[videos.getByPostId] fanOutPost failed", err));
return updated;
} else if (asset.status === "errored") {
return await ctx.prisma.videoPost.update({
where: { postId: input.postId },