Skip to content

add logging for error when marking questions as seen #1126

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion actions/answers/markQuestionAsSeenButNotAnswered.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { getJwtPayload } from "@/app/actions/jwt";
import prisma from "@/app/services/prisma";
import { getRandomInteger } from "@/app/utils/randomUtils";
import { AnswerStatus, QuestionType } from "@prisma/client";
import * as Sentry from "@sentry/nextjs";

export async function markQuestionAsSeenButNotAnswered(questionId: number) {
const payload = await getJwtPayload();
Expand Down Expand Up @@ -43,7 +44,13 @@ export async function markQuestionAsSeenButNotAnswered(questionId: number) {
: 0,
};
} catch (error) {
console.log("Error in markQuestionAsSeenButNotAnswered", error);
Sentry.captureException(error, {
extra: {
userId,
},
});

console.error("Error in markQuestionAsSeenButNotAnswered", error);
return { hasError: true };
}
}
47 changes: 38 additions & 9 deletions app/components/Deck/Deck.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import trackEvent from "@/lib/trackEvent";
import { QuestionStep } from "@/types/question";
import { AnswerStatus, QuestionTag, QuestionType, Tag } from "@prisma/client";
import * as Sentry from "@sentry/nextjs";
import classNames from "classnames";
import dayjs from "dayjs";
import { usePathname } from "next/navigation";
Expand Down Expand Up @@ -133,7 +134,7 @@

reset();
setIsSubmitting(false);
}, [

Check warning on line 137 in app/components/Deck/Deck.tsx

View workflow job for this annotation

GitHub Actions / build

React Hook useCallback has missing dependencies: 'creditCostFeatureFlag' and 'deckCost'. Either include them or remove the dependency array
currentQuestionIndex,
setCurrentQuestionIndex,
setCurrentQuestionStep,
Expand All @@ -150,30 +151,58 @@
// every time we have a different truthy question.id
// we mark it as "seen"
useEffect(() => {
const run = async () => {
const res = await markQuestionAsSeenButNotAnswered(question.id);
if (res?.random) {
setRandom(res?.random);
}
if (!!res?.hasError) {
const markQuestionAsSeen = async () => {
try {
const response = await markQuestionAsSeenButNotAnswered(question.id);

// NOTICE: if the response comes with an error we just
// go to the next question and do nothing
// is this the best way to handle this error?
if (response?.hasError) {
Sentry.captureMessage(
`Error calling markQuestionAsSeenButNotAnswered()`,
{
level: "error",
tags: {
category: "deck-errors",
},
extra: {
questionId: question.id,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add userId?

deckId: deckId,
deckVariant: deckVariant,
currentQuestionIndex: currentQuestionIndex,
},
},
);

handleNextIndex();
return;
}

if (response?.random !== undefined) {
setRandom(response.random);
}
} catch (error) {
console.error("Error marking question as seen:", error);
handleNextIndex();
return;
}
};

if (!!question?.id) run();
}, [question?.id]);
if (question?.id) {
markQuestionAsSeen();
}
}, [question?.id, handleNextIndex]);

Check warning on line 194 in app/components/Deck/Deck.tsx

View workflow job for this annotation

GitHub Actions / build

React Hook useEffect has missing dependencies: 'currentQuestionIndex', 'deckId', and 'deckVariant'. Either include them or remove the dependency array

const handleNoAnswer = useCallback(async () => {
setIsTimeOutPopUpVisible(false);
handleNextIndex();
}, [question, handleNextIndex, setDeckResponse]);

Check warning on line 199 in app/components/Deck/Deck.tsx

View workflow job for this annotation

GitHub Actions / build

React Hook useCallback has unnecessary dependencies: 'question' and 'setDeckResponse'. Either exclude them or remove the dependency array

const handleOnDurationRanOut = useCallback(async () => {
if (isSubmitting) return;
await markQuestionAsTimedOut(question.id);
setIsTimeOutPopUpVisible(true);
}, [question, handleNextIndex, setDeckResponse, isSubmitting]);

Check warning on line 205 in app/components/Deck/Deck.tsx

View workflow job for this annotation

GitHub Actions / build

React Hook useCallback has unnecessary dependencies: 'handleNextIndex' and 'setDeckResponse'. Either exclude them or remove the dependency array

const handleSkipQuestion = async () => {
if (processingSkipQuestion) return;
Expand Down Expand Up @@ -268,7 +297,7 @@

handleNextIndex();
},
[

Check warning on line 300 in app/components/Deck/Deck.tsx

View workflow job for this annotation

GitHub Actions / build

React Hook useCallback has missing dependencies: 'deckId', 'deckResponse', 'deckVariant', and 'getTimePassedSinceStart'. Either include them or remove the dependency array
setDeckResponse,
setCurrentQuestionStep,
currentQuestionStep,
Expand All @@ -282,7 +311,7 @@

const hasReachedEnd = useMemo(
() => currentQuestionIndex >= questions.length,
[currentQuestionIndex],

Check warning on line 314 in app/components/Deck/Deck.tsx

View workflow job for this annotation

GitHub Actions / build

React Hook useMemo has a missing dependency: 'questions.length'. Either include it or remove the dependency array
);

useEffect(() => {
Expand Down
9 changes: 9 additions & 0 deletions app/hooks/useInterval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@ import { useEffect, useRef } from "react";

import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect";

// useInterval creates a recurring timer that safely handles callback changes
// - Stores the callback in a ref to avoid unnecessary interval resets
// - Only creates/clears the interval when the delay changes
// - Passing null as delay disables the interval
// - Uses useIsomorphicLayoutEffect to update the callback reference synchronously
export function useInterval(callback: () => void, delay: number | null) {
const savedCallback = useRef(callback);

useIsomorphicLayoutEffect(() => {
savedCallback.current = callback;
}, [callback]);
Expand All @@ -17,6 +23,9 @@ export function useInterval(callback: () => void, delay: number | null) {
savedCallback.current();
}, delay);

// The cleanup function (returned by the `useEffect`) will be called in these scenarios:
// 1. When the component using this hook unmounts
// 2. Before the effect runs again if the `delay` dependency changes
return () => {
clearInterval(id);
};
Expand Down
Loading