Hopefully provide a fix now for #2998

Theory is that the refresh metadata was using stale data and then overriding the availbility that just happened on that media item.
pull/3211/head
tidusjar 5 years ago
parent 7a72496c78
commit 1286c40f82

@ -190,7 +190,6 @@ namespace Ombi.DependencyInjection
services.AddTransient<IEmbyAvaliabilityChecker, EmbyAvaliabilityChecker>();
services.AddTransient<IPlexEpisodeSync, PlexEpisodeSync>();
services.AddTransient<IPlexAvailabilityChecker, PlexAvailabilityChecker>();
services.AddTransient<IJobSetup, JobSetup>();
services.AddTransient<IRadarrSync, RadarrSync>();
services.AddTransient<ISonarrSync, SonarrSync>();
services.AddTransient<IOmbiAutomaticUpdater, OmbiAutomaticUpdater>();

@ -0,0 +1,7 @@
namespace Ombi.Schedule
{
public class JobDataKeys
{
public const string RecentlyAddedSearch = "recentlyAddedSearch";
}
}

@ -1,117 +0,0 @@
using System;
using Hangfire;
using Ombi.Core.Settings;
using Ombi.Schedule.Jobs;
using Ombi.Schedule.Jobs.Couchpotato;
using Ombi.Schedule.Jobs.Emby;
using Ombi.Schedule.Jobs.Lidarr;
using Ombi.Schedule.Jobs.Ombi;
using Ombi.Schedule.Jobs.Plex;
using Ombi.Schedule.Jobs.Plex.Interfaces;
using Ombi.Schedule.Jobs.Radarr;
using Ombi.Schedule.Jobs.SickRage;
using Ombi.Schedule.Jobs.Sonarr;
using Ombi.Settings.Settings.Models;
namespace Ombi.Schedule
{
public class JobSetup : IJobSetup, IDisposable
{
public JobSetup(IPlexContentSync plexContentSync, IRadarrSync radarrSync,
IOmbiAutomaticUpdater updater, IEmbyContentSync embySync, IPlexUserImporter userImporter,
IEmbyUserImporter embyUserImporter, ISonarrSync cache, ICouchPotatoSync cpCache,
ISettingsService<JobSettings> jobsettings, ISickRageSync srSync, IRefreshMetadata refresh,
INewsletterJob newsletter, IPlexRecentlyAddedSync recentlyAddedPlex, ILidarrArtistSync artist,
IIssuesPurge purge, IResendFailedRequests resender, IMediaDatabaseRefresh dbRefresh)
{
_plexContentSync = plexContentSync;
_radarrSync = radarrSync;
_updater = updater;
_embyContentSync = embySync;
_plexUserImporter = userImporter;
_embyUserImporter = embyUserImporter;
_sonarrSync = cache;
_cpCache = cpCache;
_jobSettings = jobsettings;
_srSync = srSync;
_refreshMetadata = refresh;
_newsletter = newsletter;
_plexRecentlyAddedSync = recentlyAddedPlex;
_lidarrArtistSync = artist;
_issuesPurge = purge;
_resender = resender;
_mediaDatabaseRefresh = dbRefresh;
}
private readonly IPlexContentSync _plexContentSync;
private readonly IPlexRecentlyAddedSync _plexRecentlyAddedSync;
private readonly IRadarrSync _radarrSync;
private readonly IOmbiAutomaticUpdater _updater;
private readonly IPlexUserImporter _plexUserImporter;
private readonly IEmbyContentSync _embyContentSync;
private readonly IEmbyUserImporter _embyUserImporter;
private readonly ISonarrSync _sonarrSync;
private readonly ICouchPotatoSync _cpCache;
private readonly ISickRageSync _srSync;
private readonly ISettingsService<JobSettings> _jobSettings;
private readonly IRefreshMetadata _refreshMetadata;
private readonly INewsletterJob _newsletter;
private readonly ILidarrArtistSync _lidarrArtistSync;
private readonly IIssuesPurge _issuesPurge;
private readonly IResendFailedRequests _resender;
private readonly IMediaDatabaseRefresh _mediaDatabaseRefresh;
public void Setup()
{
var s = _jobSettings.GetSettings();
// RecurringJob.AddOrUpdate(() => _embyContentSync.Start(), JobSettingsHelper.EmbyContent(s));
// RecurringJob.AddOrUpdate(() => _sonarrSync.Start(), JobSettingsHelper.Sonarr(s));
// RecurringJob.AddOrUpdate(() => _radarrSync.CacheContent(), JobSettingsHelper.Radarr(s));
// //RecurringJob.AddOrUpdate(() => _plexContentSync.Execute(null), JobSettingsHelper.PlexContent(s));
// //RecurringJob.AddOrUpdate(() => _plexRecentlyAddedSync.Start(), JobSettingsHelper.PlexRecentlyAdded(s));
// RecurringJob.AddOrUpdate(() => _cpCache.Start(), JobSettingsHelper.CouchPotato(s));
// RecurringJob.AddOrUpdate(() => _srSync.Start(), JobSettingsHelper.SickRageSync(s));
// RecurringJob.AddOrUpdate(() => _refreshMetadata.Start(), JobSettingsHelper.RefreshMetadata(s));
// RecurringJob.AddOrUpdate(() => _lidarrArtistSync.CacheContent(), JobSettingsHelper.LidarrArtistSync(s));
// RecurringJob.AddOrUpdate(() => _issuesPurge.Start(), JobSettingsHelper.IssuePurge(s));
// RecurringJob.AddOrUpdate(() => _updater.Update(null), JobSettingsHelper.Updater(s));
// RecurringJob.AddOrUpdate(() => _embyUserImporter.Start(), JobSettingsHelper.UserImporter(s));
// RecurringJob.AddOrUpdate(() => _plexUserImporter.Start(), JobSettingsHelper.UserImporter(s));
// RecurringJob.AddOrUpdate(() => _newsletter.Start(), JobSettingsHelper.Newsletter(s));
//// RecurringJob.AddOrUpdate(() => _resender.Start(), JobSettingsHelper.ResendFailedRequests(s));
// RecurringJob.AddOrUpdate(() => _mediaDatabaseRefresh.Start(), JobSettingsHelper.MediaDatabaseRefresh(s));
}
private bool _disposed;
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
_radarrSync?.Dispose();
_updater?.Dispose();
_plexUserImporter?.Dispose();
_embyContentSync?.Dispose();
_embyUserImporter?.Dispose();
_sonarrSync?.Dispose();
_cpCache?.Dispose();
_srSync?.Dispose();
_jobSettings?.Dispose();
_refreshMetadata?.Dispose();
_newsletter?.Dispose();
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}

@ -34,6 +34,7 @@ using Microsoft.Extensions.Logging;
using Ombi.Core.Notifications;
using Ombi.Helpers;
using Ombi.Notifications.Models;
using Ombi.Schedule.Jobs.Ombi;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
using Ombi.Store.Repository.Requests;
@ -63,6 +64,8 @@ namespace Ombi.Schedule.Jobs.Emby
{
await ProcessMovies();
await ProcessTv();
await OmbiQuartz.TriggerJob(nameof(IRefreshMetadata), "System");
}
private async Task ProcessMovies()

@ -56,7 +56,6 @@ namespace Ombi.Schedule.Jobs.Emby
// Episodes
await OmbiQuartz.TriggerJob(nameof(IEmbyEpisodeSync), "Emby");
await OmbiQuartz.TriggerJob(nameof(IRefreshMetadata), "System");
}

