-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
+ abstract method `RevisionEntityIdSelector()` & `IsRevisionEntityIdEqualsExpression()` * rename abstract prop `AddRevisionDelegatesKeyBySplitEntityType` to `AddSplitRevisionsDelegatesKeyByEntityType` * rename delegate `AddRevisionDelegate` to `AddSplitRevisionsDelegate` and its param `revision` to `revisions` + type param `TEntityId` @ SaverWithRevision.cs + type param `TPostId` @ PostSaver.cs + field `DuplicateIndex` @ BaseRevisionWithSplitting.cs * add field `BaseRevisionWithSplitting.DuplicateIndex` to primary key columns @ `CrawlerDbContext.OnModelCreating()` * move nested class `tbm.Crawler.Db.Revision.Splitting.RevisionWithSplitting.ModelBuilder.ReplaceParameterTypeVisitor` to `tbm.Crawler` @ c#/crawler
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
using System.Collections.ObjectModel; | ||
|
||
namespace tbm.Crawler; | ||
|
||
/// <see>https://stackoverflow.com/questions/38316519/replace-parameter-type-in-lambda-expression/38345590#38345590</see> | ||
public class ReplaceParameterTypeVisitor<TSource, TTarget> : ExpressionVisitor | ||
Check failure on line 6 in c#/crawler/src/ReplaceParameterTypeVisitor.cs GitHub Actions / build (crawler)
Check failure on line 6 in c#/crawler/src/ReplaceParameterTypeVisitor.cs GitHub Actions / build (crawler)
|
||
{ | ||
private ReadOnlyCollection<ParameterExpression>? _parameters; | ||
|
||
protected override Expression VisitParameter(ParameterExpression node) => | ||
_parameters?.FirstOrDefault(p => p.Name == node.Name) ?? | ||
(node.Type == typeof(TSource) ? Expression.Parameter(typeof(TTarget), node.Name) : node); | ||
|
||
protected override Expression VisitLambda<T>(Expression<T> node) | ||
{ | ||
_parameters = VisitAndConvert(node.Parameters, nameof(VisitLambda)); | ||
return Expression.Lambda(Visit(node.Body), _parameters); | ||
} | ||
|
||
protected override Expression VisitMember(MemberExpression node) => | ||
node.Member.DeclaringType == typeof(TSource) | ||
? Expression.Property(Visit(node.Expression)!, node.Member.Name) | ||
: base.VisitMember(node); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,30 +6,25 @@ public class ReplySaver( | |
ReplyContentImageSaver replyContentImageSaver, | ||
ReplySignatureSaver replySignatureSaver, | ||
AuthorRevisionSaver.New authorRevisionSaverFactory) | ||
: PostSaver<ReplyPost, BaseReplyRevision>( | ||
: PostSaver<ReplyPost, BaseReplyRevision, Pid>( | ||
logger, posts, authorRevisionSaverFactory, PostType.Reply) | ||
{ | ||
public delegate ReplySaver New(ConcurrentDictionary<PostId, ReplyPost> posts); | ||
|
||
protected override Dictionary<Type, AddRevisionDelegate> | ||
AddRevisionDelegatesKeyBySplitEntityType { get; } = new() | ||
{ | ||
{ | ||
typeof(ReplyRevision.SplitFloor), (db, revisions) => | ||
db.Set<ReplyRevision.SplitFloor>() | ||
.AddRange(revisions.OfType<ReplyRevision.SplitFloor>()) | ||
}, | ||
{ | ||
typeof(ReplyRevision.SplitSubReplyCount), (db, revisions) => | ||
db.Set<ReplyRevision.SplitSubReplyCount>() | ||
.AddRange(revisions.OfType<ReplyRevision.SplitSubReplyCount>()) | ||
}, | ||
private Lazy<Dictionary<Type, AddSplitRevisionsDelegate>>? _addSplitRevisionsDelegatesKeyByEntityType; | ||
protected override Lazy<Dictionary<Type, AddSplitRevisionsDelegate>> | ||
AddSplitRevisionsDelegatesKeyByEntityType => | ||
_addSplitRevisionsDelegatesKeyByEntityType ??= new(() => new() | ||
{ | ||
typeof(ReplyRevision.SplitAgreeCount), (db, revisions) => | ||
db.Set<ReplyRevision.SplitAgreeCount>() | ||
.AddRange(revisions.OfType<ReplyRevision.SplitAgreeCount>()) | ||
} | ||
}; | ||
{typeof(ReplyRevision.SplitFloor), AddSplitRevisions<ReplyRevision.SplitFloor>}, | ||
Check failure on line 19 in c#/crawler/src/Tieba/Crawl/Saver/Post/ReplySaver.cs GitHub Actions / build (crawler)
|
||
{typeof(ReplyRevision.SplitSubReplyCount), AddSplitRevisions<ReplyRevision.SplitSubReplyCount>}, | ||
Check failure on line 20 in c#/crawler/src/Tieba/Crawl/Saver/Post/ReplySaver.cs GitHub Actions / build (crawler)
|
||
{typeof(ReplyRevision.SplitAgreeCount), AddSplitRevisions<ReplyRevision.SplitAgreeCount>} | ||
Check failure on line 21 in c#/crawler/src/Tieba/Crawl/Saver/Post/ReplySaver.cs GitHub Actions / build (crawler)
|
||
}); | ||
|
||
protected override Pid RevisionEntityIdSelector(BaseReplyRevision entity) => entity.Pid; | ||
protected override Expression<Func<BaseReplyRevision, bool>> | ||
IsRevisionEntityIdEqualsExpression(BaseReplyRevision newRevision) => | ||
existingRevision => existingRevision.Pid == newRevision.Pid; | ||
|
||
public override bool UserFieldUpdateIgnorance(string propName, object? oldValue, object? newValue) => propName switch | ||
{ // FansNickname in reply response will always be null | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,25 +4,24 @@ public class SubReplySaver( | |
ILogger<SubReplySaver> logger, | ||
ConcurrentDictionary<PostId, SubReplyPost> posts, | ||
AuthorRevisionSaver.New authorRevisionSaverFactory) | ||
: PostSaver<SubReplyPost, BaseSubReplyRevision>( | ||
: PostSaver<SubReplyPost, BaseSubReplyRevision, Spid>( | ||
logger, posts, authorRevisionSaverFactory, PostType.SubReply) | ||
{ | ||
public delegate SubReplySaver New(ConcurrentDictionary<PostId, SubReplyPost> posts); | ||
|
||
protected override Dictionary<Type, AddRevisionDelegate> | ||
AddRevisionDelegatesKeyBySplitEntityType { get; } = new() | ||
{ | ||
{ | ||
typeof(SubReplyRevision.SplitAgreeCount), (db, revisions) => | ||
db.Set<SubReplyRevision.SplitAgreeCount>() | ||
.AddRange(revisions.OfType<SubReplyRevision.SplitAgreeCount>()) | ||
}, | ||
private Lazy<Dictionary<Type, AddSplitRevisionsDelegate>>? _addSplitRevisionsDelegatesKeyByEntityType; | ||
protected override Lazy<Dictionary<Type, AddSplitRevisionsDelegate>> | ||
AddSplitRevisionsDelegatesKeyByEntityType => | ||
_addSplitRevisionsDelegatesKeyByEntityType ??= new(() => new() | ||
{ | ||
typeof(SubReplyRevision.SplitDisagreeCount), (db, revisions) => | ||
db.Set<SubReplyRevision.SplitDisagreeCount>() | ||
.AddRange(revisions.OfType<SubReplyRevision.SplitDisagreeCount>()) | ||
} | ||
}; | ||
{typeof(SubReplyRevision.SplitAgreeCount), AddSplitRevisions<SubReplyRevision.SplitAgreeCount>}, | ||
Check failure on line 17 in c#/crawler/src/Tieba/Crawl/Saver/Post/SubReplySaver.cs GitHub Actions / build (crawler)
|
||
{typeof(SubReplyRevision.SplitDisagreeCount), AddSplitRevisions<SubReplyRevision.SplitDisagreeCount>}, | ||
Check failure on line 18 in c#/crawler/src/Tieba/Crawl/Saver/Post/SubReplySaver.cs GitHub Actions / build (crawler)
|
||
}); | ||
|
||
protected override Spid RevisionEntityIdSelector(BaseSubReplyRevision entity) => entity.Spid; | ||
protected override Expression<Func<BaseSubReplyRevision, bool>> | ||
IsRevisionEntityIdEqualsExpression(BaseSubReplyRevision newRevision) => | ||
existingRevision => existingRevision.Spid == newRevision.Spid; | ||
|
||
public override bool UserFieldUpdateIgnorance | ||
(string propName, object? oldValue, object? newValue) => propName switch | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,20 +6,23 @@ public class ThreadSaver( | |
ILogger<ThreadSaver> logger, | ||
ConcurrentDictionary<Tid, ThreadPost> posts, | ||
AuthorRevisionSaver.New authorRevisionSaverFactory) | ||
: PostSaver<ThreadPost, BaseThreadRevision>( | ||
: PostSaver<ThreadPost, BaseThreadRevision, Tid>( | ||
logger, posts, authorRevisionSaverFactory, PostType.Thread) | ||
{ | ||
public delegate ThreadSaver New(ConcurrentDictionary<Tid, ThreadPost> posts); | ||
|
||
protected override Dictionary<Type, AddRevisionDelegate> | ||
AddRevisionDelegatesKeyBySplitEntityType { get; } = new() | ||
{ | ||
private Lazy<Dictionary<Type, AddSplitRevisionsDelegate>>? _addSplitRevisionsDelegatesKeyByEntityType; | ||
protected override Lazy<Dictionary<Type, AddSplitRevisionsDelegate>> | ||
AddSplitRevisionsDelegatesKeyByEntityType => | ||
_addSplitRevisionsDelegatesKeyByEntityType ??= new(() => new() | ||
{ | ||
typeof(ThreadRevision.SplitViewCount), (db, revisions) => | ||
db.Set<ThreadRevision.SplitViewCount>() | ||
.AddRange(revisions.OfType<ThreadRevision.SplitViewCount>()) | ||
} | ||
}; | ||
{typeof(ThreadRevision.SplitViewCount), AddSplitRevisions<ThreadRevision.SplitViewCount>} | ||
Check failure on line 19 in c#/crawler/src/Tieba/Crawl/Saver/Post/ThreadSaver.cs GitHub Actions / build (crawler)
|
||
}); | ||
|
||
protected override Tid RevisionEntityIdSelector(BaseThreadRevision entity) => entity.Tid; | ||
protected override Expression<Func<BaseThreadRevision, bool>> | ||
IsRevisionEntityIdEqualsExpression(BaseThreadRevision newRevision) => | ||
existingRevision => existingRevision.Tid == newRevision.Tid; | ||
|
||
public override bool UserFieldUpdateIgnorance | ||
(string propName, object? oldValue, object? newValue) => propName switch | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,25 +4,20 @@ namespace tbm.Crawler.Tieba.Crawl.Saver; | |
|
||
public partial class UserSaver | ||
{ | ||
protected override Dictionary<Type, AddRevisionDelegate> | ||
AddRevisionDelegatesKeyBySplitEntityType { get; } = new() | ||
{ | ||
{ | ||
typeof(UserRevision.SplitDisplayName), (db, revisions) => | ||
db.Set<UserRevision.SplitDisplayName>() | ||
.AddRange(revisions.OfType<UserRevision.SplitDisplayName>()) | ||
}, | ||
{ | ||
typeof(UserRevision.SplitPortraitUpdatedAt), (db, revisions) => | ||
db.Set<UserRevision.SplitPortraitUpdatedAt>() | ||
.AddRange(revisions.OfType<UserRevision.SplitPortraitUpdatedAt>()) | ||
}, | ||
private Lazy<Dictionary<Type, AddSplitRevisionsDelegate>>? _addSplitRevisionsDelegatesKeyByEntityType; | ||
protected override Lazy<Dictionary<Type, AddSplitRevisionsDelegate>> | ||
AddSplitRevisionsDelegatesKeyByEntityType => | ||
_addSplitRevisionsDelegatesKeyByEntityType ??= new(() => new() | ||
{ | ||
typeof(UserRevision.SplitIpGeolocation), (db, revisions) => | ||
db.Set<UserRevision.SplitIpGeolocation>() | ||
.AddRange(revisions.OfType<UserRevision.SplitIpGeolocation>()) | ||
} | ||
}; | ||
{typeof(UserRevision.SplitDisplayName), AddSplitRevisions<UserRevision.SplitDisplayName>}, | ||
Check failure on line 12 in c#/crawler/src/Tieba/Crawl/Saver/UserSaver.cs GitHub Actions / build (crawler)
|
||
{typeof(UserRevision.SplitPortraitUpdatedAt), AddSplitRevisions<UserRevision.SplitPortraitUpdatedAt>}, | ||
Check failure on line 13 in c#/crawler/src/Tieba/Crawl/Saver/UserSaver.cs GitHub Actions / build (crawler)
|
||
{typeof(UserRevision.SplitIpGeolocation), AddSplitRevisions<UserRevision.SplitIpGeolocation>} | ||
}); | ||
|
||
protected override Uid RevisionEntityIdSelector(BaseUserRevision entity) => entity.Uid; | ||
protected override Expression<Func<BaseUserRevision, bool>> | ||
IsRevisionEntityIdEqualsExpression(BaseUserRevision newRevision) => | ||
existingRevision => existingRevision.Uid == newRevision.Uid; | ||
|
||
protected override bool ShouldIgnoreEntityRevision(string propName, PropertyEntry propEntry, EntityEntry entityEntry) | ||
{ | ||
|
@@ -87,7 +82,7 @@ protected override bool FieldRevisionIgnorance | |
public partial class UserSaver( | ||
ILogger<UserSaver> logger, SaverLocks<Uid> locks, | ||
IDictionary<Uid, User> users) | ||
: SaverWithRevision<BaseUserRevision>(logger) | ||
: SaverWithRevision<BaseUserRevision, Uid>(logger) | ||
{ | ||
public delegate UserSaver New(IDictionary<Uid, User> users); | ||
public delegate bool FieldChangeIgnorance(string propName, object? oldValue, object? newValue); | ||
|