Address review comments

This commit is contained in:
Patrick Barron 2020-05-14 17:13:45 -04:00
parent 9925742918
commit b94afc597c
20 changed files with 112 additions and 125 deletions

View File

@ -46,8 +46,6 @@ using Emby.Server.Implementations.Session;
using Emby.Server.Implementations.SocketSharp;
using Emby.Server.Implementations.TV;
using Emby.Server.Implementations.Updates;
using Jellyfin.Server.Implementations;
using Jellyfin.Server.Implementations.Activity;
using MediaBrowser.Api;
using MediaBrowser.Common;
using MediaBrowser.Common.Configuration;
@ -547,13 +545,6 @@ namespace Emby.Server.Implementations
serviceCollection.AddSingleton<IJsonSerializer, JsonSerializer>();
// TODO: properly set up scoping and switch to AddDbContextPool
serviceCollection.AddDbContext<JellyfinDb>(
options => options.UseSqlite($"Filename={Path.Combine(ApplicationPaths.DataPath, "jellyfin.db")}"),
ServiceLifetime.Transient);
serviceCollection.AddSingleton<JellyfinDbProvider>();
serviceCollection.AddSingleton(_fileSystemManager);
serviceCollection.AddSingleton<TvdbClientManager>();
@ -664,8 +655,6 @@ namespace Emby.Server.Implementations
serviceCollection.AddSingleton<IEncodingManager, MediaEncoder.EncodingManager>();
serviceCollection.AddSingleton<IActivityManager, ActivityManager>();
serviceCollection.AddSingleton<IAuthorizationContext, AuthorizationContext>();
serviceCollection.AddSingleton<ISessionContext, SessionContext>();

View File