@ -43,7 +43,7 @@ namespace Ombi.Schedule.Jobs.Lidarr
var cachedAlbum = await _cachedAlbums.FirstOrDefaultAsync(x => x.ForeignAlbumId.Equals(request.ForeignAlbumId));
if (cachedAlbum != null)
{
if (cachedAlbum.FullyAvailable)
if (cachedAlbum.FullyAvailable) // ensure we have all tracks
{
request.Available = true;
request.MarkedAsAvailable = DateTime.Now;

@ -5,6 +5,5 @@ namespace Ombi.Schedule.Jobs.Ombi
{
public interface IRefreshMetadata : IBaseJob
{
Task ProcessPlexServerContent(IEnumerable<int> contentIds);
}
}

@ -54,7 +54,7 @@ namespace Ombi.Schedule.Jobs.Ombi
{
await StartPlex();
}
var embySettings = await _embySettings.GetSettingsAsync();
if (embySettings.Enable)
{
@ -68,44 +68,16 @@ namespace Ombi.Schedule.Jobs.Ombi
}
}
public async Task ProcessPlexServerContent(IEnumerable<int> contentIds)
{
_log.LogInformation("Starting the Metadata refresh from RecentlyAddedSync");
var plexSettings = await _plexSettings.GetSettingsAsync();
try
{
if (plexSettings.Enable)
{
await StartPlexWithKnownContent(contentIds);
}
}
catch (Exception e)
{
_log.LogError(e, "Exception when refreshing the Plex Metadata");
throw;
}
}
private async Task StartPlexWithKnownContent(IEnumerable<int> contentids)
{
var everything = _plexRepo.GetAll().Where(x => contentids.Contains(x.Id));
var allMovies = everything.Where(x => x.Type == PlexMediaTypeEntity.Movie);
await StartPlexMovies(allMovies);
// Now Tv
var allTv = everything.Where(x => x.Type == PlexMediaTypeEntity.Show);
await StartPlexTv(allTv);
}
private async Task StartPlex()
{
// Ensure we check that we have not linked this item to a request
var allMovies = _plexRepo.GetAll().Where(x =>
x.Type == PlexMediaTypeEntity.Movie && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue()));
x.Type == PlexMediaTypeEntity.Movie && !x.RequestId.HasValue && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue()));
await StartPlexMovies(allMovies);
// Now Tv
var allTv = _plexRepo.GetAll().Where(x =>
x.Type == PlexMediaTypeEntity.Show && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue() || !x.TvDbId.HasValue()));
x.Type == PlexMediaTypeEntity.Show && !x.RequestId.HasValue && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue() || !x.TvDbId.HasValue()));
await StartPlexTv(allTv);
}
@ -117,9 +89,13 @@ namespace Ombi.Schedule.Jobs.Ombi
private async Task StartPlexTv(IQueryable<PlexServerContent> allTv)
{
var tvCount = 0;
foreach (var show in allTv)
{
{
// Just double check there is no associated request id
if (show.RequestId.HasValue)
{
continue;
}
var hasImdb = show.ImdbId.HasValue();
var hasTheMovieDb = show.TheMovieDbId.HasValue();
var hasTvDbId = show.TvDbId.HasValue();
@ -143,21 +119,15 @@ namespace Ombi.Schedule.Jobs.Ombi
show.TvDbId = id;
_plexRepo.UpdateWithoutSave(show);
}
tvCount++;
if (tvCount >= 75)
{
await _plexRepo.SaveChangesAsync();
tvCount = 0;
}
await _plexRepo.SaveChangesAsync();
}
await _plexRepo.SaveChangesAsync();
}
private async Task StartEmbyTv()
{
var allTv = _embyRepo.GetAll().Where(x =>
x.Type == EmbyMediaType.Series && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue() || !x.TvDbId.HasValue()));
var tvCount = 0;
foreach (var show in allTv)
{
var hasImdb = show.ImdbId.HasValue();
@ -183,21 +153,20 @@ namespace Ombi.Schedule.Jobs.Ombi
show.TvDbId = id;
_embyRepo.UpdateWithoutSave(show);
}
tvCount++;
if (tvCount >= 75)
{
await _embyRepo.SaveChangesAsync();
tvCount = 0;
}
await _embyRepo.SaveChangesAsync();
}
await _embyRepo.SaveChangesAsync();
}
private async Task StartPlexMovies(IQueryable<PlexServerContent> allMovies)
{
int movieCount = 0;
foreach (var movie in allMovies)
{
// Just double check there is no associated request id
if (movie.RequestId.HasValue)
{
continue;
}
var hasImdb = movie.ImdbId.HasValue();
var hasTheMovieDb = movie.TheMovieDbId.HasValue();
// Movies don't really use TheTvDb
@ -214,26 +183,19 @@ namespace Ombi.Schedule.Jobs.Ombi
movie.TheMovieDbId = id;
_plexRepo.UpdateWithoutSave(movie);
}
movieCount++;
if (movieCount >= 75)
{
await _plexRepo.SaveChangesAsync();
movieCount = 0;
}
}
await _plexRepo.SaveChangesAsync();
await _plexRepo.SaveChangesAsync();
}
}
private async Task StartEmbyMovies(EmbySettings settings)
{
var allMovies = _embyRepo.GetAll().Where(x =>
x.Type == EmbyMediaType.Movie && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue()));
int movieCount = 0;
foreach (var movie in allMovies)
{
movie.ImdbId.HasValue();
movie.TheMovieDbId.HasValue();
movie.TheMovieDbId.HasValue();
// Movies don't really use TheTvDb
// Check if it even has 1 ID
@ -242,6 +204,8 @@ namespace Ombi.Schedule.Jobs.Ombi
// Ok this sucks,
// The only think I can think that has happened is that we scanned Emby before Emby has got the metadata
// So let's recheck emby to see if they have got the metadata now
//
// Yeah your right that does suck - Future Jamie
_log.LogInformation($"Movie {movie.Title} does not have a ImdbId or TheMovieDbId, so rechecking emby");
foreach (var server in settings.Servers)
{
@ -273,15 +237,10 @@ namespace Ombi.Schedule.Jobs.Ombi
movie.TheMovieDbId = id;
_embyRepo.UpdateWithoutSave(movie);
}
movieCount++;
if (movieCount >= 75)
{
await _embyRepo.SaveChangesAsync();
movieCount = 0;
}
}
await _embyRepo.SaveChangesAsync();
await _embyRepo.SaveChangesAsync();
}
}
private async Task<string> GetTheMovieDbId(bool hasTvDbId, bool hasImdb, string tvdbID, string imdbId, string title, bool movie)
@ -364,7 +323,7 @@ namespace Ombi.Schedule.Jobs.Ombi
{
var result = await _movieApi.GetTvExternals(id);
return result.tvdb_id.ToString();
return result.tvdb_id.ToString();
}
}

