mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-29 08:52:25 +00:00
Merge pull request #245 from PR0M3TH3AN/codex/add-logging-for-watch-history-updates-36ejak
Decouple watch history updates from view logging timers
This commit is contained in:
2 files changed
+160
-68
No files matched your search
@@ -6983,8 +6983,12 @@ class bitvidApp {
|
||||
return;
|
||||
}
|
||||
|
||||
if (state.timerId) {
|
||||
clearTimeout(state.timerId);
|
||||
if (state.viewTimerId) {
|
||||
clearTimeout(state.viewTimerId);
|
||||
}
|
||||
|
||||
if (state.historyTimerId) {
|
||||
clearTimeout(state.historyTimerId);
|
||||
}
|
||||
|
||||
if (Array.isArray(state.handlers) && state.videoEl) {
|
||||
@@ -7080,24 +7084,41 @@ class bitvidApp {
|
||||
return;
|
||||
}
|
||||
|
||||
const THRESHOLD_SECONDS = 12;
|
||||
const VIEW_THRESHOLD_SECONDS = 12;
|
||||
const WATCH_HISTORY_THRESHOLD_SECONDS = 10;
|
||||
const state = {
|
||||
videoEl,
|
||||
pointer,
|
||||
pointerKey,
|
||||
viewerIdentityKey,
|
||||
handlers: [],
|
||||
timerId: null,
|
||||
fired: false,
|
||||
viewTimerId: null,
|
||||
historyTimerId: null,
|
||||
viewFired: false,
|
||||
historyFired: false,
|
||||
};
|
||||
|
||||
const finalize = () => {
|
||||
if (state.fired) {
|
||||
const maybeCleanup = () => {
|
||||
if (state.viewFired && state.historyFired) {
|
||||
this.cancelPendingViewLogging();
|
||||
}
|
||||
};
|
||||
|
||||
const clearTimer = (timerKey) => {
|
||||
const property = `${timerKey}TimerId`;
|
||||
if (state[property]) {
|
||||
clearTimeout(state[property]);
|
||||
state[property] = null;
|
||||
}
|
||||
};
|
||||
|
||||
const finalizeView = () => {
|
||||
if (state.viewFired) {
|
||||
return;
|
||||
}
|
||||
state.fired = true;
|
||||
cancelTimer();
|
||||
this.cancelPendingViewLogging();
|
||||
state.viewFired = true;
|
||||
clearTimer("view");
|
||||
maybeCleanup();
|
||||
|
||||
const { pointer: thresholdPointer, pointerKey: thresholdPointerKey } =
|
||||
state;
|
||||
@@ -7140,23 +7161,6 @@ class bitvidApp {
|
||||
viewResult
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const historyResult = await updateWatchHistoryList(thresholdPointer);
|
||||
if (!historyResult?.ok && isDevMode) {
|
||||
console.warn(
|
||||
"[playVideoWithFallback] Watch history update failed:",
|
||||
historyResult
|
||||
);
|
||||
}
|
||||
} catch (historyError) {
|
||||
if (isDevMode) {
|
||||
console.warn(
|
||||
"[playVideoWithFallback] Exception while updating watch history:",
|
||||
historyError
|
||||
);
|
||||
}
|
||||
}
|
||||
})().catch((error) => {
|
||||
if (isDevMode) {
|
||||
console.warn(
|
||||
@@ -7167,15 +7171,45 @@ class bitvidApp {
|
||||
});
|
||||
};
|
||||
|
||||
const cancelTimer = () => {
|
||||
if (state.timerId) {
|
||||
clearTimeout(state.timerId);
|
||||
state.timerId = null;
|
||||
const finalizeWatchHistory = () => {
|
||||
if (state.historyFired) {
|
||||
return;
|
||||
}
|
||||
state.historyFired = true;
|
||||
clearTimer("history");
|
||||
maybeCleanup();
|
||||
|
||||
const { pointer: thresholdPointer } = state;
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
const historyResult = await updateWatchHistoryList(thresholdPointer);
|
||||
if (!historyResult?.ok) {
|
||||
console.warn(
|
||||
"[playVideoWithFallback] Watch history update failed:",
|
||||
historyResult
|
||||
);
|
||||
}
|
||||
} catch (historyError) {
|
||||
console.warn(
|
||||
"[playVideoWithFallback] Exception while updating watch history:",
|
||||
historyError
|
||||
);
|
||||
}
|
||||
})().catch((error) => {
|
||||
if (isDevMode) {
|
||||
console.warn(
|
||||
"[playVideoWithFallback] Unexpected error while updating watch history:",
|
||||
error
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const scheduleTimer = () => {
|
||||
if (state.fired) {
|
||||
const scheduleTimer = (timerKey, thresholdSeconds, callback) => {
|
||||
const firedKey = `${timerKey}Fired`;
|
||||
const idKey = `${timerKey}TimerId`;
|
||||
if (state[firedKey] || state[idKey]) {
|
||||
return;
|
||||
}
|
||||
const currentSeconds = Number.isFinite(videoEl.currentTime)
|
||||
@@ -7183,13 +7217,13 @@ class bitvidApp {
|
||||
: 0;
|
||||
const remainingMs = Math.max(
|
||||
0,
|
||||
Math.ceil((THRESHOLD_SECONDS - currentSeconds) * 1000)
|
||||
Math.ceil((thresholdSeconds - currentSeconds) * 1000)
|
||||
);
|
||||
if (remainingMs <= 0) {
|
||||
finalize();
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
state.timerId = window.setTimeout(finalize, remainingMs);
|
||||
state[idKey] = window.setTimeout(callback, remainingMs);
|
||||
};
|
||||
|
||||
const registerHandler = (eventName, handler) => {
|
||||
@@ -7198,14 +7232,23 @@ class bitvidApp {
|
||||
};
|
||||
|
||||
registerHandler("timeupdate", () => {
|
||||
if (videoEl.currentTime >= THRESHOLD_SECONDS) {
|
||||
finalize();
|
||||
if (
|
||||
!state.historyFired &&
|
||||
videoEl.currentTime >= WATCH_HISTORY_THRESHOLD_SECONDS
|
||||
) {
|
||||
finalizeWatchHistory();
|
||||
}
|
||||
if (!state.viewFired && videoEl.currentTime >= VIEW_THRESHOLD_SECONDS) {
|
||||
finalizeView();
|
||||
}
|
||||
});
|
||||
|
||||
const cancelOnPause = () => {
|
||||
if (!state.fired) {
|
||||
cancelTimer();
|
||||
if (!state.viewFired) {
|
||||
clearTimer("view");
|
||||
}
|
||||
if (!state.historyFired) {
|
||||
clearTimer("history");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -7214,9 +7257,15 @@ class bitvidApp {
|
||||
);
|
||||
|
||||
const resumeIfNeeded = () => {
|
||||
if (!state.fired && !state.timerId) {
|
||||
scheduleTimer();
|
||||
if (state.viewFired && state.historyFired) {
|
||||
return;
|
||||
}
|
||||
scheduleTimer(
|
||||
"history",
|
||||
WATCH_HISTORY_THRESHOLD_SECONDS,
|
||||
finalizeWatchHistory
|
||||
);
|
||||
scheduleTimer("view", VIEW_THRESHOLD_SECONDS, finalizeView);
|
||||
};
|
||||
|
||||
["play", "playing"].forEach((event) =>
|
||||
|
||||
+69
-26
@@ -2552,39 +2552,82 @@ class NostrClient {
|
||||
overallSuccess = false;
|
||||
}
|
||||
|
||||
const publishAttemptSummaries = [];
|
||||
const acceptedRelaySet = new Set();
|
||||
|
||||
const recordPublishAttempt = (label, results) => {
|
||||
if (!Array.isArray(results) || !results.length) {
|
||||
return;
|
||||
}
|
||||
const accepted = results
|
||||
.filter((result) => result && result.success)
|
||||
.map((result) => result.url)
|
||||
.filter((url) => typeof url === "string" && url);
|
||||
if (accepted.length) {
|
||||
accepted.forEach((url) => acceptedRelaySet.add(url));
|
||||
}
|
||||
publishAttemptSummaries.push({ label, accepted, results });
|
||||
};
|
||||
|
||||
chunkResults.forEach((chunk) => {
|
||||
recordPublishAttempt(`chunk#${chunk.chunkIndex}`, chunk.results);
|
||||
});
|
||||
recordPublishAttempt("index", indexPublishResults);
|
||||
|
||||
const failedAttempts = publishAttemptSummaries.filter(
|
||||
(attempt) => !attempt.accepted.length
|
||||
);
|
||||
|
||||
if (acceptedRelaySet.size) {
|
||||
console.info(
|
||||
`[nostr] Watch history publish accepted by ${acceptedRelaySet.size} relay(s):`,
|
||||
Array.from(acceptedRelaySet).join(", ")
|
||||
);
|
||||
}
|
||||
|
||||
if (failedAttempts.length) {
|
||||
console.warn(
|
||||
"[nostr] Watch history publish rejected by relays:",
|
||||
failedAttempts.map((attempt) => ({
|
||||
label: attempt.label,
|
||||
results: attempt.results,
|
||||
}))
|
||||
);
|
||||
} else if (!acceptedRelaySet.size && publishAttemptSummaries.length) {
|
||||
console.warn("[nostr] Watch history publish had no relay attempts.");
|
||||
}
|
||||
|
||||
if (overallSuccess) {
|
||||
this.cancelWatchHistoryRepublish(normalizedActor);
|
||||
} else if (allowRetry && persistedItems.length) {
|
||||
this.scheduleWatchHistoryRepublish(normalizedActor, persistedItems);
|
||||
}
|
||||
|
||||
if (isDevMode) {
|
||||
const latestItem = persistedItems[0] || null;
|
||||
const latestPointerKey = pointerKey(latestItem);
|
||||
const latestPointerSummary = latestPointerKey
|
||||
? latestPointerKey.length > 32
|
||||
? `${latestPointerKey.slice(0, 32)}…`
|
||||
: latestPointerKey
|
||||
: null;
|
||||
const actorPreview =
|
||||
normalizedActor.length > 16
|
||||
? `${normalizedActor.slice(0, 8)}…${normalizedActor.slice(-4)}`
|
||||
: normalizedActor;
|
||||
const summary = {
|
||||
actor: actorPreview,
|
||||
itemCount: persistedItems.length,
|
||||
snapshot: snapshotId,
|
||||
latestPointer: latestPointerSummary,
|
||||
latestWatchedAt: Number.isFinite(latestItem?.watchedAt)
|
||||
? new Date(Math.max(0, Math.floor(latestItem.watchedAt))).toISOString()
|
||||
: null,
|
||||
};
|
||||
const latestItem = persistedItems[0] || null;
|
||||
const latestPointerKey = pointerKey(latestItem);
|
||||
const latestPointerSummary = latestPointerKey
|
||||
? latestPointerKey.length > 32
|
||||
? `${latestPointerKey.slice(0, 32)}…`
|
||||
: latestPointerKey
|
||||
: null;
|
||||
const actorPreview =
|
||||
normalizedActor.length > 16
|
||||
? `${normalizedActor.slice(0, 8)}…${normalizedActor.slice(-4)}`
|
||||
: normalizedActor;
|
||||
const summary = {
|
||||
actor: actorPreview,
|
||||
itemCount: persistedItems.length,
|
||||
snapshot: snapshotId,
|
||||
latestPointer: latestPointerSummary,
|
||||
latestWatchedAt: Number.isFinite(latestItem?.watchedAt)
|
||||
? new Date(Math.max(0, Math.floor(latestItem.watchedAt))).toISOString()
|
||||
: null,
|
||||
};
|
||||
|
||||
if (overallSuccess) {
|
||||
console.info("[nostr] Watch history snapshot updated:", summary);
|
||||
} else {
|
||||
console.warn("[nostr] Watch history snapshot publish incomplete:", summary);
|
||||
}
|
||||
if (overallSuccess) {
|
||||
console.info("[nostr] Watch history snapshot updated:", summary);
|
||||
} else {
|
||||
console.warn("[nostr] Watch history snapshot publish incomplete:", summary);
|
||||
}
|
||||
|
||||
const pointerEvent =
|
||||
|
||||
Reference in new issue
Block a user