@ -193,12 +193,6 @@ namespace Emby.Server.Implementations.Configuration
changed = true;
}
if (!config.CameraUploadUpgraded)
{
config.CameraUploadUpgraded = true;
changed = true;
}
if (!config.CollectionsUpgraded)
{
config.CollectionsUpgraded = true;

View File

@ -9,7 +9,6 @@
<ProjectReference Include="..\Emby.Naming\Emby.Naming.csproj" />
<ProjectReference Include="..\Emby.Notifications\Emby.Notifications.csproj" />
<ProjectReference Include="..\Jellyfin.Api\Jellyfin.Api.csproj" />
<ProjectReference Include="..\Jellyfin.Server.Implementations\Jellyfin.Server.Implementations.csproj" />
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
<ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj" />
<ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
@ -51,7 +50,7 @@
</ItemGroup>
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>netstandard2.1</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

View File

@ -5,34 +5,18 @@ using Microsoft.Extensions.Logging;
namespace Jellyfin.Data.Entities
{
public partial class ActivityLog
/// <summary>
/// An entity referencing an activity log entry.
/// </summary>
public partial class ActivityLog : ISavingChanges
{
partial void Init();
/// <summary>
/// Default constructor. Protected due to required properties, but present because EF needs it.
/// Initializes a new instance of the <see cref="ActivityLog"/> class.
/// Public constructor with required data.
/// </summary>
protected ActivityLog()
{
Init();
}
/// <summary>
/// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
/// </summary>
public static ActivityLog CreateActivityLogUnsafe()
{
return new ActivityLog();
}
/// <summary>
/// Public constructor with required data
/// </summary>
/// <param name="name"></param>
/// <param name="type"></param>
/// <param name="userId"></param>
/// <param name="datecreated"></param>
/// <param name="logSeverity"></param>
/// <param name="name">The name.</param>
/// <param name="type">The type.</param>
/// <param name="userId">The user id.</param>
public ActivityLog(string name, string type, Guid userId)
{
if (string.IsNullOrEmpty(name))
@ -54,14 +38,21 @@ namespace Jellyfin.Data.Entities
Init();
}
/// <summary>
/// Initializes a new instance of the <see cref="ActivityLog"/> class.
/// Default constructor. Protected due to required properties, but present because EF needs it.
/// </summary>
protected ActivityLog()
{
Init();
}
/// <summary>
/// Static create function (for use in LINQ queries, etc.)
/// </summary>
/// <param name="name"></param>
/// <param name="type"></param>
/// <param name="userId"></param>
/// <param name="datecreated"></param>
/// <param name="logseverity"></param>
/// <param name="name">The name.</param>
/// <param name="type">The type.</param>
/// <param name="userId">The user's id.</param>
public static ActivityLog Create(string name, string type, Guid userId)
{
return new ActivityLog(name, type, userId);
@ -72,7 +63,8 @@ namespace Jellyfin.Data.Entities
*************************************************************************/
/// <summary>
/// Identity, Indexed, Required
/// Gets the identity of this instance.
/// This is the key in the backing database.
/// </summary>
[Key]
[Required]
@ -80,7 +72,8 @@ namespace Jellyfin.Data.Entities
public int Id { get; protected set; }
/// <summary>
/// Required, Max length = 512
/// Gets or sets the name.
/// Required, Max length = 512.
/// </summary>
[Required]
[MaxLength(512)]
@ -88,21 +81,24 @@ namespace Jellyfin.Data.Entities
public string Name { get; set; }
/// <summary>
/// Max length = 512
/// Gets or sets the overview.
/// Max length = 512.
/// </summary>
[MaxLength(512)]
[StringLength(512)]
public string Overview { get; set; }
/// <summary>
/// Max length = 512
/// Gets or sets the short overview.
/// Max length = 512.
/// </summary>
[MaxLength(512)]
[StringLength(512)]
public string ShortOverview { get; set; }
/// <summary>
/// Required, Max length = 256
/// Gets or sets the type.
/// Required, Max length = 256.
/// </summary>
[Required]
[MaxLength(256)]
@ -110,41 +106,48 @@ namespace Jellyfin.Data.Entities
public string Type { get; set; }
/// <summary>
/// Required
/// Gets or sets the user id.
/// Required.
/// </summary>
[Required]
public Guid UserId { get; set; }
/// <summary>
/// Max length = 256
/// Gets or sets the item id.
/// Max length = 256.
/// </summary>
[MaxLength(256)]
[StringLength(256)]
public string ItemId { get; set; }
/// <summary>
/// Required
/// Gets or sets the date created. This should be in UTC.
/// Required.
/// </summary>
[Required]
public DateTime DateCreated { get; set; }
/// <summary>
/// Required
/// Gets or sets the log severity. Default is <see cref="LogLevel.Trace"/>.
/// Required.
/// </summary>
[Required]
public LogLevel LogSeverity { get; set; }
/// <summary>
/// Gets or sets the row version.
/// Required, ConcurrencyToken.
/// </summary>
[ConcurrencyCheck]
[Required]
public uint RowVersion { get; set; }
partial void Init();
/// <inheritdoc />
public void OnSavingChanges()
{
RowVersion++;
}
}
}

View File

@ -17,14 +17,10 @@
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>

View File

@ -50,31 +50,31 @@ namespace Jellyfin.Server.Implementations.Activity
/// <inheritdoc/>
public QueryResult<ActivityLogEntry> GetPagedResult(
Func<IQueryable<ActivityLog>, IEnumerable<ActivityLog>> func,
Func<IQueryable<ActivityLog>, IQueryable<ActivityLog>> func,
int? startIndex,
int? limit)
{
using var dbContext = _provider.CreateContext();
var result = func.Invoke(dbContext.ActivityLogs).AsQueryable();
var query = func(dbContext.ActivityLogs).OrderByDescending(entry => entry.DateCreated).AsQueryable();
if (startIndex.HasValue)
{
result = result.Where(entry => entry.Id >= startIndex.Value);
query = query.Skip(startIndex.Value);
}
if (limit.HasValue)
{
result = result.OrderByDescending(entry => entry.DateCreated).Take(limit.Value);
query = query.Take(limit.Value);
}
// This converts the objects from the new database model to the old for compatibility with the existing API.
var list = result.Select(entry => ConvertToOldModel(entry)).ToList();
var list = query.AsEnumerable().Select(ConvertToOldModel).ToList();
return new QueryResult<ActivityLogEntry>()
return new QueryResult<ActivityLogEntry>
{
Items = list,
TotalRecordCount = list.Count
TotalRecordCount = dbContext.ActivityLogs.Count()
};
}

View File

@ -25,6 +25,14 @@
<Compile Remove="Migrations\20200430214405_InitialSchema.Designer.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Jellyfin.Data\Jellyfin.Data.csproj" />
<ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />

View File

@ -110,7 +110,7 @@ namespace Jellyfin.Server.Implementations
foreach (var entity in ChangeTracker.Entries().Where(e => e.State == EntityState.Modified))
{
var saveEntity = entity.Entity as ISavingChanges;
saveEntity.OnSavingChanges();
saveEntity?.OnSavingChanges();
}
return base.SaveChanges();

View File

@ -27,7 +27,7 @@ namespace Jellyfin.Server.Implementations
/// <returns>The newly created context.</returns>
public JellyfinDb CreateContext()
{
return _serviceProvider.GetService<JellyfinDb>();
return _serviceProvider.GetRequiredService<JellyfinDb>();
}
}
}