@ -45,7 +45,7 @@ namespace Ombi.Schedule.Jobs.Plex
}
catch (Exception e)
{
_log.LogError(e, "Exception thrown in Plex availbility checker");
_log.LogError(e, "Exception thrown in Plex availability checker");
}
}
@ -72,7 +72,7 @@ namespace Ombi.Schedule.Jobs.Plex
{
useTvDb = true;
}
var tvDbId = child.ParentRequest.TvDbId;
var imdbId = child.ParentRequest.ImdbId;
IQueryable<PlexEpisode> seriesEpisodes = null;
@ -80,7 +80,7 @@ namespace Ombi.Schedule.Jobs.Plex
{
seriesEpisodes = plexEpisodes.Where(x => x.Series.ImdbId == imdbId.ToString());
}
if (useTvDb && (seriesEpisodes == null || !seriesEpisodes.Any()) )
if (useTvDb && (seriesEpisodes == null || !seriesEpisodes.Any()))
{
seriesEpisodes = plexEpisodes.Where(x => x.Series.TvDbId == tvDbId.ToString());
}
@ -94,8 +94,8 @@ namespace Ombi.Schedule.Jobs.Plex
{
// Let's try and match the series by name
seriesEpisodes = plexEpisodes.Where(x =>
x.Series.Title.Equals(child.Title, StringComparison.CurrentCultureIgnoreCase) &&
x.Series.ReleaseYear == child.ParentRequest.ReleaseDate.Year.ToString());
x.Series.Title.Equals(child.Title, StringComparison.InvariantCultureIgnoreCase) &&
x.Series.ReleaseYear.Equals(child.ParentRequest.ReleaseDate.Year.ToString(), StringComparison.InvariantCultureIgnoreCase));
}
@ -122,17 +122,18 @@ namespace Ombi.Schedule.Jobs.Plex
var allAvailable = child.SeasonRequests.All(x => x.Episodes.All(c => c.Available));
if (allAvailable)
{
// We have fulfulled this request!
_log.LogInformation("[PAC] - Child request {0} is now available, sending notification", $"{child.Title} - {child.Id}");
// We have ful-fulled this request!
child.Available = true;
child.MarkedAsAvailable = DateTime.Now;
_backgroundJobClient.Enqueue(() => _notificationService.Publish(new NotificationOptions
await _notificationService.Publish(new NotificationOptions
{
DateTime = DateTime.Now,
NotificationType = NotificationType.RequestAvailable,
RequestId = child.Id,
RequestType = RequestType.TvShow,
Recipient = child.RequestedUser.Email
}));
});
}
}
@ -166,20 +167,22 @@ namespace Ombi.Schedule.Jobs.Plex
movie.Available = true;
movie.MarkedAsAvailable = DateTime.Now;
if (movie.Available)
item.RequestId = movie.Id;
_log.LogInformation("[PAC] - Movie request {0} is now available, sending notification", $"{movie.Title} - {movie.Id}");
await _notificationService.Publish(new NotificationOptions
{
_backgroundJobClient.Enqueue(() => _notificationService.Publish(new NotificationOptions
{
DateTime = DateTime.Now,
NotificationType = NotificationType.RequestAvailable,
RequestId = movie.Id,
RequestType = RequestType.Movie,
Recipient = movie.RequestedUser != null ? movie.RequestedUser.Email : string.Empty
}));
}
DateTime = DateTime.Now,
NotificationType = NotificationType.RequestAvailable,
RequestId = movie.Id,
RequestType = RequestType.Movie,
Recipient = movie.RequestedUser != null ? movie.RequestedUser.Email : string.Empty
});
}
await _movieRepo.Save();
await _repo.SaveChangesAsync();
}
private bool _disposed;

