diff --git a/Iceshrimp.Backend/Core/Federation/ActivityPub/FederationControlService.cs b/Iceshrimp.Backend/Core/Federation/ActivityPub/FederationControlService.cs index 4729cbbd..11f7c6b8 100644 --- a/Iceshrimp.Backend/Core/Federation/ActivityPub/FederationControlService.cs +++ b/Iceshrimp.Backend/Core/Federation/ActivityPub/FederationControlService.cs @@ -37,12 +37,4 @@ public class FederationControlService( return await db.BlockedInstances.AnyAsync(p => finalHosts.Any(host => host == p.Host || host.EndsWith("." + p.Host))); } - - public async Task ShouldSkipAsync(string host) - { - return await db.Instances.AnyAsync(p => p.Host == host.ToLowerInvariant() && - ((p.IsNotResponding && - p.LastCommunicatedAt < DateTime.UtcNow - TimeSpan.FromDays(7)) || - p.IsSuspended)); - } } \ No newline at end of file diff --git a/Iceshrimp.Backend/Core/Queues/DeliverQueue.cs b/Iceshrimp.Backend/Core/Queues/DeliverQueue.cs index 468533a7..5a72e1b6 100644 --- a/Iceshrimp.Backend/Core/Queues/DeliverQueue.cs +++ b/Iceshrimp.Backend/Core/Queues/DeliverQueue.cs @@ -29,12 +29,6 @@ public class DeliverQueue(int parallelism) return; } - if (await fedCtrl.ShouldSkipAsync(jobData.RecipientHost)) - { - logger.LogDebug("fedCtrl.ShouldSkipAsync returned true, skipping"); - return; - } - logger.LogDebug("Delivering activity to: {uri}", jobData.InboxUrl); var key = await cache.FetchAsync($"userPrivateKey:{jobData.UserId}", TimeSpan.FromMinutes(60), async () => diff --git a/Iceshrimp.Backend/Core/Queues/PreDeliverQueue.cs b/Iceshrimp.Backend/Core/Queues/PreDeliverQueue.cs index e17553d6..1fcea7dd 100644 --- a/Iceshrimp.Backend/Core/Queues/PreDeliverQueue.cs +++ b/Iceshrimp.Backend/Core/Queues/PreDeliverQueue.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using System.Linq.Expressions; using Iceshrimp.Backend.Core.Configuration; using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Database.Tables; @@ -61,6 +62,8 @@ public class PreDeliverQueue(int parallelism) var inboxQueryResults = await query.Where(p => p.InboxUrl != null && p.Host != null) .Distinct() + .SkipDeadInstances(activity, db) + .SkipBlockedInstances(config.Value.FederationMode, db) .ToListAsync(token); if (inboxQueryResults.Count == 0) return; @@ -91,43 +94,74 @@ public class PreDeliverQueue(int parallelism) UserId = jobData.ActorId }); } +} - private class InboxQueryResult : IEquatable +file class InboxQueryResult : IEquatable +{ + public required string? Host; + public required string? InboxUrl; + + public bool Equals(InboxQueryResult? other) { - public required string? Host; - public required string? InboxUrl; + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return InboxUrl == other.InboxUrl && Host == other.Host; + } - public bool Equals(InboxQueryResult? other) - { - if (ReferenceEquals(null, other)) return false; - if (ReferenceEquals(this, other)) return true; - return InboxUrl == other.InboxUrl && Host == other.Host; - } + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != GetType()) return false; + return Equals((InboxQueryResult)obj); + } - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != GetType()) return false; - return Equals((InboxQueryResult)obj); - } + [SuppressMessage("ReSharper", "NonReadonlyMemberInGetHashCode", Justification = + "We are using this as a Tuple that works with LINQ on our IQueryable iterator. This is therefore intended behavior.")] + public override int GetHashCode() + { + return HashCode.Combine(InboxUrl, Host); + } - [SuppressMessage("ReSharper", "NonReadonlyMemberInGetHashCode", Justification = - "We are using this as a Tuple that works with LINQ on our IQueryable iterator. This is therefore intended behavior.")] - public override int GetHashCode() - { - return HashCode.Combine(InboxUrl, Host); - } + public static bool operator ==(InboxQueryResult? left, InboxQueryResult? right) + { + return Equals(left, right); + } - public static bool operator ==(InboxQueryResult? left, InboxQueryResult? right) - { - return Equals(left, right); - } + public static bool operator !=(InboxQueryResult? left, InboxQueryResult? right) + { + return !Equals(left, right); + } +} - public static bool operator !=(InboxQueryResult? left, InboxQueryResult? right) +file static class QueryableExtensions +{ + public static IQueryable SkipDeadInstances( + this IQueryable query, ASActivity activity, DatabaseContext db + ) + { + if (activity is ASFollow) return query; + return query.Where(user => !db.Instances.Any(p => p.Host == user.Host && + ((p.IsNotResponding && + p.LastCommunicatedAt < + DateTime.UtcNow - TimeSpan.FromDays(7)) || + p.IsSuspended))); + } + + public static IQueryable SkipBlockedInstances( + this IQueryable query, Enums.FederationMode mode, DatabaseContext db + ) + { + Expression> expr = mode switch { - return !Equals(left, right); - } + Enums.FederationMode.BlockList => u => + u.Host == null || !db.BlockedInstances.Any(p => u.Host == p.Host || u.Host.EndsWith("." + p.Host)), + Enums.FederationMode.AllowList => u => + u.Host == null || db.AllowedInstances.Any(p => u.Host == p.Host || u.Host.EndsWith("." + p.Host)), + _ => throw new ArgumentOutOfRangeException(nameof(mode), mode, null) + }; + + return query.Where(expr); } }