Skip to content

Commit

Permalink
* replace logging different values of `postRevisioningFieldSelector()…
Browse files Browse the repository at this point in the history
…` that sharing the same key `AuthorUid` of `BasePost` entities with a invoking to `Helper.LogDifferentValuesSharingTheSameKeyInEntities()` @ `AuthorRevisionSaver.Save()`

* replace logging different values of `Signature` that sharing the same key `SignatureId` of `ReplyPost` entities with a invoking to `Helper.LogDifferentValuesSharingTheSameKeyInEntities()` @ `Save()`
* turn record `ReplySignatureProjection` into class `SignatureIdAndValueEqualityComparer` that implements `EqualityComparer<ValueTuple<Nullable<uint>, Array<byte>>`
@ ReplySignatureSaver.cs
@ c#/crawler
  • Loading branch information
n0099 committed Jun 2, 2024
1 parent 4338ccf commit 493f452
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 35 deletions.
18 changes: 18 additions & 0 deletions c#/crawler/src/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,22 @@ public static byte[]? SerializedProtoBufWrapperOrNullIfEmpty<T>

public static PostContentWrapper? WrapPostContent(IEnumerable<Content>? contents) =>
contents == null ? null : new() {Value = {contents}};

public static void LogDifferentValuesSharingTheSameKeyInEntities<TLoggerCategory, TEntity, TKey, TValue>(
ILogger<TLoggerCategory> logger,
IEnumerable<TEntity> entities,
string keyName,
Func<TEntity, TKey?> keySelector,
Func<TEntity, TValue?> valueSelector,
IEqualityComparer<(TKey?, TValue?)>? keyAndValueComparer = null) => entities
.GroupBy(keySelector)
.Where(g => g.Count() > 1)
.Flatten2()
.GroupBy(p => (keySelector(p), valueSelector(p)), comparer: keyAndValueComparer)
.GroupBy(g => g.Key.Item1)
.Where(gg => gg.Count() > 1)
.Flatten2()
.ForEach(g => logger.LogWarning(
"Multiple entities with different value of field {} sharing the same key \"{}\": {}",
keyName, g.Key, SharedHelper.UnescapedJsonSerialize(g)));
}
18 changes: 5 additions & 13 deletions c#/crawler/src/Tieba/Crawl/Saver/AuthorRevisionSaver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,11 @@ private void Save<TPost, TRevision, TValue>(
where TRevision : AuthorRevision
{ // only takes the first of multiple post from the same author
var uniquePosts = posts.DistinctBy(p => p.AuthorUid).ToList();
if (uniquePosts.Count != posts.Count) (
from p in posts
group p by p.AuthorUid into g
where g.Count() > 1
from p in g
group p by (p.AuthorUid, postRevisioningFieldSelector(p)) into g
group g by g.Key.AuthorUid into gg
where gg.Count() > 1
from g in gg
select g)
.ForEach(g => logger.LogWarning(
"Multiple entities with different value of revisioning field sharing the same TPost.AuthorUid {}: {}",
g.Key, SharedHelper.UnescapedJsonSerialize(g)));
if (uniquePosts.Count != posts.Count)
Helper.LogDifferentValuesSharingTheSameKeyInEntities(logger, posts,
$"{nameof(TPost)}.{nameof(BasePost.AuthorUid)}",
p => p.AuthorUid,
postRevisioningFieldSelector);

SharedHelper.GetNowTimestamp(out var now);
var existingRevisionOfExistingUsers = dbSet.AsNoTracking()
Expand Down
41 changes: 19 additions & 22 deletions c#/crawler/src/Tieba/Crawl/Saver/ReplySignatureSaver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,15 @@ public Action Save(CrawlerDbContext db, IEnumerable<ReplyPost> replies)
}).ToList();
if (signatures.Count == 0) return () => { };
if (signatures.Count != repliesWithSignature
.GroupBy(r => new ReplySignatureProjection(r.SignatureId!.Value, r.Signature!))
.Count()) (
from r in repliesWithSignature
group r by r.SignatureId into g
where g.Count() > 1
from r in g
group r by new ReplySignatureProjection(r.SignatureId!.Value, r.Signature!) into g
group g by g.Key.SignatureId into gg
where gg.Count() > 1
from g in gg
select g)
.ForEach(g => logger.LogWarning(
"Multiple entities with different value of revisioning field sharing the same signature id {}: {}",
g.Key.SignatureId, SharedHelper.UnescapedJsonSerialize(g)));
.GroupBy(r => (r.SignatureId!.Value, r.Signature!),
comparer: SignatureIdAndValueEqualityComparer.Instance)
.Count())
Helper.LogDifferentValuesSharingTheSameKeyInEntities(logger,
repliesWithSignature,
nameof(ReplyPost.SignatureId),
r => r.SignatureId,
r => r.Signature,
SignatureIdAndValueEqualityComparer.Instance);

