Page MenuHomePhorge

D15423.1765023656.diff
No OneTemporary

Size
17 KB
Referenced Files
None
Subscribers
None

D15423.1765023656.diff

diff --git a/lib/shared/farcaster/farcaster-hooks.js b/lib/shared/farcaster/farcaster-hooks.js
--- a/lib/shared/farcaster/farcaster-hooks.js
+++ b/lib/shared/farcaster/farcaster-hooks.js
@@ -23,7 +23,11 @@
type FarcasterMessage,
farcasterMessageValidator,
} from './farcaster-messages-types.js';
-import { logTypes, useDebugLogs } from '../../components/debug-logs-context.js';
+import {
+ type AddLogCallback,
+ logTypes,
+ useDebugLogs,
+} from '../../components/debug-logs-context.js';
import { useIsUserDataReady } from '../../hooks/backup-hooks.js';
import { useGetLatestMessageEdit } from '../../hooks/latest-message-edit.js';
import { useGetCommFCUsersForFIDs } from '../../hooks/user-identities-hooks.js';
@@ -161,6 +165,8 @@
operation: () => Promise<T>,
maxRetries: number = MAX_RETRIES,
delayMs: number = RETRY_DELAY_MS,
+ addLog?: AddLogCallback,
+ operationName?: string,
): Promise<T> {
let lastError;
@@ -170,6 +176,18 @@
} catch (error) {
lastError = error;
+ if (addLog && operationName) {
+ addLog(
+ `Farcaster: Retry attempt ${attempt}/${maxRetries + 1} failed for ${operationName}`,
+ JSON.stringify({
+ attempt,
+ maxRetries,
+ error: getMessageForException(error),
+ }),
+ new Set([logTypes.FARCASTER]),
+ );
+ }
+
if (attempt <= maxRetries) {
const delay = delayMs * attempt;
await sleep(delay);
@@ -185,8 +203,11 @@
processor: (item: T, batchedUpdates: BatchedUpdates) => Promise<R>,
dispatch: Dispatch,
onProgress?: (completed: number, total: number) => void,
+ addLog?: AddLogCallback,
): Promise<Array<R>> {
const results: Array<R> = [];
+ let failedItemsCount = 0;
+
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize);
@@ -197,6 +218,17 @@
return { result, updates: itemBatchedUpdates };
} catch (error) {
console.log('Error processing item:', item, 'Error:', error);
+ if (addLog) {
+ addLog(
+ 'Farcaster: Failed to process item in batch',
+ JSON.stringify({
+ item: typeof item === 'string' ? item : 'complex_item',
+ batchIndex: i,
+ error: getMessageForException(error),
+ }),
+ new Set([logTypes.FARCASTER]),
+ );
+ }
return null;
}
});
@@ -204,6 +236,7 @@
const batchResults = await Promise.all(batchPromises);
let batchedUpdates = new BatchedUpdates();
+ let nullResultsInBatch = 0;
for (const itemResult of batchResults) {
if (itemResult) {
@@ -218,9 +251,24 @@
});
batchedUpdates = new BatchedUpdates();
}
+ } else {
+ nullResultsInBatch++;
+ failedItemsCount++;
}
}
+ if (nullResultsInBatch > 0 && addLog) {
+ addLog(
+ 'Farcaster: Some items in batch returned null results',
+ JSON.stringify({
+ nullCount: nullResultsInBatch,
+ batchSize: batch.length,
+ batchIndex: i,
+ }),
+ new Set([logTypes.FARCASTER]),
+ );
+ }
+
if (!batchedUpdates.isEmpty()) {
dispatch({
type: processFarcasterOpsActionType,
@@ -235,6 +283,21 @@
await sleep(0);
}
+ if (failedItemsCount > 0 && addLog) {
+ addLog(
+ 'Farcaster: Total failed items in processing',
+ JSON.stringify({
+ failedCount: failedItemsCount,
+ totalCount: items.length,
+ successRate:
+ (((items.length - failedItemsCount) / items.length) * 100).toFixed(
+ 2,
+ ) + '%',
+ }),
+ new Set([logTypes.FARCASTER]),
+ );
+ }
+
return results;
}
@@ -249,6 +312,7 @@
conversationId: string,
}) => Promise<?FetchFarcasterConversationResult>,
fetchUsersByFIDs: GetCommFCUsersForFIDs,
+ addLog?: AddLogCallback,
): Promise<?ConversationFetchResult> {
const conversationResult = await withRetry(
() =>
@@ -257,16 +321,63 @@
}),
MAX_RETRIES,
RETRY_DELAY_MS,
+ addLog,
+ `fetchConversation(${conversationID})`,
);
if (!conversationResult) {
+ if (addLog) {
+ addLog(
+ 'Farcaster: Conversation result is null after retries',
+ JSON.stringify({ conversationID }),
+ new Set([logTypes.FARCASTER]),
+ );
+ }
+ return null;
+ }
+
+ if (!conversationResult.result?.conversation) {
+ if (addLog) {
+ addLog(
+ 'Farcaster: Invalid conversation result structure',
+ JSON.stringify({
+ conversationID,
+ hasResult: !!conversationResult.result,
+ hasConversation: !!conversationResult.result?.conversation,
+ }),
+ new Set([logTypes.FARCASTER]),
+ );
+ }
return null;
}
const farcasterConversation = conversationResult.result.conversation;
let thread = createFarcasterRawThreadInfo(farcasterConversation);
const fids = thread.members.map(member => member.id);
+
+ if (fids.length === 0 && addLog) {
+ addLog(
+ 'Farcaster: No members (FIDs) found in conversation',
+ JSON.stringify({ conversationID }),
+ new Set([logTypes.FARCASTER]),
+ );
+ }
+
const commFCUsersForFIDs = await fetchUsersByFIDs(fids);
+
+ if (commFCUsersForFIDs.size !== fids.length && addLog) {
+ addLog(
+ 'Farcaster: FID to user mapping incomplete',
+ JSON.stringify({
+ conversationID,
+ requestedFIDs: fids.length,
+ resolvedUsers: commFCUsersForFIDs.size,
+ missingFIDs: fids.filter(fid => !commFCUsersForFIDs.has(fid)),
+ }),
+ new Set([logTypes.FARCASTER]),
+ );
+ }
+
const threadMembers = thread.members.map(
member =>
({
@@ -302,9 +413,15 @@
conversationID,
fetchFarcasterConversation,
fetchUsersByFIDs,
+ addLog,
);
if (!result) {
+ addLog(
+ 'Farcaster: No result while fetching conversation',
+ JSON.stringify({ conversationID }),
+ new Set([logTypes.FARCASTER]),
+ );
return null;
}
@@ -320,7 +437,13 @@
rawEntryInfos: [],
};
- if (threadMembers.length > 0) {
+ if (threadMembers.length === 0) {
+ addLog(
+ 'Farcaster: No thread members found for conversation',
+ JSON.stringify({ conversationID }),
+ new Set([logTypes.FARCASTER]),
+ );
+ } else {
threadMembers.forEach(member => batchedUpdates.addUserID(member.id));
}
batchedUpdates.addUpdateInfo(update);
@@ -363,15 +486,27 @@
conversationID,
fetchFarcasterConversation,
fetchUsersByFIDs,
+ addLog,
);
if (!result) {
+ addLog(
+ 'Farcaster: No result while fetching conversation with messages',
+ JSON.stringify({ conversationID, messagesLimit }),
+ new Set([logTypes.FARCASTER]),
+ );
return null;
}
const { farcasterConversation, thread, threadMembers } = result;
- if (threadMembers.length > 0) {
+ if (threadMembers.length === 0) {
+ addLog(
+ 'Farcaster: No thread members in conversation with messages',
+ JSON.stringify({ conversationID }),
+ new Set([logTypes.FARCASTER]),
+ );
+ } else {
threadMembers.forEach(member => batchedUpdates.addUserID(member.id));
}
@@ -379,6 +514,15 @@
conversationID,
messagesLimit,
);
+
+ if (messagesResult.messages.length === 0) {
+ addLog(
+ 'Farcaster: No messages fetched for conversation',
+ JSON.stringify({ conversationID, messagesLimit }),
+ new Set([logTypes.FARCASTER]),
+ );
+ }
+
batchedUpdates.addUserIDs(messagesResult.userIDs);
const reduxMessages = messagesResult.messages.slice(
@@ -453,11 +597,14 @@
}> => {
const result: Array<RawMessageInfo> = [];
const userIDs: Array<string> = [];
+ let batchNumber = 0;
+
try {
let totalMessagesFetched = 0;
let lastSeenMessageID: ?string = null;
do {
+ batchNumber++;
const batchLimit = Math.min(
50,
messagesNumberLimit - totalMessagesFetched,
@@ -477,16 +624,40 @@
() => fetchFarcasterMessages(messagesInput),
MAX_RETRIES,
RETRY_DELAY_MS,
+ addLog,
+ `fetchMessages(${conversationID}, batch=${batchNumber})`,
);
if (messagesResult) {
const farcasterMessages = messagesResult.result.messages;
+
+ if (farcasterMessages.length === 0) {
+ addLog(
+ 'Farcaster: Empty message batch received',
+ JSON.stringify({
+ conversationID,
+ batchNumber,
+ hasCursor: !!cursor,
+ }),
+ new Set([logTypes.FARCASTER]),
+ );
+ }
+
const lastMessageID =
farcasterMessages.length > 0
? farcasterMessages[farcasterMessages.length - 1].messageId
: null;
if (lastMessageID === lastSeenMessageID) {
+ addLog(
+ 'Farcaster: Duplicate message batch detected (breaking loop)',
+ JSON.stringify({
+ conversationID,
+ lastMessageID,
+ batchNumber,
+ }),
+ new Set([logTypes.FARCASTER]),
+ );
break;
}
lastSeenMessageID = lastMessageID;
@@ -499,6 +670,19 @@
);
const fcUserInfos = await fetchUsersByFIDs(userFIDs);
+ if (fcUserInfos.size !== userFIDs.length) {
+ addLog(
+ 'Farcaster: Not all FIDs resolved to users in message batch',
+ JSON.stringify({
+ conversationID,
+ requestedFIDs: userFIDs.length,
+ resolvedUsers: fcUserInfos.size,
+ batchNumber,
+ }),
+ new Set([logTypes.FARCASTER]),
+ );
+ }
+
const rawMessageInfos = farcasterMessages.flatMap(message =>
convertFarcasterMessageToCommMessages(
message,
@@ -507,6 +691,19 @@
),
);
+ if (rawMessageInfos.length < farcasterMessages.length) {
+ addLog(
+ 'Farcaster: Some messages failed to convert',
+ JSON.stringify({
+ conversationID,
+ farcasterMessages: farcasterMessages.length,
+ convertedMessages: rawMessageInfos.length,
+ batchNumber,
+ }),
+ new Set([logTypes.FARCASTER]),
+ );
+ }
+
userIDs.push(
...Array.from(fcUserInfos.entries()).map(
([fid, user]) => user?.userID ?? userIDFromFID(fid),
@@ -529,6 +726,7 @@
conversationID,
messagesNumberLimit,
cursor,
+ batchNumber,
error: getMessageForException(e),
}),
new Set([logTypes.FARCASTER]),
@@ -584,8 +782,10 @@
): Promise<$ReadOnlyArray<FarcasterInboxConversation>> => {
const allConversations: Array<FarcasterInboxConversation> = [];
let currentCursor = null;
+ let pageNumber = 0;
while (true) {
+ pageNumber++;
try {
let input = { limit: 50, category };
if (currentCursor) {
@@ -598,8 +798,22 @@
() => fetchFarcasterInbox(input),
MAX_RETRIES,
RETRY_DELAY_MS,
+ addLog,
+ `fetchInbox(${category || 'main'}, page=${pageNumber})`,
);
+ if (result.conversations.length === 0) {
+ addLog(
+ 'Farcaster: Empty inbox page received',
+ JSON.stringify({
+ category: category || 'main',
+ pageNumber,
+ hasNextCursor: !!next?.cursor,
+ }),
+ new Set([logTypes.FARCASTER]),
+ );
+ }
+
allConversations.push(...result.conversations);
if (next?.cursor) {
@@ -613,6 +827,8 @@
JSON.stringify({
category: category || 'main',
cursor: currentCursor,
+ pageNumber,
+ conversationsFetchedSoFar: allConversations.length,
error: getMessageForException(e),
}),
new Set([logTypes.FARCASTER]),
@@ -645,6 +861,7 @@
) => void {
const dispatch = useDispatch();
const threadInfos = useSelector(state => state.threadStore.threadInfos);
+ const { addLog } = useDebugLogs();
return React.useCallback(
(conversations: $ReadOnlyArray<string>) => {
@@ -666,6 +883,14 @@
threadID: threadInfo.id,
}));
+ addLog(
+ 'Farcaster: Removing dead threads',
+ JSON.stringify({
+ removedThreads: updateInfos.map(updateInfo => updateInfo.threadID),
+ }),
+ new Set([logTypes.FARCASTER]),
+ );
+
dispatch({
type: processFarcasterOpsActionType,
payload: {
@@ -674,27 +899,22 @@
},
});
},
- [dispatch, threadInfos],
+ [addLog, dispatch, threadInfos],
);
}
function useFarcasterConversationsSync(): (
- limit: number,
onProgress?: (completed: number, total: number) => void,
) => Promise<void> {
const dispatch = useDispatch();
const fetchConversationWithMessages = useFetchConversationWithMessages();
const setFarcasterDCsLoaded = useSetFarcasterDCsLoaded();
const { addLog } = useDebugLogs();
- const threadInfos = useSelector(state => state.threadStore.threadInfos);
const fetchInboxes = useFetchInboxIDs();
const removeDeadThreads = useRemoveDeadThreads();
return React.useCallback(
- async (
- limit: number,
- onProgress?: (completed: number, total: number) => void,
- ) => {
+ async (onProgress?: (completed: number, total: number) => void) => {
try {
const inboxResults = await Promise.all([
fetchInboxes(),
@@ -706,20 +926,15 @@
removeDeadThreads(conversations);
if (conversations.length === 0) {
+ addLog(
+ 'Farcaster: No conversations to sync',
+ JSON.stringify({}),
+ new Set([logTypes.FARCASTER]),
+ );
setFarcasterDCsLoaded(true);
return;
}
- const threadIDs = new Set(Object.keys(threadInfos));
- const newConversations = new Set(
- conversations.filter(
- conversationID =>
- !threadIDs.has(
- farcasterThreadIDFromConversationID(conversationID),
- ),
- ),
- );
-
onProgress?.(0, conversations.length);
await processInBatchesWithReduxBatching(
conversations,
@@ -727,13 +942,12 @@
(conversationID, batchedUpdates) =>
fetchConversationWithMessages(
conversationID,
- newConversations.has(conversationID)
- ? Number.POSITIVE_INFINITY
- : limit,
+ Number.POSITIVE_INFINITY,
batchedUpdates,
),
dispatch,
(completed, total) => onProgress?.(completed, total),
+ addLog,
);
setFarcasterDCsLoaded(true);
@@ -755,7 +969,6 @@
fetchInboxes,
removeDeadThreads,
setFarcasterDCsLoaded,
- threadInfos,
],
);
}
@@ -849,6 +1062,7 @@
existingConversationIDs.length + completed,
conversations.length,
),
+ addLog,
);
}
} catch (e) {
@@ -888,10 +1102,12 @@
return React.useCallback(
async (farcasterMessage: FarcasterMessage) => {
+ const threadID = farcasterThreadIDFromConversationID(
+ farcasterMessage.conversationId,
+ );
+
if (
- !threadInfos[
- farcasterThreadIDFromConversationID(farcasterMessage.conversationId)
- ] &&
+ !threadInfos[threadID] &&
!currentlyFetchedConversations.current.has(
farcasterMessage.conversationId,
)
@@ -925,6 +1141,18 @@
fcUserInfos,
addLog,
);
+
+ if (rawMessageInfos.length === 0) {
+ addLog(
+ 'Farcaster: Failed to convert new message to Comm messages',
+ JSON.stringify({
+ conversationID: farcasterMessage.conversationId,
+ messageID: farcasterMessage.messageId,
+ }),
+ new Set([logTypes.FARCASTER]),
+ );
+ }
+
const userIDs = userFIDs.map(fid => userIDFromFID(`${fid}`));
const updates: Array<ClientUpdateInfo> = [];
@@ -1025,10 +1253,7 @@
setProgress(null);
void (async () => {
try {
- await syncFarcasterConversations(
- Number.POSITIVE_INFINITY,
- handleProgress,
- );
+ await syncFarcasterConversations(handleProgress);
} finally {
setInProgress(false);
setProgress(null);

File Metadata

Mime Type
text/plain
Expires
Sat, Dec 6, 12:20 PM (18 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5837390
Default Alt Text
D15423.1765023656.diff (17 KB)

Event Timeline