Release 2.9.0

This commit is contained in:
2026-08-28 02:53:59 +01:00
parent 9097d45d6a
commit 3de0e89e94
67 changed files with 1767 additions and 98 deletions
@@ -1,4 +1,4 @@
const { refreshApiSource, refreshRssFeed } = require('../../data-source-refresh');
const { refreshApiSource, refreshRssFeed, refreshWeatherLocation } = require('../../data-source-refresh');
const TASK = {
taskType: 'data-source-refresh'
@@ -24,6 +24,7 @@ function registerDataSourceRefreshTask(options) {
if (!apiSource) {
throw new Error('API source not found.');
}
if (apiSource.enabled === 0 || apiSource.enabled === false) return { skipped: true, reason: 'disabled' };
return refreshApiSource(pool, common, apiSource, Number(payload.actorId) || null, options.notifyPlayerScreens);
}
@@ -32,9 +33,19 @@ function registerDataSourceRefreshTask(options) {
if (!rssFeed) {
throw new Error('RSS feed not found.');
}
if (rssFeed.enabled === 0 || rssFeed.enabled === false) return { skipped: true, reason: 'disabled' };
return refreshRssFeed(pool, common, rssFeed.id, rssFeed.feed_url, rssFeed.item_limit, Number(payload.actorId) || null, options.notifyPlayerScreens);
}
if (sourceType === 'weather-location') {
const location = await common.fetchWeatherLocationById(pool, sourceId);
if (!location) {
throw new Error('Weather location not found.');
}
if (location.enabled === 0 || location.enabled === false) return { skipped: true, reason: 'disabled' };
return refreshWeatherLocation(pool, common, location, Number(payload.actorId) || null, options.notifyPlayerScreens);
}
throw new Error('Unsupported data source refresh task.');
});
}
@@ -9,7 +9,7 @@ const TASK = {
};
const { normalizeIntervalMs } = require('../queue');
const { refreshApiSource, refreshRssFeed } = require('../../data-source-refresh');
const { refreshApiSource, refreshRssFeed, refreshWeatherLocation } = require('../../data-source-refresh');
function registerRecurringDataSourceRefreshes(options) {
const pool = options && options.pool;
@@ -23,6 +23,7 @@ function registerRecurringDataSourceRefreshes(options) {
return (async function () {
const apiSourcesData = await common.fetchApiSourcesData(pool);
(apiSourcesData.apiSources || []).forEach(function (apiSource) {
if (apiSource.enabled === 0 || apiSource.enabled === false) return;
backgroundTaskQueue.registerRecurringTask({
key: 'api-source-refresh:' + Number(apiSource.id),
title: 'API source refresh',
@@ -41,6 +42,7 @@ function registerRecurringDataSourceRefreshes(options) {
const rssFeedsData = await common.fetchRssFeedsData(pool);
(rssFeedsData.rssFeeds || []).forEach(function (rssFeed) {
if (rssFeed.enabled === 0 || rssFeed.enabled === false) return;
backgroundTaskQueue.registerRecurringTask({
key: 'rss-feed-refresh:' + Number(rssFeed.id),
title: 'RSS feed refresh',
@@ -56,6 +58,19 @@ function registerRecurringDataSourceRefreshes(options) {
}
});
});
const weatherLocationsData = await common.fetchWeatherLocationsData(pool);
(weatherLocationsData.weatherLocations || []).forEach(function (location) {
if (location.enabled === 0 || location.enabled === false) return;
backgroundTaskQueue.registerRecurringTask({
key: 'weather-location-refresh:' + Number(location.id),
title: 'Weather location refresh',
category: TASK.category,
intervalMs: normalizeIntervalMs(location.update_interval_value, location.update_interval_unit),
metadata: { sourceType: 'weather-location', sourceId: Number(location.id), sourceName: location.name },
run: function () { return refreshWeatherLocation(pool, common, location, null, options.notifyPlayerScreens); }
});
});
})();
}
@@ -73,7 +88,7 @@ function createDataSourceTaskService(options) {
}
function buildRecurringTitle(sourceType) {
return sourceType === 'rss-feed' ? 'RSS feed refresh' : 'API source refresh';
return sourceType === 'rss-feed' ? 'RSS feed refresh' : sourceType === 'weather-location' ? 'Weather location refresh' : 'API source refresh';
}
function registerRecurringRefresh(sourceType, id, name, intervalValue, intervalUnit, run) {
@@ -122,6 +137,10 @@ function createDataSourceTaskService(options) {
return refreshRssFeed(pool, common, rssFeedId, feedUrl, itemLimit, actorId, options.notifyPlayerScreens);
}
async function refreshWeatherLocationInBackground(locationId, actorId) {
return refreshWeatherLocation(pool, common, locationId, actorId, options.notifyPlayerScreens);
}
return {
formatRecurringKey: formatRecurringKey,
buildRecurringTitle: buildRecurringTitle,
@@ -129,7 +148,8 @@ function createDataSourceTaskService(options) {
removeRecurringRefresh: removeRecurringRefresh,
getTaskStatusById: getTaskStatusById,
refreshApiSourceInBackground: refreshApiSourceInBackground,
refreshRssFeedInBackground: refreshRssFeedInBackground
refreshRssFeedInBackground: refreshRssFeedInBackground,
refreshWeatherLocationInBackground: refreshWeatherLocationInBackground
};
}
@@ -1,4 +1,5 @@
const { refreshApiSource, refreshRssFeed } = require('../../data-source-refresh');
const { refreshApiSource, refreshRssFeed, refreshWeatherLocation } = require('../../data-source-refresh');
const { normalizeIntervalMs } = require('../queue');
const TASK = {
key: 'startup-data-source-refresh',
@@ -26,23 +27,52 @@ function scheduleStartupDataSourceRefreshes(options) {
};
}
function shouldRefreshAtStartup(source) {
const lastPulledAt = source && source.last_pulled_at ? new Date(source.last_pulled_at).getTime() : NaN;
if (!Number.isFinite(lastPulledAt)) {
return true;
}
const intervalMs = normalizeIntervalMs(source.update_interval_value, source.update_interval_unit);
return Date.now() - lastPulledAt >= intervalMs;
}
return (async function () {
const apiSourcesData = await common.fetchApiSourcesData(pool);
const rssFeedsData = await common.fetchRssFeedsData(pool);
const weatherLocationsData = await common.fetchWeatherLocationsData(pool);
const startupSources = [];
(apiSourcesData.apiSources || []).forEach(function (apiSource) {
if (apiSource.enabled === 0 || apiSource.enabled === false) return;
if (!shouldRefreshAtStartup(apiSource)) {
return;
}
startupSources.push(buildStartupSource('api-source', apiSource.id, apiSource.name, function () {
return refreshApiSource(pool, common, apiSource, null, options.notifyPlayerScreens);
}));
});
(rssFeedsData.rssFeeds || []).forEach(function (rssFeed) {
if (rssFeed.enabled === 0 || rssFeed.enabled === false) return;
if (!shouldRefreshAtStartup(rssFeed)) {
return;
}
startupSources.push(buildStartupSource('rss-feed', rssFeed.id, rssFeed.name, function () {
return refreshRssFeed(pool, common, rssFeed.id, rssFeed.feed_url, rssFeed.item_limit, null, options.notifyPlayerScreens);
}));
});
(weatherLocationsData.weatherLocations || []).forEach(function (location) {
if (location.enabled === 0 || location.enabled === false) return;
if (!shouldRefreshAtStartup(location)) {
return;
}
startupSources.push(buildStartupSource('weather-location', location.id, location.name, function () {
return refreshWeatherLocation(pool, common, location, null, options.notifyPlayerScreens);
}));
});
// Stagger startup refreshes to avoid a burst against the DB/player.
startupSources.forEach(function (source, index) {
const startupDelayMs = index * staggerMs;
@@ -50,7 +80,7 @@ function scheduleStartupDataSourceRefreshes(options) {
setTimeout(function () {
backgroundTaskQueue.enqueueTask({
key: TASK.key + ':' + source.type + ':' + source.id + ':' + Date.now(),
title: source.type === 'rss-feed' ? 'RSS feed refresh' : 'API source refresh',
title: source.type === 'rss-feed' ? 'RSS feed refresh' : source.type === 'weather-location' ? 'Weather location refresh' : 'API source refresh',
category: TASK.category,
taskType: 'data-source-refresh',
metadata: {