feat: retry on fail, move metrics
This commit is contained in:
parent
d32574db8a
commit
a481527257
7 changed files with 61 additions and 68 deletions
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"tasks": {
|
"tasks": {
|
||||||
"dev": "deno run --allow-import=github.com:443,jsr.io:443,raw.githubusercontent.com:443,esm.sh:443,deno.land:443 --allow-net --allow-env --allow-sys=hostname --allow-read --allow-write=/var/tmp/youtubei.js --watch src/main.ts",
|
"dev": "deno run --allow-import=github.com:443,jsr.io:443,raw.githubusercontent.com:443,esm.sh:443,deno.land:443 --allow-net --allow-env --allow-sys=hostname --allow-read --allow-write=/var/tmp/youtubei.js --watch --unsafely-ignore-certificate-errors src/main.ts",
|
||||||
"compile": "deno compile --include ./src/lib/helpers/youtubePlayerReq.ts --include ./src/lib/helpers/getFetchClient.ts --output invidious_companion --allow-import=github.com:443,jsr.io:443,raw.githubusercontent.com:443,esm.sh:443,deno.land:443 --allow-net --allow-env --allow-read --allow-sys=hostname --allow-write=/var/tmp/youtubei.js --unsafely-ignore-certificate-errors src/main.ts"
|
"compile": "deno compile --include ./src/lib/helpers/youtubePlayerReq.ts --include ./src/lib/helpers/getFetchClient.ts --output invidious_companion --allow-import=github.com:443,jsr.io:443,raw.githubusercontent.com:443,esm.sh:443,deno.land:443 --allow-net --allow-env --allow-read --allow-sys=hostname --allow-write=/var/tmp/youtubei.js --unsafely-ignore-certificate-errors src/main.ts"
|
||||||
},
|
},
|
||||||
"imports": {
|
"imports": {
|
||||||
|
@ -19,7 +19,8 @@
|
||||||
"@willsoto/node-konfig-toml-parser": "npm:@willsoto/node-konfig-toml-parser@3.0.0",
|
"@willsoto/node-konfig-toml-parser": "npm:@willsoto/node-konfig-toml-parser@3.0.0",
|
||||||
"youtubePlayerReq": "./src/lib/helpers/youtubePlayerReq.ts",
|
"youtubePlayerReq": "./src/lib/helpers/youtubePlayerReq.ts",
|
||||||
"getFetchClient": "./src/lib/helpers/getFetchClient.ts",
|
"getFetchClient": "./src/lib/helpers/getFetchClient.ts",
|
||||||
"googlevideo": "npm:googlevideo@2.0.0"
|
"googlevideo": "npm:googlevideo@2.0.0",
|
||||||
|
"metrics": "./src/routes/metrics.ts"
|
||||||
},
|
},
|
||||||
"unstable": [
|
"unstable": [
|
||||||
"cron",
|
"cron",
|
||||||
|
@ -29,4 +30,4 @@
|
||||||
"fmt": {
|
"fmt": {
|
||||||
"indentWidth": 4
|
"indentWidth": 4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ try {
|
||||||
proxies = proxyData.split("\n").map((line) => line.trim()).filter((line) =>
|
proxies = proxyData.split("\n").map((line) => line.trim()).filter((line) =>
|
||||||
line.length > 0
|
line.length > 0
|
||||||
);
|
);
|
||||||
|
console.log("[INFO] Num of proxies on the list:", proxies.length)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("[ERROR] Error reading proxy file:", error);
|
console.error("[ERROR] Error reading proxy file:", error);
|
||||||
console.log("[INFO] Proxies from a list of proxies will not be used");
|
console.log("[INFO] Proxies from a list of proxies will not be used");
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { ApiResponse, Innertube, YT } from "youtubei.js";
|
||||||
import { generateRandomString } from "youtubei.js/Utils";
|
import { generateRandomString } from "youtubei.js/Utils";
|
||||||
import { compress, decompress } from "https://deno.land/x/brotli@0.1.7/mod.ts";
|
import { compress, decompress } from "https://deno.land/x/brotli@0.1.7/mod.ts";
|
||||||
import { Store } from "@willsoto/node-konfig-core";
|
import { Store } from "@willsoto/node-konfig-core";
|
||||||
import { failedRequests, successfulRequests } from "../../routes/index.ts";
|
import { failedRequests, successfulRequests, retryCount } from "metrics";
|
||||||
let youtubePlayerReqLocation = "youtubePlayerReq";
|
let youtubePlayerReqLocation = "youtubePlayerReq";
|
||||||
if (Deno.env.get("YT_PLAYER_REQ_LOCATION")) {
|
if (Deno.env.get("YT_PLAYER_REQ_LOCATION")) {
|
||||||
if (Deno.env.has("DENO_COMPILED")) {
|
if (Deno.env.has("DENO_COMPILED")) {
|
||||||
|
@ -19,6 +19,8 @@ const { youtubePlayerReq } = await import(youtubePlayerReqLocation);
|
||||||
const videoCachePath = Deno.env.get("VIDEO_CACHE_PATH") as string ||
|
const videoCachePath = Deno.env.get("VIDEO_CACHE_PATH") as string ||
|
||||||
"/var/tmp/youtubei.js/video_cache";
|
"/var/tmp/youtubei.js/video_cache";
|
||||||
|
|
||||||
|
const maxRetries = Deno.env.get("MAX_PROXY_RETRIES") as string || 3;
|
||||||
|
|
||||||
export let kv: Deno.Kv;
|
export let kv: Deno.Kv;
|
||||||
if ((Deno.env.get("VIDEO_CACHE_ON_DISK")?.toLowerCase() ?? false) == "true") {
|
if ((Deno.env.get("VIDEO_CACHE_ON_DISK")?.toLowerCase() ?? false) == "true") {
|
||||||
console.log("[INFO] Storing video cache on disk");
|
console.log("[INFO] Storing video cache on disk");
|
||||||
|
@ -40,11 +42,29 @@ export const youtubePlayerParsing = async (
|
||||||
if (videoCached != null && cacheEnabled == true) {
|
if (videoCached != null && cacheEnabled == true) {
|
||||||
return JSON.parse(new TextDecoder().decode(decompress(videoCached)));
|
return JSON.parse(new TextDecoder().decode(decompress(videoCached)));
|
||||||
} else {
|
} else {
|
||||||
const youtubePlayerResponse = await youtubePlayerReq(
|
let youtubePlayerResponse = await youtubePlayerReq(
|
||||||
innertubeClient,
|
innertubeClient,
|
||||||
videoId,
|
videoId,
|
||||||
konfigStore,
|
konfigStore,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
for (let retries = 1; retries <= (maxRetries as number); retries++) {
|
||||||
|
if (
|
||||||
|
!youtubePlayerResponse.data.playabilityStatus?.errorScreen
|
||||||
|
?.playerErrorMessageRenderer?.subreason?.runs?.[0]?.text
|
||||||
|
?.includes("This helps protect our community")
|
||||||
|
) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
console.log(`[DEBUG] Got 'This helps protect our community', retrying request for ${videoId}. Retry ${retries} of ${maxRetries}`)
|
||||||
|
retryCount.inc()
|
||||||
|
youtubePlayerResponse = await youtubePlayerReq(
|
||||||
|
innertubeClient,
|
||||||
|
videoId,
|
||||||
|
konfigStore,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const videoData = youtubePlayerResponse.data;
|
const videoData = youtubePlayerResponse.data;
|
||||||
|
|
||||||
const video = new YT.VideoInfo(
|
const video = new YT.VideoInfo(
|
||||||
|
|
|
@ -3,7 +3,7 @@ import type { BgConfig } from "bgutils";
|
||||||
import { JSDOM } from "jsdom";
|
import { JSDOM } from "jsdom";
|
||||||
import { Innertube, UniversalCache } from "youtubei.js";
|
import { Innertube, UniversalCache } from "youtubei.js";
|
||||||
import { Store } from "@willsoto/node-konfig-core";
|
import { Store } from "@willsoto/node-konfig-core";
|
||||||
import { externalTokenGeneratorFail, poTokenFail } from "../../routes/index.ts";
|
import { externalTokenGeneratorFail, poTokenFail } from "metrics";
|
||||||
let getFetchClientLocation = "getFetchClient";
|
let getFetchClientLocation = "getFetchClient";
|
||||||
if (Deno.env.get("GET_FETCH_CLIENT_LOCATION")) {
|
if (Deno.env.get("GET_FETCH_CLIENT_LOCATION")) {
|
||||||
if (Deno.env.has("DENO_COMPILED")) {
|
if (Deno.env.has("DENO_COMPILED")) {
|
||||||
|
|
|
@ -2,71 +2,12 @@ import { Hono } from "hono";
|
||||||
import { logger } from "hono/logger";
|
import { logger } from "hono/logger";
|
||||||
import { Store } from "@willsoto/node-konfig-core";
|
import { Store } from "@willsoto/node-konfig-core";
|
||||||
import { bearerAuth } from "hono/bearer-auth";
|
import { bearerAuth } from "hono/bearer-auth";
|
||||||
import { Counter, Gauge, Registry } from "prom-client";
|
|
||||||
|
|
||||||
import youtubeApiPlayer from "./youtube_api_routes/player.ts";
|
import youtubeApiPlayer from "./youtube_api_routes/player.ts";
|
||||||
import invidiousRouteLatestVersion from "./invidious_routes/latestVersion.ts";
|
import invidiousRouteLatestVersion from "./invidious_routes/latestVersion.ts";
|
||||||
import invidiousRouteDashManifest from "./invidious_routes/dashManifest.ts";
|
import invidiousRouteDashManifest from "./invidious_routes/dashManifest.ts";
|
||||||
import videoPlaybackProxy from "./videoPlaybackProxy.ts";
|
import videoPlaybackProxy from "./videoPlaybackProxy.ts";
|
||||||
import metrics from "./metrics.ts";
|
import metrics from "metrics";
|
||||||
|
|
||||||
const METRICS_PREFIX = "invidious_companion_";
|
|
||||||
export const register = new Registry();
|
|
||||||
|
|
||||||
export const externalTokenGeneratorFail = new Counter({
|
|
||||||
name: `${METRICS_PREFIX}externaltokengenerator_fail`,
|
|
||||||
help: "TODO",
|
|
||||||
registers: [register],
|
|
||||||
});
|
|
||||||
|
|
||||||
export const cachedEntries = new Gauge({
|
|
||||||
name: `${METRICS_PREFIX}cached_entries`,
|
|
||||||
help: "TODO",
|
|
||||||
registers: [register],
|
|
||||||
});
|
|
||||||
|
|
||||||
export const subreasonProtectCommunity = new Counter({
|
|
||||||
name: `${METRICS_PREFIX}subreason_protect_community`,
|
|
||||||
help: "TODO",
|
|
||||||
registers: [register],
|
|
||||||
});
|
|
||||||
|
|
||||||
export const poTokenFail = new Counter({
|
|
||||||
name: `${METRICS_PREFIX}potoken_fail`,
|
|
||||||
help: "TODO",
|
|
||||||
registers: [register],
|
|
||||||
});
|
|
||||||
|
|
||||||
export const reasonBot = new Counter({
|
|
||||||
name: `${METRICS_PREFIX}reason_bot`,
|
|
||||||
help: "TODO",
|
|
||||||
registers: [register],
|
|
||||||
});
|
|
||||||
|
|
||||||
export const videoUnavailable = new Counter({
|
|
||||||
name: `${METRICS_PREFIX}video_unavailable`,
|
|
||||||
help: "TODO",
|
|
||||||
registers: [register],
|
|
||||||
});
|
|
||||||
|
|
||||||
export const videoRestricted = new Counter({
|
|
||||||
name: `${METRICS_PREFIX}video_restricted`,
|
|
||||||
help: "TODO",
|
|
||||||
registers: [register],
|
|
||||||
});
|
|
||||||
|
|
||||||
export const failedRequests = new Counter({
|
|
||||||
name: `${METRICS_PREFIX}failed_requests`,
|
|
||||||
help: "TODO",
|
|
||||||
registers: [register],
|
|
||||||
});
|
|
||||||
|
|
||||||
export const successfulRequests = new Counter({
|
|
||||||
name: `${METRICS_PREFIX}successful_requests`,
|
|
||||||
help: "TODO",
|
|
||||||
registers: [register],
|
|
||||||
});
|
|
||||||
|
|
||||||
import health from "./health.ts";
|
import health from "./health.ts";
|
||||||
|
|
||||||
export const routes = (
|
export const routes = (
|
||||||
|
|
|
@ -1,8 +1,38 @@
|
||||||
import { Hono } from "hono";
|
import { Hono } from "hono";
|
||||||
import { cachedEntries, register } from "./index.ts";
|
import { Counter, Gauge, Registry } from "prom-client";
|
||||||
import { kv } from "../lib/helpers/youtubePlayerHandling.ts";
|
import { kv } from "../lib/helpers/youtubePlayerHandling.ts";
|
||||||
|
|
||||||
const metrics = new Hono();
|
const metrics = new Hono();
|
||||||
|
const METRICS_PREFIX = "invidious_companion_";
|
||||||
|
export const register = new Registry();
|
||||||
|
|
||||||
|
function createCounter(name: string, help?: string): Counter {
|
||||||
|
return new Counter({
|
||||||
|
name: `${METRICS_PREFIX}${name}`,
|
||||||
|
help: help || "TODO",
|
||||||
|
registers: [register],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const cachedEntries = new Gauge({
|
||||||
|
name: `${METRICS_PREFIX}cached_entries`,
|
||||||
|
help: "TODO",
|
||||||
|
registers: [register],
|
||||||
|
});
|
||||||
|
|
||||||
|
export const externalTokenGeneratorFail = createCounter(
|
||||||
|
"externaltokengenerator_fail",
|
||||||
|
);
|
||||||
|
export const subreasonProtectCommunity = createCounter(
|
||||||
|
"subreason_protect_community",
|
||||||
|
);
|
||||||
|
export const poTokenFail = createCounter("potoken_fail");
|
||||||
|
export const reasonBot = createCounter("reason_bot", "TODO");
|
||||||
|
export const videoUnavailable = createCounter("video_unavailable", "TODO");
|
||||||
|
export const videoRestricted = createCounter("video_restricted", "TODO");
|
||||||
|
export const failedRequests = createCounter("failed_requests", "TODO");
|
||||||
|
export const successfulRequests = createCounter("successful_requests", "TODO");
|
||||||
|
export const retryCount = createCounter("retry_count", "TODO");
|
||||||
|
|
||||||
metrics.get("/", async () => {
|
metrics.get("/", async () => {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
|
|
|
@ -8,7 +8,7 @@ import {
|
||||||
subreasonProtectCommunity,
|
subreasonProtectCommunity,
|
||||||
videoRestricted,
|
videoRestricted,
|
||||||
videoUnavailable,
|
videoUnavailable,
|
||||||
} from "../index.ts";
|
} from "metrics";
|
||||||
|
|
||||||
const player = new Hono<{ Variables: HonoVariables }>();
|
const player = new Hono<{ Variables: HonoVariables }>();
|
||||||
|
|
||||||
|
|
Reference in a new issue