diff --git a/addon/Dockerfile b/addon/Dockerfile index 9aaf66a..14dd96e 100644 --- a/addon/Dockerfile +++ b/addon/Dockerfile @@ -1,4 +1,4 @@ -FROM node:16-alpine +FROM node:21-alpine RUN apk update && apk upgrade && \ apk add --no-cache git diff --git a/addon/addon.js b/addon/addon.js index a017a4e..0492989 100644 --- a/addon/addon.js +++ b/addon/addon.js @@ -1,4 +1,3 @@ -import Bottleneck from 'bottleneck'; import { addonBuilder } from 'stremio-addon-sdk'; import { Type } from './lib/types.js'; import { dummyManifest } from './lib/manifest.js'; @@ -10,6 +9,7 @@ import applyFilters from './lib/filter.js'; import { applyMochs, getMochCatalog, getMochItemMeta } from './moch/moch.js'; import StaticLinks from './moch/static.js'; import { createNamedQueue } from "./lib/namedQueue.js"; +import pLimit from "p-limit"; const CACHE_MAX_AGE = parseInt(process.env.CACHE_MAX_AGE) || 60 * 60; // 1 hour in seconds const CACHE_MAX_AGE_EMPTY = 60; // 60 seconds @@ -19,12 +19,7 @@ const STALE_ERROR_AGE = 7 * 24 * 60 * 60; // 7 days const builder = new addonBuilder(dummyManifest()); const requestQueue = createNamedQueue(Infinity); -const limiter = new Bottleneck({ - maxConcurrent: process.env.LIMIT_MAX_CONCURRENT || 40, - highWater: process.env.LIMIT_QUEUE_SIZE || 100, - strategy: Bottleneck.strategy.OVERFLOW -}); -const limiterOptions = { expiration: 2 * 60 * 1000 } +const newLimiter = pLimit(30) builder.defineStreamHandler((args) => { if (!args.id.match(/tt\d+/i) && !args.id.match(/kitsu:\d+/i)) { @@ -69,14 +64,14 @@ builder.defineMetaHandler((args) => { }) async function resolveStreams(args) { - return cacheWrapStream(args.id, () => limiter.schedule(limiterOptions, () => streamHandler(args) + return cacheWrapStream(args.id, () => newLimiter(() => streamHandler(args) .then(records => records .sort((a, b) => b.torrent.seeders - a.torrent.seeders || b.torrent.uploadDate - a.torrent.uploadDate) .map(record => toStreamInfo(record))))); } async function streamHandler(args) { - console.log(`Current stats: `, limiter.counts()) + // console.log(`Pending count: ${newLimiter.pendingCount}, active count: ${newLimiter.activeCount}`, ) if (args.type === Type.MOVIE) { return movieRecordsHandler(args); } else if (args.type === Type.SERIES) { diff --git a/addon/lib/cache.js b/addon/lib/cache.js index 7f46d0a..72a2c3a 100644 --- a/addon/lib/cache.js +++ b/addon/lib/cache.js @@ -9,6 +9,7 @@ const RESOLVED_URL_KEY_PREFIX = `${GLOBAL_KEY_PREFIX}|resolved`; const STREAM_TTL = process.env.STREAM_TTL || 24 * 60 * 60; // 24 hours const STREAM_EMPTY_TTL = process.env.STREAM_EMPTY_TTL || 60; // 1 minute +const RESOLVED_URL_TTL = 3 * 60 * 60; // 3 hours const AVAILABILITY_TTL = 8 * 60 * 60; // 8 hours const AVAILABILITY_EMPTY_TTL = 30 * 60; // 30 minutes const MESSAGE_VIDEO_URL_TTL = 60; // 1 minutes @@ -30,7 +31,7 @@ function initiateRemoteCache() { options: { collection: 'torrentio_addon_collection', socketTimeoutMS: 30000, - poolSize: 150, + poolSize: 200, useNewUrlParser: true, useUnifiedTopology: false, ttl: STREAM_EMPTY_TTL @@ -68,8 +69,8 @@ export function cacheWrapStream(id, method) { } export function cacheWrapResolvedUrl(id, method) { - return cacheWrap(memoryCache, `${RESOLVED_URL_KEY_PREFIX}:${id}`, method, { - ttl: (url) => isStaticUrl(url) ? MESSAGE_VIDEO_URL_TTL : STREAM_TTL + return cacheWrap(remoteCache, `${RESOLVED_URL_KEY_PREFIX}:${id}`, method, { + ttl: (url) => isStaticUrl(url) ? MESSAGE_VIDEO_URL_TTL : RESOLVED_URL_TTL }); } diff --git a/addon/lib/repository.js b/addon/lib/repository.js index 9447514..e1a6121 100644 --- a/addon/lib/repository.js +++ b/addon/lib/repository.js @@ -3,7 +3,7 @@ const Op = Sequelize.Op; const DATABASE_URI = process.env.DATABASE_URI; -const database = new Sequelize(DATABASE_URI, { logging: false, pool: { max: 50, min: 5, idle: 60 * 60 * 1000 } }); +const database = new Sequelize(DATABASE_URI, { logging: false, pool: { max: 30, min: 5, idle: 20 * 60 * 1000 } }); const Torrent = database.define('torrent', { diff --git a/addon/moch/realdebrid.js b/addon/moch/realdebrid.js index 6aaa7a3..54ea857 100644 --- a/addon/moch/realdebrid.js +++ b/addon/moch/realdebrid.js @@ -395,5 +395,5 @@ function infringingFile(error) { } async function getDefaultOptions(ip) { - return { ip, timeout: 10000 }; + return { ip, timeout: 15000 }; } diff --git a/addon/package-lock.json b/addon/package-lock.json index 321243d..5d7445c 100644 --- a/addon/package-lock.json +++ b/addon/package-lock.json @@ -22,6 +22,7 @@ "name-to-imdb": "^3.0.4", "named-queue": "^2.2.1", "offcloud-api": "^1.0.2", + "p-limit": "^5.0.0", "parse-torrent-title": "git://github.com/TheBeastLT/parse-torrent-title.git#022408972c2a040f846331a912a6a8487746a654", "pg": "^8.11.3", "pg-hstore": "^2.3.4", @@ -1452,6 +1453,20 @@ "node": ">=0.10.0" } }, + "node_modules/p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/packet-reader": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", @@ -2548,6 +2563,17 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/addon/package.json b/addon/package.json index da2c7f4..ef95f2e 100644 --- a/addon/package.json +++ b/addon/package.json @@ -22,6 +22,7 @@ "name-to-imdb": "^3.0.4", "named-queue": "^2.2.1", "offcloud-api": "^1.0.2", + "p-limit": "^5.0.0", "parse-torrent-title": "git://github.com/TheBeastLT/parse-torrent-title.git#022408972c2a040f846331a912a6a8487746a654", "pg": "^8.11.3", "pg-hstore": "^2.3.4",