fix(live): expose full refresh busy and phase progress
Ensure full refresh marks the live projection as building before source refresh awaits, and expose phase-specific counters so language detection progress is determinate. Covers #40 and #41. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -9,6 +9,7 @@ const router = express.Router();
|
||||
|
||||
function serializeState(state) {
|
||||
const emptyProjectionWithLiveInput = state.total_count > 0 && state.projected_count === 0;
|
||||
const isLayaPhase = state.phase === 'laya_identity' || state.phase === 'laya_language';
|
||||
return {
|
||||
status: state.status,
|
||||
stale: state.status !== 'success' || emptyProjectionWithLiveInput,
|
||||
@ -21,6 +22,8 @@ function serializeState(state) {
|
||||
total: state.total_count,
|
||||
layaProcessed: state.laya_processed_count,
|
||||
layaTotal: state.laya_total_count,
|
||||
phaseProcessed: isLayaPhase ? state.laya_processed_count : state.processed_count,
|
||||
phaseTotal: isLayaPhase ? state.laya_total_count : state.total_count,
|
||||
error: state.error
|
||||
};
|
||||
}
|
||||
|
||||
@ -296,7 +296,7 @@ function updateProjectionProgress(database, phase, progress = {}) {
|
||||
`).run(phase, progress.layaProcessed ?? null, progress.layaTotal ?? null);
|
||||
}
|
||||
|
||||
function markProjectionBuilding(database = null) {
|
||||
function markProjectionBuilding(database = null, phase = 'preparing') {
|
||||
database ||= defaultDatabase();
|
||||
const total = database.prepare("SELECT COUNT(*) AS count FROM playlist_items WHERE type = 'live'").get().count;
|
||||
const startedAt = Date.now();
|
||||
@ -304,12 +304,12 @@ function markProjectionBuilding(database = null) {
|
||||
INSERT INTO catalog_projection_state
|
||||
(projection, status, started_at, completed_at, input_hash, projected_count, phase,
|
||||
processed_count, total_count, laya_processed_count, laya_total_count, error)
|
||||
VALUES ('live', 'building', ?, NULL, NULL, 0, 'preparing', 0, ?, 0, 0, NULL)
|
||||
VALUES ('live', 'building', ?, NULL, NULL, 0, ?, 0, ?, 0, 0, NULL)
|
||||
ON CONFLICT(projection) DO UPDATE SET status = 'building', started_at = excluded.started_at,
|
||||
completed_at = NULL, phase = 'preparing', processed_count = 0,
|
||||
completed_at = NULL, phase = excluded.phase, processed_count = 0,
|
||||
total_count = excluded.total_count, laya_processed_count = 0,
|
||||
laya_total_count = 0, error = NULL
|
||||
`).run(startedAt, total);
|
||||
`).run(startedAt, phase, total);
|
||||
return projectionState(database);
|
||||
}
|
||||
|
||||
@ -392,8 +392,9 @@ async function fullRebuildOrchestrator(database = null, dependencies = {}) {
|
||||
database ||= defaultDatabase();
|
||||
const syncService = dependencies.syncService || require('./syncService');
|
||||
const sourceRepository = dependencies.sources || require('../db').sources;
|
||||
markProjectionBuilding(database, 'refreshing_live_sources');
|
||||
await syncService.refreshEnabledLiveSources({ rebuild: false });
|
||||
await startRebuild(database, { analyzeAll: true }).promise;
|
||||
await startRebuild(database, { analyzeAll: true, stateAlreadyBuilding: true }).promise;
|
||||
await syncService.refreshEnabledEpgSources();
|
||||
const epgSources = await sourceRepository.getByType('epg');
|
||||
epgMatching.rebuildPersistedEpgMatches(database, epgSources);
|
||||
@ -441,9 +442,10 @@ function startRebuild(database = null, options = {}) {
|
||||
mark = markProjectionBuilding,
|
||||
runner = rebuildWithSignals,
|
||||
schedule = setImmediate,
|
||||
stateAlreadyBuilding = false,
|
||||
...rebuildOptions
|
||||
} = options;
|
||||
activeState = mark(database);
|
||||
activeState = stateAlreadyBuilding ? projectionState(database) : mark(database);
|
||||
activeRebuild = new Promise((resolve, reject) => {
|
||||
schedule(() => {
|
||||
Promise.resolve()
|
||||
|
||||
Reference in New Issue
Block a user