View File

@ -1,5 +1,4 @@
#pragma warning disable CS1591
#pragma warning disable SA1601
#pragma warning disable CS1591
// <auto-generated />
using System;
@ -12,8 +11,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace Jellyfin.Server.Implementations.Migrations
{
[DbContext(typeof(JellyfinDb))]
[Migration("20200502231229_InitialSchema")]
partial class InitialSchema
[Migration("20200514181226_AddActivityLog")]
partial class AddActivityLog
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
@ -65,7 +64,7 @@ namespace Jellyfin.Server.Implementations.Migrations
b.HasKey("Id");
b.ToTable("ActivityLog");
b.ToTable("ActivityLogs");
});
#pragma warning restore 612, 618
}

View File

@ -1,4 +1,4 @@
#pragma warning disable CS1591
#pragma warning disable CS1591
#pragma warning disable SA1601
using System;
@ -6,7 +6,7 @@ using Microsoft.EntityFrameworkCore.Migrations;
namespace Jellyfin.Server.Implementations.Migrations
{
public partial class InitialSchema : Migration
public partial class AddActivityLog : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
@ -14,7 +14,7 @@ namespace Jellyfin.Server.Implementations.Migrations
name: "jellyfin");
migrationBuilder.CreateTable(
name: "ActivityLog",
name: "ActivityLogs",
schema: "jellyfin",
columns: table => new
{
@ -32,14 +32,14 @@ namespace Jellyfin.Server.Implementations.Migrations
},
constraints: table =>
{
table.PrimaryKey("PK_ActivityLog", x => x.Id);
table.PrimaryKey("PK_ActivityLogs", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "ActivityLog",
name: "ActivityLogs",
schema: "jellyfin");
}
}

View File

@ -1,6 +1,3 @@
#pragma warning disable CS1591
#pragma warning disable SA1601
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
@ -15,7 +12,9 @@ namespace Jellyfin.Server.Implementations.Migrations
public JellyfinDb CreateDbContext(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder<JellyfinDb>();
optionsBuilder.UseSqlite("Data Source=jellyfin.db");
optionsBuilder.UseSqlite(
"Data Source=jellyfin.db",
opt => opt.MigrationsAssembly("Jellyfin.Migrations"));
return new JellyfinDb(optionsBuilder.Options);
}

View File

@ -1,9 +1,7 @@
// <auto-generated />
using System;
using Jellyfin.Server.Implementations;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace Jellyfin.Server.Implementations.Migrations
{
@ -60,7 +58,7 @@ namespace Jellyfin.Server.Implementations.Migrations
b.HasKey("Id");
b.ToTable("ActivityLog");
b.ToTable("ActivityLogs");
});
#pragma warning restore 612, 618
}

View File

