Run Xtream imports in background to avoid long-held HTTP connections dropping silently
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
from pymongo import MongoClient
|
from pymongo import MongoClient
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
import socketio
|
import socketio
|
||||||
|
import asyncio
|
||||||
import os, glob
|
import os, glob
|
||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
@@ -714,6 +715,19 @@ async def import_xtream_codes(request):
|
|||||||
)
|
)
|
||||||
save_playlist_document(playlist_doc)
|
save_playlist_document(playlist_doc)
|
||||||
|
|
||||||
|
asyncio.create_task(run_xtream_import(
|
||||||
|
id_playlist, import_key, collection_channels,
|
||||||
|
xtream_server, xtream_username, xtream_password, sidClient
|
||||||
|
))
|
||||||
|
|
||||||
|
return web.json_response({'status': 'started', 'id_playlist': id_playlist})
|
||||||
|
|
||||||
|
|
||||||
|
async def run_xtream_import(id_playlist, import_key, collection_channels,
|
||||||
|
xtream_server, xtream_username, xtream_password, sidClient):
|
||||||
|
# Runs in the background: the HTTP request already returned, so imports that take
|
||||||
|
# minutes no longer hold a live connection open (which browsers/networks can silently drop).
|
||||||
|
# Completion is reported to the client over the existing progress_analysis socketio channel.
|
||||||
try:
|
try:
|
||||||
await emit_analysis_progress({'percentage': 0.02}, sidClient)
|
await emit_analysis_progress({'percentage': 0.02}, sidClient)
|
||||||
|
|
||||||
@@ -781,15 +795,29 @@ async def import_xtream_codes(request):
|
|||||||
bulk_insert_channels(collection_channels, pending_channels, inserted_channels)
|
bulk_insert_channels(collection_channels, pending_channels, inserted_channels)
|
||||||
number_channels = collection_channels.count_documents({"id_playlist": id_playlist})
|
number_channels = collection_channels.count_documents({"id_playlist": id_playlist})
|
||||||
playlists.update_many({'id_playlist': id_playlist}, {"$set": {"num_channels": number_channels}})
|
playlists.update_many({'id_playlist': id_playlist}, {"$set": {"num_channels": number_channels}})
|
||||||
await emit_analysis_progress({'percentage': 1}, sidClient)
|
await emit_analysis_progress({
|
||||||
return web.json_response({'num_channel': number_channels, 'id_playlist': id_playlist})
|
'percentage': 1,
|
||||||
|
'completed': True,
|
||||||
|
'num_channel': number_channels,
|
||||||
|
'id_playlist': id_playlist,
|
||||||
|
}, sidClient)
|
||||||
|
|
||||||
except requests.RequestException as exc:
|
except requests.RequestException as exc:
|
||||||
logger.exception("Xtream import failed")
|
logger.exception("Xtream import failed")
|
||||||
return web.json_response({'error': f'Xtream request failed: {exc}'}, status=502)
|
await emit_analysis_progress({
|
||||||
|
'percentage': 1,
|
||||||
|
'completed': True,
|
||||||
|
'error': f'Xtream request failed: {exc}',
|
||||||
|
'id_playlist': id_playlist,
|
||||||
|
}, sidClient)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.exception("Xtream import failed")
|
logger.exception("Xtream import failed")
|
||||||
return web.json_response({'error': f'Xtream import failed: {exc}'}, status=500)
|
await emit_analysis_progress({
|
||||||
|
'percentage': 1,
|
||||||
|
'completed': True,
|
||||||
|
'error': f'Xtream import failed: {exc}',
|
||||||
|
'id_playlist': id_playlist,
|
||||||
|
}, sidClient)
|
||||||
finally:
|
finally:
|
||||||
active_xtream_imports.pop(import_key, None)
|
active_xtream_imports.pop(import_key, None)
|
||||||
|
|
||||||
|
|||||||
+25
-13
@@ -1557,6 +1557,28 @@
|
|||||||
var displayPercent = Math.round(percentage * 100)
|
var displayPercent = Math.round(percentage * 100)
|
||||||
$("#progress-bar").val(displayPercent);
|
$("#progress-bar").val(displayPercent);
|
||||||
$("#progress-text").text(displayPercent + "%");
|
$("#progress-text").text(displayPercent + "%");
|
||||||
|
|
||||||
|
if (payload['completed']) {
|
||||||
|
if (payload['id_playlist']) {
|
||||||
|
$('#id_playlist_to_action').val(payload['id_playlist']);
|
||||||
|
}
|
||||||
|
if (payload['error']) {
|
||||||
|
$('#add_playlist_alert').html('<div class="alert alert-danger" role="alert">' + payload['error'] + '</div>');
|
||||||
|
} else {
|
||||||
|
var num_channel = payload['num_channel'] || 0;
|
||||||
|
if (num_channel > 0) {
|
||||||
|
$('#add_playlist_alert').html('<div class="alert alert-success" role="alert">Imported items: ' + String(num_channel) + '</div>');
|
||||||
|
update_list_playlist();
|
||||||
|
$('#modal_add_playlist').modal('hide');
|
||||||
|
} else {
|
||||||
|
$('#add_playlist_alert').html('<div class="alert alert-danger" role="alert">No items returned by Xtream Codes.</div>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$("#progress-container").hide();
|
||||||
|
playlistImportInFlight = false;
|
||||||
|
playlistImportProgress = 0;
|
||||||
|
$('#upload-button').prop('disabled', false).text('Save');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2850,22 +2872,12 @@
|
|||||||
xtream_username: xtreamUsername,
|
xtream_username: xtreamUsername,
|
||||||
xtream_password: xtreamPassword
|
xtream_password: xtreamPassword
|
||||||
}).done(function(data){
|
}).done(function(data){
|
||||||
if (data.status === 'already_running') {
|
// The import runs in the background on the server; completion is reported
|
||||||
|
// via the progress_analysis socket event, not this HTTP response.
|
||||||
$('#id_playlist_to_action').val(data.id_playlist || $('#id_playlist_to_action').val());
|
$('#id_playlist_to_action').val(data.id_playlist || $('#id_playlist_to_action').val());
|
||||||
$('#add_playlist_alert').html('<div class="alert alert-info" role="alert">' + (data.message || 'Xtream import already running...') + '</div>');
|
$('#add_playlist_alert').html('<div class="alert alert-info" role="alert">' + (data.message || 'Importing Xtream Codes playlist...') + '</div>');
|
||||||
playlistImportInFlight = true;
|
playlistImportInFlight = true;
|
||||||
$('#upload-button').prop('disabled', true).text('Importing...');
|
$('#upload-button').prop('disabled', true).text('Importing...');
|
||||||
return;
|
|
||||||
}
|
|
||||||
var num_channel = data.num_channel || 0;
|
|
||||||
$('#id_playlist_to_action').val(data.id_playlist || $('#id_playlist_to_action').val());
|
|
||||||
if (num_channel > 0) {
|
|
||||||
$('#add_playlist_alert').html('<div class="alert alert-success" role="alert">Imported items: ' + String(num_channel) + '</div>');
|
|
||||||
} else {
|
|
||||||
$('#add_playlist_alert').html('<div class="alert alert-danger" role="alert">No items returned by Xtream Codes.</div>');
|
|
||||||
}
|
|
||||||
update_list_playlist();
|
|
||||||
$('#modal_add_playlist').modal('hide');
|
|
||||||
}).fail(function(xhr){
|
}).fail(function(xhr){
|
||||||
var message = 'Xtream import failed.';
|
var message = 'Xtream import failed.';
|
||||||
if (xhr.responseJSON && xhr.responseJSON.error) {
|
if (xhr.responseJSON && xhr.responseJSON.error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user