Refactor PostgreSQL provider: multi-schema & async prep
- Refactor migrations and provider to use multiple PostgreSQL schemas, each matching a legacy SQLite database (activitylog, authentication, displaypreferences, library, users). - All tables, foreign keys, and indexes are now schema-qualified; Down migration drops tables by schema. - Provider ensures schemas exist before migrations; entities are mapped to correct schemas in OnModelCreating. - Add support for max-pool-size, min-pool-size, and multiplexing connection options; update logging accordingly. - VACUUM ANALYZE now runs per schema during scheduled optimization. - TruncateAllTablesAsync now truncates tables with schema qualification. - README updated with schema structure, new options, and multiplexing warnings. - CacheDecorator now calls async repository methods using .GetAwaiter().GetResult(), with documentation. - Lays groundwork for full async/await and multiplexing support in the database layer.
This commit is contained in:
@@ -24,6 +24,15 @@ public interface IChapterManager
|
||||
/// <param name="chapters">The set of chapters.</param>
|
||||
void SaveChapters(Video video, IReadOnlyList<ChapterInfo> chapters);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the chapters asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="video">The video.</param>
|
||||
/// <param name="chapters">The set of chapters.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
Task SaveChaptersAsync(Video video, IReadOnlyList<ChapterInfo> chapters, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a single chapter of a BaseItem on a specific index.
|
||||
/// </summary>
|
||||
@@ -32,6 +41,15 @@ public interface IChapterManager
|
||||
/// <returns>A chapter instance.</returns>
|
||||
ChapterInfo? GetChapter(Guid baseItemId, int index);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a single chapter of a BaseItem on a specific index asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="baseItemId">The BaseItems id.</param>
|
||||
/// <param name="index">The index of that chapter.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>A chapter instance.</returns>
|
||||
Task<ChapterInfo?> GetChapterAsync(Guid baseItemId, int index, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all chapters associated with the baseItem.
|
||||
/// </summary>
|
||||
@@ -39,6 +57,14 @@ public interface IChapterManager
|
||||
/// <returns>A readonly list of chapter instances.</returns>
|
||||
IReadOnlyList<ChapterInfo> GetChapters(Guid baseItemId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all chapters associated with the baseItem asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="baseItemId">The BaseItems id.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>A readonly list of chapter instances.</returns>
|
||||
Task<IReadOnlyList<ChapterInfo>> GetChaptersAsync(Guid baseItemId, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes the chapter images.
|
||||
/// </summary>
|
||||
|
||||
@@ -1145,8 +1145,16 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
Id = item.Id.ToString("N", CultureInfo.InvariantCulture),
|
||||
Protocol = protocol ?? MediaProtocol.File,
|
||||
MediaStreams = MediaSourceManager.GetMediaStreams(item.Id),
|
||||
MediaAttachments = MediaSourceManager.GetMediaAttachments(item.Id),
|
||||
// Note: Using GetAwaiter().GetResult() here as this method is synchronous by design.
|
||||
// TODO: Consider making GetVersionInfo async in future refactoring.
|
||||
MediaStreams = MediaSourceManager
|
||||
.GetMediaStreamsAsync(item.Id, CancellationToken.None)
|
||||
.GetAwaiter()
|
||||
.GetResult(),
|
||||
MediaAttachments = MediaSourceManager
|
||||
.GetMediaAttachmentsAsync(item.Id, CancellationToken.None)
|
||||
.GetAwaiter()
|
||||
.GetResult(),
|
||||
Name = GetMediaSourceName(item),
|
||||
Path = enablePathSubstitution ? GetMappedPath(item, itemPath, protocol) : itemPath,
|
||||
RunTimeTicks = item.RunTimeTicks,
|
||||
|
||||
@@ -16,11 +16,12 @@ using Jellyfin.MediaEncoding.Keyframes;
|
||||
public interface IKeyframeManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the keyframe data.
|
||||
/// Gets the keyframe data asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="itemId">The item id.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The keyframe data.</returns>
|
||||
IReadOnlyList<KeyframeData> GetKeyframeData(Guid itemId);
|
||||
Task<IReadOnlyList<KeyframeData>> GetKeyframeDataAsync(Guid itemId, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the keyframe data.
|
||||
|
||||
@@ -42,6 +42,22 @@ namespace MediaBrowser.Controller.Library
|
||||
/// <returns>IEnumerable<MediaStream>.</returns>
|
||||
IReadOnlyList<MediaStream> GetMediaStreams(MediaStreamQuery query);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the media streams asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="itemId">The item identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>IReadOnlyList<MediaStream>.</returns>
|
||||
Task<IReadOnlyList<MediaStream>> GetMediaStreamsAsync(Guid itemId, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the media streams asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>IReadOnlyList<MediaStream>.</returns>
|
||||
Task<IReadOnlyList<MediaStream>> GetMediaStreamsAsync(MediaStreamQuery query, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the media attachments.
|
||||
/// </summary>
|
||||
@@ -56,6 +72,22 @@ namespace MediaBrowser.Controller.Library
|
||||
/// <returns>IEnumerable<MediaAttachment>.</returns>
|
||||
IReadOnlyList<MediaAttachment> GetMediaAttachments(MediaAttachmentQuery query);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the media attachments asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="itemId">The item identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>IReadOnlyList<MediaAttachment>.</returns>
|
||||
Task<IReadOnlyList<MediaAttachment>> GetMediaAttachmentsAsync(Guid itemId, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the media attachments asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>IReadOnlyList<MediaAttachment>.</returns>
|
||||
Task<IReadOnlyList<MediaAttachment>> GetMediaAttachmentsAsync(MediaAttachmentQuery query, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the playback media sources.
|
||||
/// </summary>
|
||||
|
||||
@@ -24,24 +24,28 @@ public interface IChapterRepository
|
||||
Task DeleteChaptersAsync(Guid itemId, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the chapters.
|
||||
/// Saves the chapters asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="itemId">The item.</param>
|
||||
/// <param name="chapters">The set of chapters.</param>
|
||||
void SaveChapters(Guid itemId, IReadOnlyList<ChapterInfo> chapters);
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
Task SaveChaptersAsync(Guid itemId, IReadOnlyList<ChapterInfo> chapters, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all chapters associated with the baseItem.
|
||||
/// Gets all chapters associated with the baseItem asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="baseItemId">The BaseItems id.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>A readonly list of chapter instances.</returns>
|
||||
IReadOnlyList<ChapterInfo> GetChapters(Guid baseItemId);
|
||||
Task<IReadOnlyList<ChapterInfo>> GetChaptersAsync(Guid baseItemId, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a single chapter of a BaseItem on a specific index.
|
||||
/// Gets a single chapter of a BaseItem on a specific index asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="baseItemId">The BaseItems id.</param>
|
||||
/// <param name="index">The index of that chapter.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>A chapter instance.</returns>
|
||||
ChapterInfo? GetChapter(Guid baseItemId, int index);
|
||||
Task<ChapterInfo?> GetChapterAsync(Guid baseItemId, int index, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
@@ -61,6 +61,14 @@ public interface IItemRepository
|
||||
/// <returns>QueryResult<BaseItem>.</returns>
|
||||
QueryResult<BaseItem> GetItems(InternalItemsQuery filter);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the items asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="filter">The query.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>QueryResult<BaseItem>.</returns>
|
||||
Task<QueryResult<BaseItem>> GetItemsAsync(InternalItemsQuery filter, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the item ids list.
|
||||
/// </summary>
|
||||
@@ -68,6 +76,14 @@ public interface IItemRepository
|
||||
/// <returns>List<Guid>.</returns>
|
||||
IReadOnlyList<Guid> GetItemIdsList(InternalItemsQuery filter);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the item ids list asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="filter">The query.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>List<Guid>.</returns>
|
||||
Task<IReadOnlyList<Guid>> GetItemIdsListAsync(InternalItemsQuery filter, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the item list.
|
||||
/// </summary>
|
||||
@@ -75,6 +91,14 @@ public interface IItemRepository
|
||||
/// <returns>List<BaseItem>.</returns>
|
||||
IReadOnlyList<BaseItem> GetItemList(InternalItemsQuery filter);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the item list asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="filter">The query.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>List<BaseItem>.</returns>
|
||||
Task<IReadOnlyList<BaseItem>> GetItemListAsync(InternalItemsQuery filter, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the item list. Used mainly by the Latest api endpoint.
|
||||
/// </summary>
|
||||
@@ -98,8 +122,24 @@ public interface IItemRepository
|
||||
|
||||
int GetCount(InternalItemsQuery filter);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the count of items asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="filter">The query.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The count.</returns>
|
||||
Task<int> GetCountAsync(InternalItemsQuery filter, CancellationToken cancellationToken = default);
|
||||
|
||||
ItemCounts GetItemCounts(InternalItemsQuery filter);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the item counts asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="filter">The query.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The item counts.</returns>
|
||||
Task<ItemCounts> GetItemCountsAsync(InternalItemsQuery filter, CancellationToken cancellationToken = default);
|
||||
|
||||
QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetGenres(InternalItemsQuery filter);
|
||||
|
||||
QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetMusicGenres(InternalItemsQuery filter);
|
||||
|
||||
@@ -16,11 +16,12 @@ using Jellyfin.MediaEncoding.Keyframes;
|
||||
public interface IKeyframeRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the keyframe data.
|
||||
/// Gets the keyframe data asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="itemId">The item id.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The keyframe data.</returns>
|
||||
IReadOnlyList<KeyframeData> GetKeyframeData(Guid itemId);
|
||||
Task<IReadOnlyList<KeyframeData>> GetKeyframeDataAsync(Guid itemId, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the keyframe data.
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Persistence;
|
||||
@@ -16,17 +17,19 @@ namespace MediaBrowser.Controller.Persistence;
|
||||
public interface IMediaAttachmentRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the media attachments.
|
||||
/// Gets the media attachments asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="filter">The query.</param>
|
||||
/// <returns>IEnumerable{MediaAttachment}.</returns>
|
||||
IReadOnlyList<MediaAttachment> GetMediaAttachments(MediaAttachmentQuery filter);
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>IReadOnlyList{MediaAttachment}.</returns>
|
||||
Task<IReadOnlyList<MediaAttachment>> GetMediaAttachmentsAsync(MediaAttachmentQuery filter, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the media attachments.
|
||||
/// Saves the media attachments asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <param name="attachments">The attachments.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
void SaveMediaAttachments(Guid id, IReadOnlyList<MediaAttachment> attachments, CancellationToken cancellationToken);
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
Task SaveMediaAttachmentsAsync(Guid id, IReadOnlyList<MediaAttachment> attachments, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Persistence;
|
||||
@@ -19,17 +20,19 @@ namespace MediaBrowser.Controller.Persistence;
|
||||
public interface IMediaStreamRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the media streams.
|
||||
/// Gets the media streams asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="filter">The query.</param>
|
||||
/// <returns>IEnumerable{MediaStream}.</returns>
|
||||
IReadOnlyList<MediaStream> GetMediaStreams(MediaStreamQuery filter);
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>IReadOnlyList{MediaStream}.</returns>
|
||||
Task<IReadOnlyList<MediaStream>> GetMediaStreamsAsync(MediaStreamQuery filter, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the media streams.
|
||||
/// Saves the media streams asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <param name="streams">The streams.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
void SaveMediaStreams(Guid id, IReadOnlyList<MediaStream> streams, CancellationToken cancellationToken);
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
Task SaveMediaStreamsAsync(Guid id, IReadOnlyList<MediaStream> streams, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Persistence;
|
||||
@@ -21,6 +23,14 @@ public interface IPeopleRepository
|
||||
/// <returns>The list of people matching the filter.</returns>
|
||||
IReadOnlyList<PersonInfo> GetPeople(InternalPeopleQuery filter);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the people asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="filter">The query.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The list of people matching the filter.</returns>
|
||||
Task<IReadOnlyList<PersonInfo>> GetPeopleAsync(InternalPeopleQuery filter, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the people.
|
||||
/// </summary>
|
||||
@@ -28,10 +38,27 @@ public interface IPeopleRepository
|
||||
/// <param name="people">The people.</param>
|
||||
void UpdatePeople(Guid itemId, IReadOnlyList<PersonInfo> people);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the people asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="itemId">The item identifier.</param>
|
||||
/// <param name="people">The people.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
Task UpdatePeopleAsync(Guid itemId, IReadOnlyList<PersonInfo> people, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the people names.
|
||||
/// </summary>
|
||||
/// <param name="filter">The query.</param>
|
||||
/// <returns>The list of people names matching the filter.</returns>
|
||||
IReadOnlyList<string> GetPeopleNames(InternalPeopleQuery filter);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the people names asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="filter">The query.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The list of people names matching the filter.</returns>
|
||||
Task<IReadOnlyList<string>> GetPeopleNamesAsync(InternalPeopleQuery filter, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user