@ -49,14 +49,13 @@ namespace Ombi.Schedule.Jobs.Plex
public class PlexContentSync : IPlexContentSync
{
public PlexContentSync(ISettingsService<PlexSettings> plex, IPlexApi plexApi, ILogger<PlexContentSync> logger, IPlexContentRepository repo,
IPlexEpisodeSync epsiodeSync, IRefreshMetadata metadataRefresh)
IPlexEpisodeSync epsiodeSync)
{
Plex = plex;
PlexApi = plexApi;
Logger = logger;
Repo = repo;
EpisodeSync = epsiodeSync;
Metadata = metadataRefresh;
Plex.ClearCache();
}
@ -65,12 +64,11 @@ namespace Ombi.Schedule.Jobs.Plex
private ILogger<PlexContentSync> Logger { get; }
private IPlexContentRepository Repo { get; }
private IPlexEpisodeSync EpisodeSync { get; }
private IRefreshMetadata Metadata { get; }
public async Task Execute(IJobExecutionContext context)
{
JobDataMap dataMap = context.JobDetail.JobDataMap;
var recentlyAddedSearch = dataMap.GetBooleanValueFromString("recentlyAddedSearch");
var recentlyAddedSearch = dataMap.GetBooleanValueFromString(JobDataKeys.RecentlyAddedSearch);
var plexSettings = await Plex.GetSettingsAsync();
if (!plexSettings.Enable)
@ -83,7 +81,9 @@ namespace Ombi.Schedule.Jobs.Plex
return;
}
var processedContent = new ProcessedContent();
Logger.LogInformation($"Starting Plex Content Cacher {(recentlyAddedSearch ? "Recently Added Scan" : "")}");
Logger.LogInformation(recentlyAddedSearch
? "Starting Plex Content Cacher Recently Added Scan"
: "Starting Plex Content Cacher");
try
{
if (recentlyAddedSearch)
@ -103,7 +103,6 @@ namespace Ombi.Schedule.Jobs.Plex
if (!recentlyAddedSearch)
{
Logger.LogInformation("Starting EP Cacher");
await OmbiQuartz.TriggerJob(nameof(IPlexEpisodeSync), "Plex");
}

@ -60,7 +60,7 @@ namespace Ombi.Schedule
private static async Task AddSystem(JobSettings s)
{
await OmbiQuartz.Instance.AddJob<IRefreshMetadata>(nameof(IRefreshMetadata), "System", JobSettingsHelper.RefreshMetadata(s));
await OmbiQuartz.Instance.AddJob<IRefreshMetadata>(nameof(IRefreshMetadata), "System", null);
await OmbiQuartz.Instance.AddJob<IIssuesPurge>(nameof(IIssuesPurge), "System", JobSettingsHelper.IssuePurge(s));
//OmbiQuartz.Instance.AddJob<IOmbiAutomaticUpdater>(nameof(IOmbiAutomaticUpdater), "System", JobSettingsHelper.Updater(s));
await OmbiQuartz.Instance.AddJob<INewsletterJob>(nameof(INewsletterJob), "System", JobSettingsHelper.Newsletter(s));
@ -80,7 +80,7 @@ namespace Ombi.Schedule
private static async Task AddPlex(JobSettings s)
{
await OmbiQuartz.Instance.AddJob<IPlexContentSync>(nameof(IPlexContentSync), "Plex", JobSettingsHelper.PlexContent(s), new Dictionary<string, string> { { "recentlyAddedSearch", "false" } });
await OmbiQuartz.Instance.AddJob<IPlexContentSync>(nameof(IPlexContentSync) + "RecentlyAdded", "Plex", JobSettingsHelper.PlexRecentlyAdded(s), new Dictionary<string, string> { { "recentlyAddedSearch", "true" } });
await OmbiQuartz.Instance.AddJob<IPlexContentSync>(nameof(IPlexContentSync) + "RecentlyAdded", "Plex", JobSettingsHelper.PlexRecentlyAdded(s), new Dictionary<string, string> { { JobDataKeys.RecentlyAddedSearch, "true" } });
await OmbiQuartz.Instance.AddJob<IPlexUserImporter>(nameof(IPlexUserImporter), "Plex", JobSettingsHelper.UserImporter(s));
await OmbiQuartz.Instance.AddJob<IPlexEpisodeSync>(nameof(IPlexEpisodeSync), "Plex", null);
await OmbiQuartz.Instance.AddJob<IPlexAvailabilityChecker>(nameof(IPlexAvailabilityChecker), "Plex", null);

@ -53,6 +53,8 @@ namespace Ombi.Store.Entities
public DateTime AddedAt { get; set; }
public string Quality { get; set; }
public int? RequestId { get; set; }
[NotMapped]
public bool HasImdb => !string.IsNullOrEmpty(ImdbId);

File diff suppressed because it is too large Load Diff

@ -0,0 +1,22 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Ombi.Store.Migrations
{
public partial class RequestIdOnPlexContent : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "RequestId",
table: "PlexServerContent",
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "RequestId",
table: "PlexServerContent");
}
}
}

