WIP: Phase 3B playback engine handoff

This commit is contained in:
Media
2026-08-16 21:50:19 -05:00
parent e2ecdc97e2
commit 68273d457f
16 changed files with 3506 additions and 244 deletions
+44 -5
View File
@@ -6,6 +6,8 @@ const {
const { createAssetRouter } = require("./assets/routes");
const { createMediaRouter } = require("./assets/media-routes");
const { createAssetService } = require("./assets/service");
const { createPlaybackService } = require("./playback");
const { createPlaybackRouter } = require("./playback/routes");
const {
createPlaylistRouter,
createPlaylistService,
@@ -13,10 +15,10 @@ const {
const { createSettingsRouter } = require("./settings/routes");
const { createSettingsService } = require("./settings/service");
function safeNotifier(notifier, logger) {
function safeNotifier(notifier, logger, failureMessage) {
const warn = (error) => {
try {
logger?.warn?.("Playlist invalidation notification failed", error);
logger?.warn?.(failureMessage, error);
} catch {
// A best-effort notification or warning must not undo a database commit.
}
@@ -40,10 +42,35 @@ function createApp({
migrations,
now = Date.now,
onPlaylistsChanged = () => {},
playbackService: suppliedPlaybackService,
storage,
}) {
const app = express();
const notifyPlaylistsChanged = safeNotifier(onPlaylistsChanged, logger);
const notifyPlaylistsChanged = safeNotifier(
onPlaylistsChanged,
logger,
"Playlist invalidation notification failed",
);
const playbackService =
suppliedPlaybackService ||
createPlaybackService({
database,
now,
onActivationChanged: notifyPlaylistsChanged,
});
if (!suppliedPlaybackService) {
playbackService.initialize();
}
const reconcilePlaybackDomain = (change) =>
playbackService.domainChanged(change);
const reconcileBeforeDomainChange = () =>
playbackService.reconcile("before_domain_change");
const notifyPlaylistMutation = (change) => {
reconcilePlaybackDomain(change);
const publicChange = { ...change };
delete publicChange.invalidBoundaryChanged;
notifyPlaylistsChanged(publicChange);
};
const settingsService = createSettingsService(database);
const assetService = createAssetService({
database,
@@ -53,8 +80,10 @@ function createApp({
const playlistService = createPlaylistService({
database,
now,
onChanged: notifyPlaylistsChanged,
onBeforeChange: reconcileBeforeDomainChange,
onChanged: notifyPlaylistMutation,
});
app.locals.playbackService = playbackService;
app.disable("x-powered-by");
app.set("trust proxy", config.trustProxy);
@@ -85,18 +114,28 @@ function createApp({
app.use(
"/api/settings",
createSettingsRouter(settingsService, {
onBeforePlaybackDomainChange: reconcileBeforeDomainChange,
onPlaylistsChanged: notifyPlaylistsChanged,
onPlaybackDomainChanged: reconcilePlaybackDomain,
}),
);
app.use(
"/api/assets",
createAssetRouter({
assetService,
onBeforePlaybackDomainChange: reconcileBeforeDomainChange,
onPlaylistsChanged: notifyPlaylistsChanged,
onPlaybackDomainChanged: reconcilePlaybackDomain,
processingConfig: config.processing,
}),
);
app.use("/api/playlists", createPlaylistRouter(playlistService));
app.use(
"/api/playlists",
createPlaylistRouter(playlistService, {
playbackService,
}),
);
app.use("/api/playback", createPlaybackRouter(playbackService));
app.use("/media", createMediaRouter(assetService));
app.use((request, response) => {