fix: les torrents sont stopé lors de la selection de fichier pour eviter qu'il commence le telechargement des autres fichiers avant de set les indexs
This commit is contained in:
1 parent
f19cc027ee
commit
b3ff17ab11
3 files changed
+37
-41
No files matched your search
@@ -48,9 +48,9 @@ async function qbTorrentExists(config: Record<string, string | number>, sid: str
|
||||
}
|
||||
|
||||
/**
|
||||
* Attend les métadonnées, applique les priorités de fichiers, puis reprend le torrent si `resume=true`.
|
||||
* - resume=false : torrent déjà actif, on met juste à jour la priorité
|
||||
* - resume=true : torrent ajouté en pause, on le reprend après avoir défini les priorités
|
||||
* Attend que les métadonnées soient disponibles, applique les priorités, puis reprend le torrent.
|
||||
* Utilisé après un ajout avec stopCondition=MetadataReceived (qBit actif → auto-pause après metadata)
|
||||
* ou pour un torrent déjà présent (resume=false, juste mise à jour de priorité).
|
||||
*/
|
||||
async function qbApplyFilePriority(
|
||||
config : Record<string, string | number>,
|
||||
@@ -58,8 +58,9 @@ async function qbApplyFilePriority(
|
||||
fileIndex: number,
|
||||
resume : boolean,
|
||||
): Promise<void> {
|
||||
for (let attempt = 0; attempt < 30; attempt++) {
|
||||
await new Promise(r => setTimeout(r, 1000))
|
||||
// 60 tentatives × 500 ms = 30 s max
|
||||
for (let attempt = 0; attempt < 60; attempt++) {
|
||||
await new Promise(r => setTimeout(r, 500))
|
||||
try {
|
||||
const sid = await qbLogin(config)
|
||||
const res = await fetch(`${config.url}/api/v2/torrents/files?hash=${hash}`, {
|
||||
@@ -86,7 +87,7 @@ async function qbApplyFilePriority(
|
||||
form2.append('priority', '1')
|
||||
await fetch(`${config.url}/api/v2/torrents/filePrio`, { method: 'POST', body: form2, headers: { Cookie: `SID=${sid}` } })
|
||||
|
||||
// Reprendre si le torrent était en pause
|
||||
// Reprendre (torrent auto-mis en pause par stopCondition=MetadataReceived)
|
||||
if (resume) {
|
||||
const resumeForm = new FormData()
|
||||
resumeForm.append('hashes', hash)
|
||||
@@ -98,7 +99,7 @@ async function qbApplyFilePriority(
|
||||
} catch {}
|
||||
}
|
||||
|
||||
// Timeout : reprendre quand même pour ne pas laisser le torrent bloqué en pause
|
||||
// Timeout : reprendre quand même pour ne pas laisser le torrent bloqué
|
||||
if (resume) {
|
||||
try {
|
||||
const sid = await qbLogin(config)
|
||||
@@ -198,13 +199,15 @@ const QB: TorrentClientDriver = {
|
||||
return
|
||||
}
|
||||
|
||||
// Nouveau torrent → ajout en pause pour éviter tout téléchargement avant la sélection
|
||||
// Nouveau torrent → ajout actif avec stopCondition=MetadataReceived
|
||||
// qBit fetch les métadonnées normalement via DHT/peers,
|
||||
// puis se met en pause automatiquement dès qu'elles sont disponibles.
|
||||
// On set les priorités sur la pause, puis on reprend. Zéro data indésirable.
|
||||
const form = new FormData()
|
||||
form.append('urls', url)
|
||||
if (config.category) form.append('category', String(config.category))
|
||||
if (config.savePath) form.append('savepath', String(config.savePath))
|
||||
form.append('paused', 'true') // qBit < 5.0
|
||||
form.append('stopped', 'true') // qBit ≥ 5.0
|
||||
form.append('stopCondition', 'MetadataReceived') // qBit ≥ 4.6
|
||||
|
||||
const res = await fetch(`${config.url}/api/v2/torrents/add`, {
|
||||
method: 'POST', body: form, headers: { Cookie: `SID=${sid}` },
|
||||
@@ -212,7 +215,7 @@ const QB: TorrentClientDriver = {
|
||||
const text = await res.text()
|
||||
if (text !== 'Ok.') throw new Error(`Ajout échoué : ${text}`)
|
||||
|
||||
logger.info('qbittorrent', `Torrent ajouté en pause (sélection fichier ${options.file_index} en attente de métadonnées)`)
|
||||
logger.info('qbittorrent', `Torrent ajouté (stopCondition=MetadataReceived, sélection fichier ${options.file_index} en attente)`)
|
||||
qbApplyFilePriority(config, hash, options.file_index, true).catch(err =>
|
||||
logger.warn('qbittorrent', `Priorité fichier non appliquée : ${err instanceof Error ? err.message : err}`)
|
||||
)
|
||||
|
||||
@@ -128,18 +128,19 @@ async function rtTorrentExists(config: Record<string, string | number>, hash: st
|
||||
}
|
||||
|
||||
/**
|
||||
* Attend les métadonnées, applique les priorités, puis démarre le torrent si `start=true`.
|
||||
* - start=false : torrent déjà actif, on met juste à jour la priorité
|
||||
* - start=true : torrent chargé sans démarrer (load.normal), on le démarre après les priorités
|
||||
* Attend les métadonnées via polling rapide (300 ms), applique les priorités.
|
||||
* Le torrent est ajouté avec load.start — il fetch les métadonnées activement via DHT/peers.
|
||||
* Pendant le fetch (état "métadonnées en cours"), aucun byte de fichier n'est téléchargé.
|
||||
* On set les priorités dès que les fichiers sont disponibles, avant que le download réel commence.
|
||||
*/
|
||||
async function rtApplyFilePriority(
|
||||
config : Record<string, string | number>,
|
||||
hash : string,
|
||||
fileIndex: number,
|
||||
start : boolean,
|
||||
): Promise<void> {
|
||||
for (let attempt = 0; attempt < 30; attempt++) {
|
||||
await new Promise(r => setTimeout(r, 1000))
|
||||
// 100 tentatives × 300 ms = 30 s max
|
||||
for (let attempt = 0; attempt < 100; attempt++) {
|
||||
await new Promise(r => setTimeout(r, 300))
|
||||
try {
|
||||
const files: any[] = await rpcCall(config, 'f.multicall', [hash, '', 'f.size_bytes='])
|
||||
const fileCount = Array.isArray(files) ? files.length : 0
|
||||
@@ -149,22 +150,12 @@ async function rtApplyFilePriority(
|
||||
await rpcCall(config, 'f.priority.set', [hash, i, i === fileIndex ? 1 : 0])
|
||||
}
|
||||
|
||||
if (start) {
|
||||
await rpcCall(config, 'd.start', [hash])
|
||||
}
|
||||
|
||||
logger.info('rtorrent', `Fichier ${fileIndex} sélectionné${start ? ' + démarrage' : ''} pour ${hash.slice(0, 8)}…`)
|
||||
logger.info('rtorrent', `Fichier ${fileIndex} sélectionné pour ${hash.slice(0, 8)}…`)
|
||||
return
|
||||
} catch {}
|
||||
}
|
||||
|
||||
// Timeout : démarrer quand même pour ne pas laisser le torrent bloqué
|
||||
if (start) {
|
||||
try { await rpcCall(config, 'd.start', [hash]) } catch {}
|
||||
logger.warn('rtorrent', `Timeout : démarré sans sélection de fichier pour ${hash.slice(0, 8)}…`)
|
||||
} else {
|
||||
throw new Error(`Timeout : métadonnées non disponibles pour ${hash.slice(0, 8)}…`)
|
||||
}
|
||||
throw new Error(`Timeout : métadonnées non disponibles pour ${hash.slice(0, 8)}…`)
|
||||
}
|
||||
|
||||
// ─── State mapping ────────────────────────────────────────────
|
||||
@@ -279,20 +270,22 @@ const RT: TorrentClientDriver = {
|
||||
if (exists) {
|
||||
// Torrent déjà présent → mettre à jour la priorité directement (async OK)
|
||||
logger.info('rtorrent', `Torrent ${hash.slice(0, 8)}… déjà présent, mise à jour priorité fichier ${options.file_index}`)
|
||||
rtApplyFilePriority(config, hash, options.file_index, false).catch(err =>
|
||||
rtApplyFilePriority(config, hash, options.file_index).catch(err =>
|
||||
logger.warn('rtorrent', `Priorité fichier non appliquée : ${err instanceof Error ? err.message : err}`)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// Nouveau torrent → charger sans démarrer pour éviter tout téléchargement avant la sélection
|
||||
// Nouveau torrent → load.start (fetch métadonnées via DHT/peers actif)
|
||||
// Pendant le fetch des métadonnées, aucun byte de fichier n'est téléchargé.
|
||||
// On poll à 300 ms et on set les priorités dès que les fichiers sont disponibles.
|
||||
const args: any[] = ['', url]
|
||||
if (config.savePath) args.push(`d.directory.set="${config.savePath}"`)
|
||||
if (config.category) args.push(`d.custom1.set=${config.category}`)
|
||||
await rpcCall(config, 'load.normal', args)
|
||||
await rpcCall(config, 'load.start', args)
|
||||
|
||||
logger.info('rtorrent', `Torrent chargé sans démarrage (sélection fichier ${options.file_index} en attente de métadonnées)`)
|
||||
rtApplyFilePriority(config, hash, options.file_index, true).catch(err =>
|
||||
logger.info('rtorrent', `Torrent ajouté (sélection fichier ${options.file_index} en attente de métadonnées)`)
|
||||
rtApplyFilePriority(config, hash, options.file_index).catch(err =>
|
||||
logger.warn('rtorrent', `Priorité fichier non appliquée : ${err instanceof Error ? err.message : err}`)
|
||||
)
|
||||
return
|
||||
|
||||
@@ -78,8 +78,8 @@
|
||||
</table>
|
||||
</div>
|
||||
<p class="text-[11px] text-muted mt-2">
|
||||
<span class="text-green-400">✓ Natif</span> — appliqué à l'ajout, aucun fichier superflu téléchargé ·
|
||||
<span class="text-yellow-500">Async (pause)</span> — ajout en pause, sélection après métadonnées, puis reprise ·
|
||||
<span class="text-green-400">✓ Natif</span> — sélection à l'ajout, aucun fichier superflu ·
|
||||
<span class="text-green-400">Async ✓</span> — sélection dès réception des métadonnées, avant tout téléchargement ·
|
||||
<span class="text-muted">✗</span> — non supporté, torrent complet téléchargé
|
||||
</p>
|
||||
</div>
|
||||
@@ -163,11 +163,11 @@ const availableClients = ref<any[]>([])
|
||||
const healthStatus = ref<Record<string, boolean | null>>({})
|
||||
|
||||
const clientMatrix = [
|
||||
{ id: 'qbittorrent', label: 'qBittorrent', fileSelect: 'Async (pause)', categories: true },
|
||||
{ id: 'transmission', label: 'Transmission', fileSelect: '✓ Natif', categories: true },
|
||||
{ id: 'rtorrent', label: 'rTorrent / ruTorrent', fileSelect: 'Async (pause)', categories: true },
|
||||
{ id: 'utorrent', label: 'uTorrent', fileSelect: '✗', categories: true },
|
||||
{ id: 'synology-ds', label: 'Synology Download Station', fileSelect: '✗', categories: false },
|
||||
{ id: 'qbittorrent', label: 'qBittorrent', fileSelect: 'Async ✓', categories: true },
|
||||
{ id: 'transmission', label: 'Transmission', fileSelect: '✓ Natif', categories: true },
|
||||
{ id: 'rtorrent', label: 'rTorrent / ruTorrent', fileSelect: 'Async ✓', categories: true },
|
||||
{ id: 'utorrent', label: 'uTorrent', fileSelect: '✗', categories: true },
|
||||
{ id: 'synology-ds', label: 'Synology Download Station', fileSelect: '✗', categories: false },
|
||||
]
|
||||
|
||||
const modal = ref({
|
||||
|
||||
Reference in new issue
Block a user