@ -1,12 +1,17 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Emby.Drawing;
using Emby.Server.Implementations;
using Jellyfin.Drawing.Skia;
using Jellyfin.Server.Implementations;
using Jellyfin.Server.Implementations.Activity;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Model.Activity;
using MediaBrowser.Model.IO;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
@ -56,6 +61,15 @@ namespace Jellyfin.Server
Logger.LogWarning($"Skia not available. Will fallback to {nameof(NullImageEncoder)}.");
}
// TODO: Set up scoping and use AddDbContextPool
serviceCollection.AddDbContext<JellyfinDb>(
options => options.UseSqlite($"Filename={Path.Combine(ApplicationPaths.DataPath, "jellyfin.db")}"),
ServiceLifetime.Transient);
serviceCollection.AddSingleton<JellyfinDbProvider>();
serviceCollection.AddSingleton<IActivityManager, ActivityManager>();
base.RegisterServices(serviceCollection);
}

View File

@ -13,9 +13,6 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Nullable>enable</Nullable>
<!-- Used for generating migrations for EF Core -->
<GenerateRuntimeConfigurationFiles>True</GenerateRuntimeConfigurationFiles>
</PropertyGroup>
<ItemGroup>
@ -44,10 +41,6 @@
<ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.7.82" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.3" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.3" />
<PackageReference Include="prometheus-net" Version="3.5.0" />
@ -67,6 +60,7 @@
<ProjectReference Include="..\Emby.Drawing\Emby.Drawing.csproj" />
<ProjectReference Include="..\Emby.Server.Implementations\Emby.Server.Implementations.csproj" />
<ProjectReference Include="..\Jellyfin.Drawing.Skia\Jellyfin.Drawing.Skia.csproj" />
<ProjectReference Include="..\Jellyfin.Server.Implementations\Jellyfin.Server.Implementations.csproj" />
</ItemGroup>
</Project>

View File

@ -1,3 +1,7 @@
using System;
using System.Globalization;
using System.Linq;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Activity;
@ -47,7 +51,14 @@ namespace MediaBrowser.Api.System
public object Get(GetActivityLogs request)
{
var result = _activityManager.GetPagedResult(request.StartIndex, request.Limit);
DateTime? minDate = string.IsNullOrWhiteSpace(request.MinDate) ?
(DateTime?)null :
DateTime.Parse(request.MinDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
var filterFunc = new Func<IQueryable<ActivityLog>, IQueryable<ActivityLog>>(
entries => entries.Where(entry => entry.DateCreated >= minDate));
var result = _activityManager.GetPagedResult(filterFunc, request.StartIndex, request.Limit);
return ToOptimizedResult(result);
}

View File

@ -1,7 +1,6 @@
#pragma warning disable CS1591
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
@ -21,7 +20,7 @@ namespace MediaBrowser.Model.Activity
QueryResult<ActivityLogEntry> GetPagedResult(int? startIndex, int? limit);
QueryResult<ActivityLogEntry> GetPagedResult(
Func<IQueryable<ActivityLog>, IEnumerable<ActivityLog>> func,
Func<IQueryable<ActivityLog>, IQueryable<ActivityLog>> func,
int? startIndex,
int? limit);
}

View File

@ -79,8 +79,6 @@ namespace MediaBrowser.Model.Configuration
public bool EnableRemoteAccess { get; set; }
public bool CameraUploadUpgraded { get; set; }
public bool CollectionsUpgraded { get; set; }
/// <summary>

View File

@ -0,0 +1,9 @@
#pragma warning disable CS1591
namespace MediaBrowser.Model.Devices
{
public class DeviceOptions
{
public string CustomName { get; set; }
}
}

View File

@ -1,23 +0,0 @@
#pragma warning disable CS1591
using System;
namespace MediaBrowser.Model.Devices
{
public class DevicesOptions
{
public string[] EnabledCameraUploadDevices { get; set; }
public string CameraUploadPath { get; set; }
public bool EnableCameraUploadSubfolders { get; set; }
public DevicesOptions()
{
EnabledCameraUploadDevices = Array.Empty<string>();
}
}
public class DeviceOptions
{
public string CustomName { get; set; }
}
}