aboutsummaryrefslogtreecommitdiff
path: root/src/Jellyfin.Database/Jellyfin.Database.Implementations
diff options
context:
space:
mode:
authorpokreman06 <112423673+pokreman06@users.noreply.github.com>2025-10-02 11:07:05 -0600
committerGitHub <noreply@github.com>2025-10-02 11:07:05 -0600
commit0b4854c5eff7c862d05f43048e08dd3a1a25efaa (patch)
treea4c417af05deef7878ab9342c85c506ad22e1ced /src/Jellyfin.Database/Jellyfin.Database.Implementations
parentd6a1c8413c6a213f6e579246c1b85aad9b028b3a (diff)
parent0f42aa892e0a7fe2ac4e680e7647515af0909e5e (diff)
Merge branch 'jellyfin:master' into master
Diffstat (limited to 'src/Jellyfin.Database/Jellyfin.Database.Implementations')
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemEntity.cs4
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Locking/OptimisticLockBehavior.cs24
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemConfiguration.cs1
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PeopleBaseItemMapConfiguration.cs2
4 files changed, 28 insertions, 3 deletions
diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemEntity.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemEntity.cs
index a09a96317c..d58466e5ca 100644
--- a/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemEntity.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemEntity.cs
@@ -146,6 +146,8 @@ public class BaseItemEntity
public Guid? ParentId { get; set; }
+ public BaseItemEntity? DirectParent { get; set; }
+
public Guid? TopParentId { get; set; }
public Guid? SeasonId { get; set; }
@@ -168,6 +170,8 @@ public class BaseItemEntity
public ICollection<AncestorId>? Children { get; set; }
+ public ICollection<BaseItemEntity>? DirectChildren { get; set; }
+
public ICollection<BaseItemMetadataField>? LockedFields { get; set; }
public ICollection<BaseItemTrailerType>? TrailerTypes { get; set; }
diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/Locking/OptimisticLockBehavior.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Locking/OptimisticLockBehavior.cs
index 9395b2e2dd..b90a2e056f 100644
--- a/src/Jellyfin.Database/Jellyfin.Database.Implementations/Locking/OptimisticLockBehavior.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Locking/OptimisticLockBehavior.cs
@@ -1,6 +1,7 @@
using System;
using System.Data.Common;
using System.Linq;
+using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
@@ -28,15 +29,34 @@ public class OptimisticLockBehavior : IEntityFrameworkCoreLockingBehavior
TimeSpan[] sleepDurations = [
TimeSpan.FromMilliseconds(50),
TimeSpan.FromMilliseconds(50),
+ TimeSpan.FromMilliseconds(50),
+ TimeSpan.FromMilliseconds(50),
+ TimeSpan.FromMilliseconds(250),
TimeSpan.FromMilliseconds(250),
+ TimeSpan.FromMilliseconds(250),
+ TimeSpan.FromMilliseconds(150),
+ TimeSpan.FromMilliseconds(150),
TimeSpan.FromMilliseconds(150),
TimeSpan.FromMilliseconds(500),
+ TimeSpan.FromMilliseconds(150),
TimeSpan.FromMilliseconds(500),
+ TimeSpan.FromMilliseconds(150),
TimeSpan.FromSeconds(3)
];
+
+ Func<int, Context, TimeSpan> backoffProvider = (index, context) =>
+ {
+ var backoff = sleepDurations[index];
+ return backoff + TimeSpan.FromMilliseconds(RandomNumberGenerator.GetInt32(0, (int)(backoff.TotalMilliseconds * .5)));
+ };
+
_logger = logger;
- _writePolicy = Policy.HandleInner<Exception>(e => e.Message.Contains("database is locked", StringComparison.InvariantCultureIgnoreCase)).WaitAndRetry(sleepDurations, RetryHandle);
- _writeAsyncPolicy = Policy.HandleInner<Exception>(e => e.Message.Contains("database is locked", StringComparison.InvariantCultureIgnoreCase)).WaitAndRetryAsync(sleepDurations, RetryHandle);
+ _writePolicy = Policy
+ .HandleInner<Exception>(e => e.Message.Contains("database is locked", StringComparison.InvariantCultureIgnoreCase))
+ .WaitAndRetry(sleepDurations.Length, backoffProvider, RetryHandle);
+ _writeAsyncPolicy = Policy
+ .HandleInner<Exception>(e => e.Message.Contains("database is locked", StringComparison.InvariantCultureIgnoreCase))
+ .WaitAndRetryAsync(sleepDurations.Length, backoffProvider, RetryHandle);
void RetryHandle(Exception exception, TimeSpan timespan, int retryNo, Context context)
{
diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemConfiguration.cs
index bcf458abd5..6fccfd976d 100644
--- a/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemConfiguration.cs
@@ -27,6 +27,7 @@ public class BaseItemConfiguration : IEntityTypeConfiguration<BaseItemEntity>
builder.HasMany(e => e.Provider);
builder.HasMany(e => e.Parents);
builder.HasMany(e => e.Children);
+ builder.HasMany(e => e.DirectChildren).WithOne(e => e.DirectParent).HasForeignKey(e => e.ParentId).OnDelete(DeleteBehavior.Cascade);
builder.HasMany(e => e.LockedFields);
builder.HasMany(e => e.TrailerTypes);
builder.HasMany(e => e.Images);
diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PeopleBaseItemMapConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PeopleBaseItemMapConfiguration.cs
index 5e3ab44433..f7694aeda0 100644
--- a/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PeopleBaseItemMapConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PeopleBaseItemMapConfiguration.cs
@@ -12,7 +12,7 @@ public class PeopleBaseItemMapConfiguration : IEntityTypeConfiguration<PeopleBas
/// <inheritdoc/>
public void Configure(EntityTypeBuilder<PeopleBaseItemMap> builder)
{
- builder.HasKey(e => new { e.ItemId, e.PeopleId });
+ builder.HasKey(e => new { e.ItemId, e.PeopleId, e.Role });
builder.HasIndex(e => new { e.ItemId, e.SortOrder });
builder.HasIndex(e => new { e.ItemId, e.ListOrder });
builder.HasOne(e => e.Item);