tidy up ef core transaction refactor

ref #343
This commit is contained in:
Collin Barrett 2018-08-15 18:36:18 -05:00
parent cce241c02b
commit 3f80da819e
12 changed files with 654 additions and 33 deletions

5
cantSnapshot.sql Normal file
View file

@ -0,0 +1,5 @@
--TODO: https://github.com/collinbarrett/FilterLists/issues/200
--TODO: https://github.com/collinbarrett/FilterLists/issues/201
UPDATE filterlists SET CantSnapshot = 1
WHERE id IN (48, 149, 173, 185, 186, 187, 188, 189, 352)

View file

@ -49,7 +49,7 @@ private static void CaptureSnapshots(int batchSize)
var snapshotService = serviceProvider.GetService<SnapshotService>();
Log("Capturing FilterList snapshots...");
snapshotService.CaptureAsync(batchSize).Wait();
Log(Environment.NewLine + "Snapshots captured.");
Log("Snapshots captured.");
telemetryClient.Flush();
}

View file

@ -0,0 +1,594 @@
// <auto-generated />
using System;
using FilterLists.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
namespace FilterLists.Api.Migrations
{
[DbContext(typeof(FilterListsDbContext))]
[Migration("20180815233049_AddCantSnapshot")]
partial class AddCantSnapshot
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.1.1-rtm-30846")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("FilterLists.Data.Entities.FilterList", b =>
{
b.Property<ushort>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("SMALLINT UNSIGNED")
.HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
b.Property<bool>("CantSnapshot");
b.Property<string>("ChatUrl")
.HasColumnType("TEXT");
b.Property<DateTime?>("CreatedDateUtc")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp()");
b.Property<string>("Description")
.HasColumnType("TEXT");
b.Property<string>("DescriptionSourceUrl")
.HasColumnType("TEXT");
b.Property<DateTime?>("DiscontinuedDate")
.ValueGeneratedOnAdd()
.HasColumnType("DATE")
.HasDefaultValueSql("NULL");
b.Property<string>("DonateUrl")
.HasColumnType("TEXT");
b.Property<string>("EmailAddress")
.ValueGeneratedOnAdd()
.HasColumnType("VARCHAR(126)")
.HasDefaultValueSql("NULL");
b.Property<string>("ForumUrl")
.HasColumnType("TEXT");
b.Property<string>("HomeUrl")
.HasColumnType("TEXT");
b.Property<string>("IssuesUrl")
.HasColumnType("TEXT");
b.Property<byte>("LicenseId")
.ValueGeneratedOnAdd()
.HasDefaultValue((byte)5);
b.Property<DateTime?>("ModifiedDateUtc")
.IsRequired()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("VARCHAR(126)");
b.Property<string>("PolicyUrl")
.HasColumnType("TEXT");
b.Property<DateTime?>("PublishedDate")
.ValueGeneratedOnAdd()
.HasColumnType("DATE")
.HasDefaultValueSql("NULL");
b.Property<string>("SubmissionUrl")
.HasColumnType("TEXT");
b.Property<byte?>("SyntaxId");
b.Property<string>("ViewUrl")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("LicenseId");
b.HasIndex("SyntaxId");
b.ToTable("filterlists");
});
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.FilterListLanguage", b =>
{
b.Property<ushort>("FilterListId");
b.Property<ushort>("LanguageId");
b.Property<DateTime?>("CreatedDateUtc")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp()");
b.HasKey("FilterListId", "LanguageId");
b.HasIndex("LanguageId");
b.ToTable("filterlists_languages");
});
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.FilterListMaintainer", b =>
{
b.Property<ushort>("FilterListId");
b.Property<ushort>("MaintainerId");
b.Property<DateTime?>("CreatedDateUtc")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp()");
b.HasKey("FilterListId", "MaintainerId");
b.HasIndex("MaintainerId");
b.ToTable("filterlists_maintainers");
});
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.Fork", b =>
{
b.Property<ushort>("ForkFilterListId");
b.Property<ushort>("UpstreamFilterListId");
b.Property<DateTime?>("CreatedDateUtc")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp()");
b.HasKey("ForkFilterListId", "UpstreamFilterListId");
b.HasIndex("UpstreamFilterListId");
b.ToTable("forks");
});
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.Merge", b =>
{
b.Property<ushort>("MergeFilterListId");
b.Property<ushort>("UpstreamFilterListId");
b.Property<DateTime?>("CreatedDateUtc")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp()");
b.HasKey("MergeFilterListId", "UpstreamFilterListId");
b.HasIndex("UpstreamFilterListId");
b.ToTable("merges");
});
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.SnapshotRule", b =>
{
b.Property<uint>("AddedBySnapshotId");
b.Property<uint>("RuleId");
b.Property<DateTime?>("CreatedDateUtc")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp()");
b.Property<DateTime?>("ModifiedDateUtc")
.IsRequired()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
b.Property<uint?>("RemovedBySnapshotId");
b.HasKey("AddedBySnapshotId", "RuleId");
b.HasIndex("RemovedBySnapshotId");
b.HasIndex("RuleId");
b.ToTable("snapshots_rules");
});
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.SoftwareSyntax", b =>
{
b.Property<byte>("SyntaxId");
b.Property<byte>("SoftwareId");
b.Property<DateTime?>("CreatedDateUtc")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp()");
b.HasKey("SyntaxId", "SoftwareId");
b.HasIndex("SoftwareId");
b.ToTable("software_syntaxes");
});
modelBuilder.Entity("FilterLists.Data.Entities.Language", b =>
{
b.Property<ushort>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("SMALLINT UNSIGNED")
.HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
b.Property<DateTime?>("CreatedDateUtc")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp()");
b.Property<string>("Iso6391")
.ValueGeneratedOnAdd()
.HasColumnType("VARCHAR(2)")
.HasDefaultValueSql("NULL");
b.Property<string>("Iso6392")
.ValueGeneratedOnAdd()
.HasColumnType("VARCHAR(3)")
.HasDefaultValueSql("NULL");
b.Property<string>("Iso6392B")
.ValueGeneratedOnAdd()
.HasColumnType("VARCHAR(3)")
.HasDefaultValueSql("NULL");
b.Property<string>("Iso6392T")
.ValueGeneratedOnAdd()
.HasColumnType("VARCHAR(3)")
.HasDefaultValueSql("NULL");
b.Property<string>("Iso6393")
.ValueGeneratedOnAdd()
.HasColumnType("VARCHAR(3)")
.HasDefaultValueSql("NULL");
b.Property<string>("LocalName")
.ValueGeneratedOnAdd()
.HasColumnType("VARCHAR(126)")
.HasDefaultValueSql("NULL");
b.Property<DateTime?>("ModifiedDateUtc")
.IsRequired()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
b.Property<string>("Name")
.ValueGeneratedOnAdd()
.HasColumnType("VARCHAR(126)")
.HasDefaultValueSql("NULL");
b.HasKey("Id");
b.ToTable("languages");
});
modelBuilder.Entity("FilterLists.Data.Entities.License", b =>
{
b.Property<byte>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TINYINT UNSIGNED")
.HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
b.Property<DateTime?>("CreatedDateUtc")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp()");
b.Property<string>("DescriptionUrl")
.HasColumnType("TEXT");
b.Property<DateTime?>("ModifiedDateUtc")
.IsRequired()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("VARCHAR(126)");
b.Property<bool>("PermissiveAdaptation");
b.Property<bool>("PermissiveCommercial");
b.HasKey("Id");
b.ToTable("licenses");
});
modelBuilder.Entity("FilterLists.Data.Entities.Maintainer", b =>
{
b.Property<ushort>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("SMALLINT UNSIGNED")
.HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
b.Property<DateTime?>("CreatedDateUtc")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp()");
b.Property<string>("EmailAddress")
.ValueGeneratedOnAdd()
.HasColumnType("VARCHAR(126)")
.HasDefaultValueSql("NULL");
b.Property<string>("HomeUrl")
.HasColumnType("TEXT");
b.Property<DateTime?>("ModifiedDateUtc")
.IsRequired()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("VARCHAR(126)");
b.Property<string>("TwitterHandle")
.ValueGeneratedOnAdd()
.HasColumnType("VARCHAR(126)")
.HasDefaultValueSql("NULL");
b.HasKey("Id");
b.ToTable("maintainers");
});
modelBuilder.Entity("FilterLists.Data.Entities.Rule", b =>
{
b.Property<uint>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INT UNSIGNED")
.HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
b.Property<DateTime?>("CreatedDateUtc")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp()");
b.Property<string>("Raw")
.IsRequired()
.HasColumnType("VARCHAR(8192)");
b.HasKey("Id");
b.ToTable("rules");
});
modelBuilder.Entity("FilterLists.Data.Entities.Snapshot", b =>
{
b.Property<uint>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("MEDIUMINT UNSIGNED")
.HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
b.Property<DateTime?>("CreatedDateUtc")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp()");
b.Property<ushort>("FilterListId");
b.Property<string>("HttpStatusCode")
.ValueGeneratedOnAdd()
.HasColumnType("VARCHAR(3)")
.HasDefaultValueSql("NULL");
b.Property<DateTime?>("ModifiedDateUtc")
.IsRequired()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
b.Property<bool>("WasSuccessful");
b.HasKey("Id");
b.HasIndex("FilterListId");
b.ToTable("snapshots");
});
modelBuilder.Entity("FilterLists.Data.Entities.Software", b =>
{
b.Property<byte>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TINYINT UNSIGNED")
.HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
b.Property<DateTime?>("CreatedDateUtc")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp()");
b.Property<string>("DownloadUrl")
.HasColumnType("TEXT");
b.Property<string>("HomeUrl")
.HasColumnType("TEXT");
b.Property<DateTime?>("ModifiedDateUtc")
.IsRequired()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("VARCHAR(126)");
b.HasKey("Id");
b.ToTable("software");
});
modelBuilder.Entity("FilterLists.Data.Entities.Syntax", b =>
{
b.Property<byte>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TINYINT UNSIGNED")
.HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
b.Property<DateTime?>("CreatedDateUtc")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp()");
b.Property<string>("DefinitionUrl")
.HasColumnType("TEXT");
b.Property<DateTime?>("ModifiedDateUtc")
.IsRequired()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("VARCHAR(126)");
b.HasKey("Id");
b.ToTable("syntaxes");
});
modelBuilder.Entity("FilterLists.Data.Entities.FilterList", b =>
{
b.HasOne("FilterLists.Data.Entities.License", "License")
.WithMany("FilterLists")
.HasForeignKey("LicenseId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("FilterLists.Data.Entities.Syntax", "Syntax")
.WithMany("FilterLists")
.HasForeignKey("SyntaxId");
});
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.FilterListLanguage", b =>
{
b.HasOne("FilterLists.Data.Entities.FilterList", "FilterList")
.WithMany("FilterListLanguages")
.HasForeignKey("FilterListId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("FilterLists.Data.Entities.Language", "Language")
.WithMany("FilterListLanguages")
.HasForeignKey("LanguageId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.FilterListMaintainer", b =>
{
b.HasOne("FilterLists.Data.Entities.FilterList", "FilterList")
.WithMany("FilterListMaintainers")
.HasForeignKey("FilterListId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("FilterLists.Data.Entities.Maintainer", "Maintainer")
.WithMany("FilterListMaintainers")
.HasForeignKey("MaintainerId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.Fork", b =>
{
b.HasOne("FilterLists.Data.Entities.FilterList", "ForkFilterList")
.WithMany("ForkFilterLists")
.HasForeignKey("ForkFilterListId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("FilterLists.Data.Entities.FilterList", "UpstreamFilterList")
.WithMany("UpstreamForkFilterLists")
.HasForeignKey("UpstreamFilterListId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.Merge", b =>
{
b.HasOne("FilterLists.Data.Entities.FilterList", "MergeFilterList")
.WithMany("MergeFilterLists")
.HasForeignKey("MergeFilterListId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("FilterLists.Data.Entities.FilterList", "UpstreamFilterList")
.WithMany("UpstreamMergeFilterLists")
.HasForeignKey("UpstreamFilterListId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.SnapshotRule", b =>
{
b.HasOne("FilterLists.Data.Entities.Snapshot", "AddedBySnapshot")
.WithMany("AddedSnapshotRules")
.HasForeignKey("AddedBySnapshotId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("FilterLists.Data.Entities.Snapshot", "RemovedBySnapshot")
.WithMany("RemovedSnapshotRules")
.HasForeignKey("RemovedBySnapshotId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("FilterLists.Data.Entities.Rule", "Rule")
.WithMany("SnapshotRules")
.HasForeignKey("RuleId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.SoftwareSyntax", b =>
{
b.HasOne("FilterLists.Data.Entities.Software", "Software")
.WithMany("SoftwareSyntaxes")
.HasForeignKey("SoftwareId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("FilterLists.Data.Entities.Syntax", "Syntax")
.WithMany("SoftwareSyntaxes")
.HasForeignKey("SyntaxId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("FilterLists.Data.Entities.Snapshot", b =>
{
b.HasOne("FilterLists.Data.Entities.FilterList", "FilterList")
.WithMany("Snapshots")
.HasForeignKey("FilterListId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,33 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace FilterLists.Api.Migrations
{
public partial class AddCantSnapshot : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
"IsCompleted",
"snapshots",
"WasSuccessful");
migrationBuilder.AddColumn<bool>(
"CantSnapshot",
"filterlists",
nullable: false,
defaultValue: false);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
"CantSnapshot",
"filterlists");
migrationBuilder.RenameColumn(
"WasSuccessful",
"snapshots",
"IsCompleted");
}
}
}

View file

@ -25,6 +25,8 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.HasColumnType("SMALLINT UNSIGNED")
.HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
b.Property<bool>("CantSnapshot");
b.Property<string>("ChatUrl")
.HasColumnType("TEXT");
@ -402,14 +404,14 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.HasColumnType("VARCHAR(3)")
.HasDefaultValueSql("NULL");
b.Property<bool>("IsCompleted");
b.Property<DateTime?>("ModifiedDateUtc")
.IsRequired()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("TIMESTAMP")
.HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
b.Property<bool>("WasSuccessful");
b.HasKey("Id");
b.HasIndex("FilterListId");

View file

@ -8,6 +8,7 @@ namespace FilterLists.Data.Entities
[UsedImplicitly]
public class FilterList : BaseEntity
{
public bool CantSnapshot { get; set; }
public string ChatUrl { get; set; }
public string Description { get; set; }
public string DescriptionSourceUrl { get; set; }

View file

@ -8,7 +8,7 @@ public class Snapshot : BaseEntity
public uint FilterListId { get; set; }
public FilterList FilterList { get; set; }
public string HttpStatusCode { get; set; }
public bool IsCompleted { get; set; }
public bool WasSuccessful { get; set; }
public ICollection<SnapshotRule> AddedSnapshotRules { get; set; }
public ICollection<SnapshotRule> RemovedSnapshotRules { get; set; }
}

View file

@ -18,7 +18,7 @@ public override void Configure(EntityTypeBuilder<FilterList> entityTypeBuilder)
.HasColumnType("TEXT");
entityTypeBuilder.Property(x => x.DiscontinuedDate)
.HasColumnType("DATE")
.HasDefaultValueSql("NULL"); ;
.HasDefaultValueSql("NULL");
entityTypeBuilder.Property(x => x.DonateUrl)
.HasColumnType("TEXT");
entityTypeBuilder.Property(x => x.EmailAddress)
@ -40,7 +40,7 @@ public override void Configure(EntityTypeBuilder<FilterList> entityTypeBuilder)
.HasColumnType("TEXT");
entityTypeBuilder.Property(x => x.PublishedDate)
.HasColumnType("DATE")
.HasDefaultValueSql("NULL"); ;
.HasDefaultValueSql("NULL");
entityTypeBuilder.Property(x => x.SubmissionUrl)
.HasColumnType("TEXT");
entityTypeBuilder.Property(x => x.ViewUrl)

View file

@ -15,15 +15,15 @@ public ListDetailsDtoMappingProfile() =>
.ForMember(d => d.Maintainers, c => c.MapFrom(l => l.FilterListMaintainers.Select(m => m.Maintainer)))
.ForMember(d => d.RuleCount,
c => c.MapFrom(l =>
l.Snapshots.Where(s => s.IsCompleted && s.HttpStatusCode == "200")
l.Snapshots.Where(s => s.WasSuccessful)
.SelectMany(sr => sr.AddedSnapshotRules)
.Count() -
l.Snapshots.Where(s => s.IsCompleted && s.HttpStatusCode == "200")
l.Snapshots.Where(s => s.WasSuccessful)
.SelectMany(sr => sr.RemovedSnapshotRules)
.Count()))
.ForMember(d => d.UpdatedDate,
c => c.MapFrom(l =>
l.Snapshots.Where(s => s.IsCompleted && s.HttpStatusCode == "200")
l.Snapshots.Where(s => s.WasSuccessful)
.Where(s => s.AddedSnapshotRules.Count > 0 || s.RemovedSnapshotRules.Count > 0)
.OrderByDescending(s => s.CreatedDateUtc)
.Select(s => s.CreatedDateUtc)

View file

@ -13,7 +13,7 @@ public ListSummaryDtoMappingProfile() =>
.ForMember(d => d.Languages, c => c.MapFrom(l => l.FilterListLanguages.Select(la => la.Language)))
.ForMember(d => d.UpdatedDate,
c => c.MapFrom(l =>
l.Snapshots.Where(s => s.IsCompleted && s.HttpStatusCode == "200")
l.Snapshots.Where(s => s.WasSuccessful)
.Where(s => s.AddedSnapshotRules.Count > 0 || s.RemovedSnapshotRules.Count > 0)
.OrderByDescending(s => s.CreatedDateUtc)
.Select(s => s.CreatedDateUtc)

View file

@ -46,11 +46,9 @@ public async Task SaveAsync()
{
await SaveSnapshotInBatches(content);
await DedupSnapshotRules();
await SetSuccessful();
}
//TODO: remove after closed: https://github.com/collinbarrett/FilterLists/issues/344
await SetCompleted();
transaction.Commit();
}
catch (Exception e)
@ -119,7 +117,11 @@ private async Task SendExceptionEmail(Exception e)
var message = new StringBuilder();
message.AppendLine("Snapshot Exception");
message.AppendLine("FilterListId: " + snapshot.FilterListId);
message.AppendLine("Exception: " + e.Message);
message.AppendLine("Exception:");
message.AppendLine(e.Message);
message.AppendLine(e.StackTrace);
message.AppendLine(e.InnerException?.Message);
message.AppendLine(e.InnerException?.StackTrace);
await emailService.SendEmailAsync("Snapshot Exception", message.ToString());
}
@ -176,9 +178,9 @@ private void RemoveDuplicateSnapshotRules(IQueryable<SnapshotRule> existingSnaps
dbContext.SnapshotRules.RemoveRange(duplicateSnapshotRules);
}
private async Task SetCompleted()
private async Task SetSuccessful()
{
snapshot.IsCompleted = true;
snapshot.WasSuccessful = true;
await dbContext.SaveChangesAsync();
}
}

View file

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
@ -15,11 +14,6 @@ namespace FilterLists.Services.Snapshot
[UsedImplicitly]
public class SnapshotService : Service
{
//TODO: https://github.com/collinbarrett/FilterLists/issues/200
//TODO: https://github.com/collinbarrett/FilterLists/issues/201
private static readonly IList<uint> IgnoreLists =
new ReadOnlyCollection<uint>(new List<uint> {48, 149, 173, 185, 186, 187, 188, 189, 352});
private readonly DateTime yesterday = DateTime.UtcNow.AddDays(-1);
public SnapshotService(FilterListsDbContext dbContext, IConfigurationProvider configurationProvider,
@ -30,25 +24,15 @@ public SnapshotService(FilterListsDbContext dbContext, IConfigurationProvider co
public async Task CaptureAsync(int batchSize)
{
//TODO: remove after closed: https://github.com/collinbarrett/FilterLists/issues/344
await RollbackIncompletedSnapshots();
var lists = await GetListsToCapture(batchSize);
var snapshots = CreateSnapshots(lists);
await SaveSnapshots(snapshots);
}
private async Task RollbackIncompletedSnapshots()
{
var incompleteSnapshots = DbContext.Snapshots.Where(ss => ss.IsCompleted == false);
DbContext.Snapshots.RemoveRange(incompleteSnapshots);
await DbContext.SaveChangesAsync();
}
private async Task<List<FilterListViewUrlDto>> GetListsToCapture(int batchSize) =>
await DbContext
.FilterLists
.Where(l => !IgnoreLists.Contains(l.Id) &&
.Where(l => !l.CantSnapshot &&
(!l.Snapshots.Any() ||
l.Snapshots
.Select(s => s.CreatedDateUtc)