var existingSignatures = (
from s in db.ReplySignatures.AsTracking()
Expand All @@ -63,18 +58,20 @@ join newInReply in signatures on existing.SignatureId equals newInReply.Signatur
return locks.Dispose;
}

private sealed record ReplySignatureProjection(uint SignatureId, byte[] Signature)
private class SignatureIdAndValueEqualityComparer : EqualityComparer<(uint? SignatureId, byte[]? Signature)>

Check failure on line 61 in c#/crawler/src/Tieba/Crawl/Saver/ReplySignatureSaver.cs

View workflow job for this annotation

GitHub Actions / build (crawler)

Private classes which are not derived in the current assembly should be marked as 'sealed'. (https://rules.sonarsource.com/csharp/RSPEC-3260)

Check failure on line 61 in c#/crawler/src/Tieba/Crawl/Saver/ReplySignatureSaver.cs

View workflow job for this annotation

GitHub Actions / build (crawler)

Type 'SignatureIdAndValueEqualityComparer' contains the word 'and', which suggests it has multiple purposes (https://github.com/dennisdoomen/CSharpGuidelines/blob/5.7.0/_rules/1000.md)

Check failure on line 61 in c#/crawler/src/Tieba/Crawl/Saver/ReplySignatureSaver.cs

View workflow job for this annotation

GitHub Actions / build (crawler)

Type 'SignatureIdAndValueEqualityComparer' can be sealed because it has no subtypes in its containing assembly and is not externally visible (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1852)

Check failure on line 61 in c#/crawler/src/Tieba/Crawl/Saver/ReplySignatureSaver.cs

View workflow job for this annotation

GitHub Actions / build (crawler)

Private classes which are not derived in the current assembly should be marked as 'sealed'. (https://rules.sonarsource.com/csharp/RSPEC-3260)

Check failure on line 61 in c#/crawler/src/Tieba/Crawl/Saver/ReplySignatureSaver.cs

View workflow job for this annotation

GitHub Actions / build (crawler)

Type 'SignatureIdAndValueEqualityComparer' contains the word 'and', which suggests it has multiple purposes (https://github.com/dennisdoomen/CSharpGuidelines/blob/5.7.0/_rules/1000.md)

Check failure on line 61 in c#/crawler/src/Tieba/Crawl/Saver/ReplySignatureSaver.cs

View workflow job for this annotation

GitHub Actions / build (crawler)

Type 'SignatureIdAndValueEqualityComparer' can be sealed because it has no subtypes in its containing assembly and is not externally visible (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1852)
{
public bool Equals(ReplySignatureProjection? other) =>
other != null
&& SignatureId == other.SignatureId
&& ByteArrayEqualityComparer.Instance.Equals(Signature, other.Signature);
public static SignatureIdAndValueEqualityComparer Instance { get; } = new();

public override int GetHashCode()
public override bool Equals((uint? SignatureId, byte[]? Signature) x, (uint? SignatureId, byte[]? Signature) y) =>
x == y ||
(x.SignatureId == y.SignatureId
&& ByteArrayEqualityComparer.Instance.Equals(x.Signature, y.Signature));

public override int GetHashCode((uint? SignatureId, byte[]? Signature) obj)
{
var hash = default(HashCode);
hash.Add(SignatureId);
hash.AddBytes(Signature);
hash.Add(obj.SignatureId);
hash.AddBytes(obj.Signature);
return hash.ToHashCode();
}
}
Expand Down

0 comments on commit 493f452

Please sign in to comment.