Fixed post-crash recovery for actively livestreaming channels.

This commit is contained in:
rainbow napkin 2026-06-03 23:25:55 -04:00
parent ee47e1b844
commit 3ca91288d2
4 changed files with 34 additions and 13 deletions

View file

@ -83,7 +83,7 @@ class archivedMedia extends queuedMedia{
media.startTime,
media.startTimeStamp,
media.earlyEnd,
null,
media.uuid,
channel);
}

View file

@ -1267,7 +1267,7 @@ class queue{
//If archiving is enabled
if(!noArchive){
//Add the item to the channel archive
this.archiveMedia(wasPlaying);
await this.archiveMedia(wasPlaying);
}
//broadcast queue using unsaved archive, run this before chanDB.save() for better responsiveness
@ -1828,29 +1828,29 @@ class queue{
//If we have a remainder from a livestream
if(chanDB.media.liveRemainder){
//Iterate backwards through the archive to pull the newest first, since that's probably where this fucker is
for(let archiveIndex = (chanDB.media.archived.length - 1); archiveIndex > 0; archiveIndex--){
//Grab the current media object
const archivedMedia = chanDB.media.archived[archiveIndex];
let archive = await this.getArchive();
//Iterate backwards through channel archive
for(let archiveIndex = (archive.length - 1); archiveIndex > 0; archiveIndex--){
//If the current object matches our remainder UUID
if((archivedMedia.uuid.toString() == chanDB.media.liveRemainder.toString())){
if((archive[archiveIndex].uuid.toString() == chanDB.media.liveRemainder.toString())){
//Null out any early end
archivedMedia.earlyEnd = null;
archive[archiveIndex].earlyEnd = null;
//Re-hydrate the item
const archivedMediaObject = archivedMedia.rehydrate();
const archivedMediaObject = archive[archiveIndex].rehydrate();
//if we still have a video to finish
if(archivedMediaObject.getEndTime() > now){
//Set the fucker as now playing
chanDB.media.nowPlaying = archivedMediaObject;
//Convert the fucker back to queuedMedia and save as now playing
chanDB.media.nowPlaying = queuedMedia.fromArchivedMedia(archivedMediaObject);
//Schedule the fucker in RAM, w/ the start function also running in RAM-Only mode
this.scheduleMedia([archivedMediaObject], null, chanDB, true, true, true);
//Splice the fucker out of the archive
chanDB.media.archived.splice(archiveIndex, 1);
await archivedMediaModel.deleteOne({channel: this.channel.name, uuid: new BSON.UUID(chanDB.media.liveRemainder)});
}
//Break out of the loop

View file

@ -88,6 +88,27 @@ class queuedMedia extends media{
startTimeStamp);
}
/**
* Creates a queuedMedia object from an archivedMedia object
* @param {String} channel - Channel where object was queued
* @returns {archivedMedia} queuedMedia object created from given media object
*/
static fromArchivedMedia(media){
//Create and return queuedMedia object from given media object and arguments
return new this(
media.title,
media.fileName,
media.url,
media.id,
media.type,
media.duration,
media.rawLink,
media.startTime,
media.startTimeStamp,
media.earlyEnd,
media.uuid);
}
/**
* Converts array of media objects into array of queuedMedia objects
* @param {Array} mediaList - Array of media objects to queue

View file

@ -22,7 +22,7 @@ const mediaSchema = require('./mediaSchema');
const archivedMedia = require('../../../app/channel/media/archivedMedia');
/**
* DB Schema for documents representing a queued media object
* DB Schema for documents representing a archived media object
*/
const archivedProperties = new mongoose.Schema({
channel: {