@ -14,7 +14,7 @@ namespace Ombi.Store.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.2.1-servicing-10028");
.HasAnnotation("ProductVersion", "2.2.2-servicing-10034");
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
@ -455,6 +455,8 @@ namespace Ombi.Store.Migrations
b.Property<string>("ReleaseYear");
b.Property<int?>("RequestId");
b.Property<string>("TheMovieDbId");
b.Property<string>("Title");

@ -90,8 +90,8 @@ namespace Ombi.Store.Repository
.WaitAndRetryAsync(new[]
{
TimeSpan.FromSeconds(1),
TimeSpan.FromSeconds(2),
TimeSpan.FromSeconds(3)
TimeSpan.FromSeconds(5),
TimeSpan.FromSeconds(10)
});
var result = await policy.ExecuteAndCaptureAsync(async () =>

@ -27,6 +27,7 @@ using Ombi.Store.Context;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
using Serilog;
using SQLitePCL;
using ILogger = Serilog.ILogger;
namespace Ombi
@ -97,8 +98,7 @@ namespace Ombi
x.UseActivator(new IoCJobActivator(services.BuildServiceProvider()));
});
SQLitePCL.raw.sqlite3_config(2);
SQLitePCL.raw.sqlite3_config(raw.SQLITE_CONFIG_MULTITHREAD);
services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
{

Loading…
Cancel
Save