Merge pull request #130 from NicolasConstant/topic_purge-failing-users
Topic purge failing users
This commit is contained in:
commit
18e0397efe
8 changed files with 346 additions and 16 deletions
|
@ -49,6 +49,7 @@ If both whitelisting and blacklisting are set, only the whitelisting will be act
|
||||||
* `Instance:UnlistedTwitterAccounts` (default: null) to enable unlisted publication for selected twitter accounts, separated by `;` (please limit this to brands and other public profiles).
|
* `Instance:UnlistedTwitterAccounts` (default: null) to enable unlisted publication for selected twitter accounts, separated by `;` (please limit this to brands and other public profiles).
|
||||||
* `Instance:SensitiveTwitterAccounts` (default: null) mark all media from given accounts as sensitive by default, separated by `;`.
|
* `Instance:SensitiveTwitterAccounts` (default: null) mark all media from given accounts as sensitive by default, separated by `;`.
|
||||||
* `Instance:FailingTwitterUserCleanUpThreshold` (default: 700) set the max allowed errors (due to a banned/deleted/private account) from a Twitter Account retrieval before auto-removal. (by default an account is called every 15 mins)
|
* `Instance:FailingTwitterUserCleanUpThreshold` (default: 700) set the max allowed errors (due to a banned/deleted/private account) from a Twitter Account retrieval before auto-removal. (by default an account is called every 15 mins)
|
||||||
|
* `Instance:FailingFollowerCleanUpThreshold` (default: 30000) set the max allowed errors from a Follower (Fediverse) Account before auto-removal. (often due to account suppression, instance issues, etc)
|
||||||
|
|
||||||
# Docker Compose full example
|
# Docker Compose full example
|
||||||
|
|
||||||
|
|
|
@ -13,5 +13,6 @@
|
||||||
public string SensitiveTwitterAccounts { get; set; }
|
public string SensitiveTwitterAccounts { get; set; }
|
||||||
|
|
||||||
public int FailingTwitterUserCleanUpThreshold { get; set; }
|
public int FailingTwitterUserCleanUpThreshold { get; set; }
|
||||||
|
public int FailingFollowerCleanUpThreshold { get; set; } = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,11 @@ using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
using BirdsiteLive.Common.Settings;
|
||||||
using BirdsiteLive.DAL.Contracts;
|
using BirdsiteLive.DAL.Contracts;
|
||||||
using BirdsiteLive.DAL.Models;
|
using BirdsiteLive.DAL.Models;
|
||||||
using BirdsiteLive.Domain;
|
using BirdsiteLive.Domain;
|
||||||
|
using BirdsiteLive.Moderation.Actions;
|
||||||
using BirdsiteLive.Pipeline.Contracts;
|
using BirdsiteLive.Pipeline.Contracts;
|
||||||
using BirdsiteLive.Pipeline.Models;
|
using BirdsiteLive.Pipeline.Models;
|
||||||
using BirdsiteLive.Pipeline.Processors.SubTasks;
|
using BirdsiteLive.Pipeline.Processors.SubTasks;
|
||||||
|
@ -23,14 +25,18 @@ namespace BirdsiteLive.Pipeline.Processors
|
||||||
private readonly ISendTweetsToInboxTask _sendTweetsToInboxTask;
|
private readonly ISendTweetsToInboxTask _sendTweetsToInboxTask;
|
||||||
private readonly ISendTweetsToSharedInboxTask _sendTweetsToSharedInbox;
|
private readonly ISendTweetsToSharedInboxTask _sendTweetsToSharedInbox;
|
||||||
private readonly IFollowersDal _followersDal;
|
private readonly IFollowersDal _followersDal;
|
||||||
|
private readonly InstanceSettings _instanceSettings;
|
||||||
private readonly ILogger<SendTweetsToFollowersProcessor> _logger;
|
private readonly ILogger<SendTweetsToFollowersProcessor> _logger;
|
||||||
|
private readonly IRemoveFollowerAction _removeFollowerAction;
|
||||||
|
|
||||||
#region Ctor
|
#region Ctor
|
||||||
public SendTweetsToFollowersProcessor(ISendTweetsToInboxTask sendTweetsToInboxTask, ISendTweetsToSharedInboxTask sendTweetsToSharedInbox, IFollowersDal followersDal, ILogger<SendTweetsToFollowersProcessor> logger)
|
public SendTweetsToFollowersProcessor(ISendTweetsToInboxTask sendTweetsToInboxTask, ISendTweetsToSharedInboxTask sendTweetsToSharedInbox, IFollowersDal followersDal, ILogger<SendTweetsToFollowersProcessor> logger, InstanceSettings instanceSettings, IRemoveFollowerAction removeFollowerAction)
|
||||||
{
|
{
|
||||||
_sendTweetsToInboxTask = sendTweetsToInboxTask;
|
_sendTweetsToInboxTask = sendTweetsToInboxTask;
|
||||||
_sendTweetsToSharedInbox = sendTweetsToSharedInbox;
|
_sendTweetsToSharedInbox = sendTweetsToSharedInbox;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_instanceSettings = instanceSettings;
|
||||||
|
_removeFollowerAction = removeFollowerAction;
|
||||||
_followersDal = followersDal;
|
_followersDal = followersDal;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -107,7 +113,17 @@ namespace BirdsiteLive.Pipeline.Processors
|
||||||
private async Task ProcessFailingUserAsync(Follower follower)
|
private async Task ProcessFailingUserAsync(Follower follower)
|
||||||
{
|
{
|
||||||
follower.PostingErrorCount++;
|
follower.PostingErrorCount++;
|
||||||
await _followersDal.UpdateFollowerAsync(follower);
|
|
||||||
|
if (follower.PostingErrorCount > _instanceSettings.FailingFollowerCleanUpThreshold
|
||||||
|
&& _instanceSettings.FailingFollowerCleanUpThreshold > 0
|
||||||
|
|| follower.PostingErrorCount > 2147483600)
|
||||||
|
{
|
||||||
|
await _removeFollowerAction.ProcessAsync(follower);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await _followersDal.UpdateFollowerAsync(follower);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -23,7 +23,8 @@
|
||||||
"MaxUsersCapacity": 1000,
|
"MaxUsersCapacity": 1000,
|
||||||
"UnlistedTwitterAccounts": null,
|
"UnlistedTwitterAccounts": null,
|
||||||
"SensitiveTwitterAccounts": null,
|
"SensitiveTwitterAccounts": null,
|
||||||
"FailingTwitterUserCleanUpThreshold": 700
|
"FailingTwitterUserCleanUpThreshold": 700,
|
||||||
|
"FailingFollowerCleanUpThreshold": 30000
|
||||||
},
|
},
|
||||||
"Db": {
|
"Db": {
|
||||||
"Type": "postgres",
|
"Type": "postgres",
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers
|
||||||
public class DbInitializerPostgresDal : PostgresBase, IDbInitializerDal
|
public class DbInitializerPostgresDal : PostgresBase, IDbInitializerDal
|
||||||
{
|
{
|
||||||
private readonly PostgresTools _tools;
|
private readonly PostgresTools _tools;
|
||||||
private readonly Version _currentVersion = new Version(2, 3);
|
private readonly Version _currentVersion = new Version(2, 4);
|
||||||
private const string DbVersionType = "db-version";
|
private const string DbVersionType = "db-version";
|
||||||
|
|
||||||
#region Ctor
|
#region Ctor
|
||||||
|
@ -134,7 +134,8 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers
|
||||||
new Tuple<Version, Version>(new Version(1,0), new Version(2,0)),
|
new Tuple<Version, Version>(new Version(1,0), new Version(2,0)),
|
||||||
new Tuple<Version, Version>(new Version(2,0), new Version(2,1)),
|
new Tuple<Version, Version>(new Version(2,0), new Version(2,1)),
|
||||||
new Tuple<Version, Version>(new Version(2,1), new Version(2,2)),
|
new Tuple<Version, Version>(new Version(2,1), new Version(2,2)),
|
||||||
new Tuple<Version, Version>(new Version(2,2), new Version(2,3))
|
new Tuple<Version, Version>(new Version(2,2), new Version(2,3)),
|
||||||
|
new Tuple<Version, Version>(new Version(2,3), new Version(2,4))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,6 +164,14 @@ namespace BirdsiteLive.DAL.Postgres.DataAccessLayers
|
||||||
var addPostingError = $@"ALTER TABLE {_settings.FollowersTableName} ADD postingErrorCount SMALLINT";
|
var addPostingError = $@"ALTER TABLE {_settings.FollowersTableName} ADD postingErrorCount SMALLINT";
|
||||||
await _tools.ExecuteRequestAsync(addPostingError);
|
await _tools.ExecuteRequestAsync(addPostingError);
|
||||||
}
|
}
|
||||||
|
else if (from == new Version(2, 3) && to == new Version(2, 4))
|
||||||
|
{
|
||||||
|
var alterLastSync = $@"ALTER TABLE {_settings.TwitterUserTableName} ALTER COLUMN fetchingErrorCount TYPE INTEGER";
|
||||||
|
await _tools.ExecuteRequestAsync(alterLastSync);
|
||||||
|
|
||||||
|
var alterPostingError = $@"ALTER TABLE {_settings.FollowersTableName} ALTER COLUMN postingErrorCount TYPE INTEGER";
|
||||||
|
await _tools.ExecuteRequestAsync(alterPostingError);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
|
|
|
@ -340,6 +340,48 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers
|
||||||
Assert.AreEqual(10, result.PostingErrorCount);
|
Assert.AreEqual(10, result.PostingErrorCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public async Task CreateUpdateAndGetFollower_Integer()
|
||||||
|
{
|
||||||
|
var acct = "myhandle";
|
||||||
|
var host = "domain.ext";
|
||||||
|
var following = new[] { 12, 19, 23 };
|
||||||
|
var followingSync = new Dictionary<int, long>()
|
||||||
|
{
|
||||||
|
{12, 165L},
|
||||||
|
{19, 166L},
|
||||||
|
{23, 167L}
|
||||||
|
};
|
||||||
|
var inboxRoute = "/myhandle/inbox";
|
||||||
|
var sharedInboxRoute = "/inbox";
|
||||||
|
var actorId = $"https://{host}/{acct}";
|
||||||
|
|
||||||
|
var dal = new FollowersPostgresDal(_settings);
|
||||||
|
await dal.CreateFollowerAsync(acct, host, inboxRoute, sharedInboxRoute, actorId, following, followingSync);
|
||||||
|
var result = await dal.GetFollowerAsync(acct, host);
|
||||||
|
|
||||||
|
var updatedFollowing = new List<int> { 12, 19, 23, 24 };
|
||||||
|
var updatedFollowingSync = new Dictionary<int, long>(){
|
||||||
|
{12, 170L},
|
||||||
|
{19, 171L},
|
||||||
|
{23, 172L},
|
||||||
|
{24, 173L}
|
||||||
|
};
|
||||||
|
result.Followings = updatedFollowing.ToList();
|
||||||
|
result.FollowingsSyncStatus = updatedFollowingSync;
|
||||||
|
result.PostingErrorCount = 32768;
|
||||||
|
|
||||||
|
await dal.UpdateFollowerAsync(result);
|
||||||
|
result = await dal.GetFollowerAsync(acct, host);
|
||||||
|
|
||||||
|
Assert.AreEqual(updatedFollowing.Count, result.Followings.Count);
|
||||||
|
Assert.AreEqual(updatedFollowing[0], result.Followings[0]);
|
||||||
|
Assert.AreEqual(updatedFollowingSync.Count, result.FollowingsSyncStatus.Count);
|
||||||
|
Assert.AreEqual(updatedFollowingSync.First().Key, result.FollowingsSyncStatus.First().Key);
|
||||||
|
Assert.AreEqual(updatedFollowingSync.First().Value, result.FollowingsSyncStatus.First().Value);
|
||||||
|
Assert.AreEqual(32768, result.PostingErrorCount);
|
||||||
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public async Task CreateUpdateAndGetFollower_Remove()
|
public async Task CreateUpdateAndGetFollower_Remove()
|
||||||
{
|
{
|
||||||
|
|
|
@ -130,6 +130,38 @@ namespace BirdsiteLive.DAL.Postgres.Tests.DataAccessLayers
|
||||||
Assert.IsTrue(Math.Abs((now.ToUniversalTime() - result.LastSync).Milliseconds) < 100);
|
Assert.IsTrue(Math.Abs((now.ToUniversalTime() - result.LastSync).Milliseconds) < 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public async Task CreateUpdate3AndGetUser()
|
||||||
|
{
|
||||||
|
var acct = "myid";
|
||||||
|
var lastTweetId = 1548L;
|
||||||
|
|
||||||
|
var dal = new TwitterUserPostgresDal(_settings);
|
||||||
|
|
||||||
|
await dal.CreateTwitterUserAsync(acct, lastTweetId);
|
||||||
|
var result = await dal.GetTwitterUserAsync(acct);
|
||||||
|
|
||||||
|
|
||||||
|
var updatedLastTweetId = 1600L;
|
||||||
|
var updatedLastSyncId = 1550L;
|
||||||
|
var now = DateTime.Now;
|
||||||
|
var errors = 32768;
|
||||||
|
|
||||||
|
result.LastTweetPostedId = updatedLastTweetId;
|
||||||
|
result.LastTweetSynchronizedForAllFollowersId = updatedLastSyncId;
|
||||||
|
result.FetchingErrorCount = errors;
|
||||||
|
result.LastSync = now;
|
||||||
|
await dal.UpdateTwitterUserAsync(result);
|
||||||
|
|
||||||
|
result = await dal.GetTwitterUserAsync(acct);
|
||||||
|
|
||||||
|
Assert.AreEqual(acct, result.Acct);
|
||||||
|
Assert.AreEqual(updatedLastTweetId, result.LastTweetPostedId);
|
||||||
|
Assert.AreEqual(updatedLastSyncId, result.LastTweetSynchronizedForAllFollowersId);
|
||||||
|
Assert.AreEqual(errors, result.FetchingErrorCount);
|
||||||
|
Assert.IsTrue(Math.Abs((now.ToUniversalTime() - result.LastSync).Milliseconds) < 100);
|
||||||
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
[ExpectedException(typeof(ArgumentException))]
|
[ExpectedException(typeof(ArgumentException))]
|
||||||
public async Task Update_NoId()
|
public async Task Update_NoId()
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
using BirdsiteLive.Common.Settings;
|
||||||
using BirdsiteLive.DAL.Contracts;
|
using BirdsiteLive.DAL.Contracts;
|
||||||
using BirdsiteLive.DAL.Models;
|
using BirdsiteLive.DAL.Models;
|
||||||
|
using BirdsiteLive.Moderation.Actions;
|
||||||
using BirdsiteLive.Pipeline.Models;
|
using BirdsiteLive.Pipeline.Models;
|
||||||
using BirdsiteLive.Pipeline.Processors;
|
using BirdsiteLive.Pipeline.Processors;
|
||||||
using BirdsiteLive.Pipeline.Processors.SubTasks;
|
using BirdsiteLive.Pipeline.Processors.SubTasks;
|
||||||
|
@ -72,17 +74,22 @@ namespace BirdsiteLive.Pipeline.Tests.Processors
|
||||||
.Returns(Task.CompletedTask);
|
.Returns(Task.CompletedTask);
|
||||||
|
|
||||||
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
|
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
|
||||||
|
|
||||||
var loggerMock = new Mock<ILogger<SendTweetsToFollowersProcessor>>();
|
var loggerMock = new Mock<ILogger<SendTweetsToFollowersProcessor>>();
|
||||||
|
|
||||||
|
var settings = new InstanceSettings();
|
||||||
|
|
||||||
|
var removeFollowerMock = new Mock<IRemoveFollowerAction>(MockBehavior.Strict);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object);
|
var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object);
|
||||||
var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None);
|
var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None);
|
||||||
|
|
||||||
#region Validations
|
#region Validations
|
||||||
sendTweetsToInboxTaskMock.VerifyAll();
|
sendTweetsToInboxTaskMock.VerifyAll();
|
||||||
sendTweetsToSharedInboxTaskMock.VerifyAll();
|
sendTweetsToSharedInboxTaskMock.VerifyAll();
|
||||||
followersDalMock.VerifyAll();
|
followersDalMock.VerifyAll();
|
||||||
|
removeFollowerMock.VerifyAll();
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,15 +154,20 @@ namespace BirdsiteLive.Pipeline.Tests.Processors
|
||||||
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
|
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
|
||||||
|
|
||||||
var loggerMock = new Mock<ILogger<SendTweetsToFollowersProcessor>>();
|
var loggerMock = new Mock<ILogger<SendTweetsToFollowersProcessor>>();
|
||||||
|
|
||||||
|
var settings = new InstanceSettings();
|
||||||
|
|
||||||
|
var removeFollowerMock = new Mock<IRemoveFollowerAction>(MockBehavior.Strict);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object);
|
var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object);
|
||||||
var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None);
|
var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None);
|
||||||
|
|
||||||
#region Validations
|
#region Validations
|
||||||
sendTweetsToInboxTaskMock.VerifyAll();
|
sendTweetsToInboxTaskMock.VerifyAll();
|
||||||
sendTweetsToSharedInboxTaskMock.VerifyAll();
|
sendTweetsToSharedInboxTaskMock.VerifyAll();
|
||||||
followersDalMock.VerifyAll();
|
followersDalMock.VerifyAll();
|
||||||
|
removeFollowerMock.VerifyAll();
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,15 +241,20 @@ namespace BirdsiteLive.Pipeline.Tests.Processors
|
||||||
.Returns(Task.CompletedTask);
|
.Returns(Task.CompletedTask);
|
||||||
|
|
||||||
var loggerMock = new Mock<ILogger<SendTweetsToFollowersProcessor>>();
|
var loggerMock = new Mock<ILogger<SendTweetsToFollowersProcessor>>();
|
||||||
|
|
||||||
|
var settings = new InstanceSettings();
|
||||||
|
|
||||||
|
var removeFollowerMock = new Mock<IRemoveFollowerAction>(MockBehavior.Strict);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object);
|
var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object);
|
||||||
var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None);
|
var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None);
|
||||||
|
|
||||||
#region Validations
|
#region Validations
|
||||||
sendTweetsToInboxTaskMock.VerifyAll();
|
sendTweetsToInboxTaskMock.VerifyAll();
|
||||||
sendTweetsToSharedInboxTaskMock.VerifyAll();
|
sendTweetsToSharedInboxTaskMock.VerifyAll();
|
||||||
followersDalMock.VerifyAll();
|
followersDalMock.VerifyAll();
|
||||||
|
removeFollowerMock.VerifyAll();
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,15 +329,20 @@ namespace BirdsiteLive.Pipeline.Tests.Processors
|
||||||
.Returns(Task.CompletedTask);
|
.Returns(Task.CompletedTask);
|
||||||
|
|
||||||
var loggerMock = new Mock<ILogger<SendTweetsToFollowersProcessor>>();
|
var loggerMock = new Mock<ILogger<SendTweetsToFollowersProcessor>>();
|
||||||
|
|
||||||
|
var settings = new InstanceSettings();
|
||||||
|
|
||||||
|
var removeFollowerMock = new Mock<IRemoveFollowerAction>(MockBehavior.Strict);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object);
|
var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object);
|
||||||
var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None);
|
var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None);
|
||||||
|
|
||||||
#region Validations
|
#region Validations
|
||||||
sendTweetsToInboxTaskMock.VerifyAll();
|
sendTweetsToInboxTaskMock.VerifyAll();
|
||||||
sendTweetsToSharedInboxTaskMock.VerifyAll();
|
sendTweetsToSharedInboxTaskMock.VerifyAll();
|
||||||
followersDalMock.VerifyAll();
|
followersDalMock.VerifyAll();
|
||||||
|
removeFollowerMock.VerifyAll();
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,15 +422,20 @@ namespace BirdsiteLive.Pipeline.Tests.Processors
|
||||||
.Returns(Task.CompletedTask);
|
.Returns(Task.CompletedTask);
|
||||||
|
|
||||||
var loggerMock = new Mock<ILogger<SendTweetsToFollowersProcessor>>();
|
var loggerMock = new Mock<ILogger<SendTweetsToFollowersProcessor>>();
|
||||||
|
|
||||||
|
var settings = new InstanceSettings();
|
||||||
|
|
||||||
|
var removeFollowerMock = new Mock<IRemoveFollowerAction>(MockBehavior.Strict);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object);
|
var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object);
|
||||||
var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None);
|
var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None);
|
||||||
|
|
||||||
#region Validations
|
#region Validations
|
||||||
sendTweetsToInboxTaskMock.VerifyAll();
|
sendTweetsToInboxTaskMock.VerifyAll();
|
||||||
sendTweetsToSharedInboxTaskMock.VerifyAll();
|
sendTweetsToSharedInboxTaskMock.VerifyAll();
|
||||||
followersDalMock.VerifyAll();
|
followersDalMock.VerifyAll();
|
||||||
|
removeFollowerMock.VerifyAll();
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,15 +498,20 @@ namespace BirdsiteLive.Pipeline.Tests.Processors
|
||||||
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
|
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
|
||||||
|
|
||||||
var loggerMock = new Mock<ILogger<SendTweetsToFollowersProcessor>>();
|
var loggerMock = new Mock<ILogger<SendTweetsToFollowersProcessor>>();
|
||||||
|
|
||||||
|
var settings = new InstanceSettings();
|
||||||
|
|
||||||
|
var removeFollowerMock = new Mock<IRemoveFollowerAction>(MockBehavior.Strict);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object);
|
var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object);
|
||||||
var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None);
|
var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None);
|
||||||
|
|
||||||
#region Validations
|
#region Validations
|
||||||
sendTweetsToInboxTaskMock.VerifyAll();
|
sendTweetsToInboxTaskMock.VerifyAll();
|
||||||
sendTweetsToSharedInboxTaskMock.VerifyAll();
|
sendTweetsToSharedInboxTaskMock.VerifyAll();
|
||||||
followersDalMock.VerifyAll();
|
followersDalMock.VerifyAll();
|
||||||
|
removeFollowerMock.VerifyAll();
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -543,15 +575,20 @@ namespace BirdsiteLive.Pipeline.Tests.Processors
|
||||||
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
|
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
|
||||||
|
|
||||||
var loggerMock = new Mock<ILogger<SendTweetsToFollowersProcessor>>();
|
var loggerMock = new Mock<ILogger<SendTweetsToFollowersProcessor>>();
|
||||||
|
|
||||||
|
var settings = new InstanceSettings();
|
||||||
|
|
||||||
|
var removeFollowerMock = new Mock<IRemoveFollowerAction>(MockBehavior.Strict);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object);
|
var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object);
|
||||||
var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None);
|
var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None);
|
||||||
|
|
||||||
#region Validations
|
#region Validations
|
||||||
sendTweetsToInboxTaskMock.VerifyAll();
|
sendTweetsToInboxTaskMock.VerifyAll();
|
||||||
sendTweetsToSharedInboxTaskMock.VerifyAll();
|
sendTweetsToSharedInboxTaskMock.VerifyAll();
|
||||||
followersDalMock.VerifyAll();
|
followersDalMock.VerifyAll();
|
||||||
|
removeFollowerMock.VerifyAll();
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -623,15 +660,196 @@ namespace BirdsiteLive.Pipeline.Tests.Processors
|
||||||
.Returns(Task.CompletedTask);
|
.Returns(Task.CompletedTask);
|
||||||
|
|
||||||
var loggerMock = new Mock<ILogger<SendTweetsToFollowersProcessor>>();
|
var loggerMock = new Mock<ILogger<SendTweetsToFollowersProcessor>>();
|
||||||
|
|
||||||
|
var settings = new InstanceSettings();
|
||||||
|
|
||||||
|
var removeFollowerMock = new Mock<IRemoveFollowerAction>(MockBehavior.Strict);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object);
|
var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object);
|
||||||
var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None);
|
var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None);
|
||||||
|
|
||||||
#region Validations
|
#region Validations
|
||||||
sendTweetsToInboxTaskMock.VerifyAll();
|
sendTweetsToInboxTaskMock.VerifyAll();
|
||||||
sendTweetsToSharedInboxTaskMock.VerifyAll();
|
sendTweetsToSharedInboxTaskMock.VerifyAll();
|
||||||
followersDalMock.VerifyAll();
|
followersDalMock.VerifyAll();
|
||||||
|
removeFollowerMock.VerifyAll();
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public async Task ProcessAsync_MultiInstances_Inbox_OneTweet_Error_SettingsThreshold_Test()
|
||||||
|
{
|
||||||
|
#region Stubs
|
||||||
|
var tweetId = 1;
|
||||||
|
var host1 = "domain1.ext";
|
||||||
|
var host2 = "domain2.ext";
|
||||||
|
var inbox = "/user/inbox";
|
||||||
|
var userId1 = 2;
|
||||||
|
var userId2 = 3;
|
||||||
|
var userAcct = "user";
|
||||||
|
|
||||||
|
var userWithTweets = new UserWithDataToSync()
|
||||||
|
{
|
||||||
|
Tweets = new[]
|
||||||
|
{
|
||||||
|
new ExtractedTweet
|
||||||
|
{
|
||||||
|
Id = tweetId
|
||||||
|
}
|
||||||
|
},
|
||||||
|
User = new SyncTwitterUser
|
||||||
|
{
|
||||||
|
Acct = userAcct
|
||||||
|
},
|
||||||
|
Followers = new[]
|
||||||
|
{
|
||||||
|
new Follower
|
||||||
|
{
|
||||||
|
Id = userId1,
|
||||||
|
Host = host1,
|
||||||
|
InboxRoute = inbox
|
||||||
|
},
|
||||||
|
new Follower
|
||||||
|
{
|
||||||
|
Id = userId2,
|
||||||
|
Host = host2,
|
||||||
|
InboxRoute = inbox,
|
||||||
|
PostingErrorCount = 42
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Mocks
|
||||||
|
var sendTweetsToInboxTaskMock = new Mock<ISendTweetsToInboxTask>(MockBehavior.Strict);
|
||||||
|
sendTweetsToInboxTaskMock
|
||||||
|
.Setup(x => x.ExecuteAsync(
|
||||||
|
It.Is<ExtractedTweet[]>(y => y.Length == 1),
|
||||||
|
It.Is<Follower>(y => y.Id == userId1),
|
||||||
|
It.Is<SyncTwitterUser>(y => y.Acct == userAcct)))
|
||||||
|
.Returns(Task.CompletedTask);
|
||||||
|
|
||||||
|
sendTweetsToInboxTaskMock
|
||||||
|
.Setup(x => x.ExecuteAsync(
|
||||||
|
It.Is<ExtractedTweet[]>(y => y.Length == 1),
|
||||||
|
It.Is<Follower>(y => y.Id == userId2),
|
||||||
|
It.Is<SyncTwitterUser>(y => y.Acct == userAcct)))
|
||||||
|
.Throws(new Exception());
|
||||||
|
|
||||||
|
var sendTweetsToSharedInboxTaskMock = new Mock<ISendTweetsToSharedInboxTask>(MockBehavior.Strict);
|
||||||
|
|
||||||
|
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
|
||||||
|
|
||||||
|
var loggerMock = new Mock<ILogger<SendTweetsToFollowersProcessor>>();
|
||||||
|
|
||||||
|
var settings = new InstanceSettings
|
||||||
|
{
|
||||||
|
FailingFollowerCleanUpThreshold = 10
|
||||||
|
};
|
||||||
|
|
||||||
|
var removeFollowerMock = new Mock<IRemoveFollowerAction>(MockBehavior.Strict);
|
||||||
|
removeFollowerMock
|
||||||
|
.Setup(x => x.ProcessAsync(It.Is<Follower>(y => y.Id == userId2)))
|
||||||
|
.Returns(Task.CompletedTask);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object);
|
||||||
|
var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None);
|
||||||
|
|
||||||
|
#region Validations
|
||||||
|
sendTweetsToInboxTaskMock.VerifyAll();
|
||||||
|
sendTweetsToSharedInboxTaskMock.VerifyAll();
|
||||||
|
followersDalMock.VerifyAll();
|
||||||
|
removeFollowerMock.VerifyAll();
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public async Task ProcessAsync_MultiInstances_Inbox_OneTweet_Error_MaxThreshold_Test()
|
||||||
|
{
|
||||||
|
#region Stubs
|
||||||
|
var tweetId = 1;
|
||||||
|
var host1 = "domain1.ext";
|
||||||
|
var host2 = "domain2.ext";
|
||||||
|
var inbox = "/user/inbox";
|
||||||
|
var userId1 = 2;
|
||||||
|
var userId2 = 3;
|
||||||
|
var userAcct = "user";
|
||||||
|
|
||||||
|
var userWithTweets = new UserWithDataToSync()
|
||||||
|
{
|
||||||
|
Tweets = new[]
|
||||||
|
{
|
||||||
|
new ExtractedTweet
|
||||||
|
{
|
||||||
|
Id = tweetId
|
||||||
|
}
|
||||||
|
},
|
||||||
|
User = new SyncTwitterUser
|
||||||
|
{
|
||||||
|
Acct = userAcct
|
||||||
|
},
|
||||||
|
Followers = new[]
|
||||||
|
{
|
||||||
|
new Follower
|
||||||
|
{
|
||||||
|
Id = userId1,
|
||||||
|
Host = host1,
|
||||||
|
InboxRoute = inbox
|
||||||
|
},
|
||||||
|
new Follower
|
||||||
|
{
|
||||||
|
Id = userId2,
|
||||||
|
Host = host2,
|
||||||
|
InboxRoute = inbox,
|
||||||
|
PostingErrorCount = 2147483600
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Mocks
|
||||||
|
var sendTweetsToInboxTaskMock = new Mock<ISendTweetsToInboxTask>(MockBehavior.Strict);
|
||||||
|
sendTweetsToInboxTaskMock
|
||||||
|
.Setup(x => x.ExecuteAsync(
|
||||||
|
It.Is<ExtractedTweet[]>(y => y.Length == 1),
|
||||||
|
It.Is<Follower>(y => y.Id == userId1),
|
||||||
|
It.Is<SyncTwitterUser>(y => y.Acct == userAcct)))
|
||||||
|
.Returns(Task.CompletedTask);
|
||||||
|
|
||||||
|
sendTweetsToInboxTaskMock
|
||||||
|
.Setup(x => x.ExecuteAsync(
|
||||||
|
It.Is<ExtractedTweet[]>(y => y.Length == 1),
|
||||||
|
It.Is<Follower>(y => y.Id == userId2),
|
||||||
|
It.Is<SyncTwitterUser>(y => y.Acct == userAcct)))
|
||||||
|
.Throws(new Exception());
|
||||||
|
|
||||||
|
var sendTweetsToSharedInboxTaskMock = new Mock<ISendTweetsToSharedInboxTask>(MockBehavior.Strict);
|
||||||
|
|
||||||
|
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
|
||||||
|
|
||||||
|
var loggerMock = new Mock<ILogger<SendTweetsToFollowersProcessor>>();
|
||||||
|
|
||||||
|
var settings = new InstanceSettings
|
||||||
|
{
|
||||||
|
FailingFollowerCleanUpThreshold = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
var removeFollowerMock = new Mock<IRemoveFollowerAction>(MockBehavior.Strict);
|
||||||
|
removeFollowerMock
|
||||||
|
.Setup(x => x.ProcessAsync(It.Is<Follower>(y => y.Id == userId2)))
|
||||||
|
.Returns(Task.CompletedTask);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object);
|
||||||
|
var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None);
|
||||||
|
|
||||||
|
#region Validations
|
||||||
|
sendTweetsToInboxTaskMock.VerifyAll();
|
||||||
|
sendTweetsToSharedInboxTaskMock.VerifyAll();
|
||||||
|
followersDalMock.VerifyAll();
|
||||||
|
removeFollowerMock.VerifyAll();
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -704,15 +922,20 @@ namespace BirdsiteLive.Pipeline.Tests.Processors
|
||||||
.Returns(Task.CompletedTask);
|
.Returns(Task.CompletedTask);
|
||||||
|
|
||||||
var loggerMock = new Mock<ILogger<SendTweetsToFollowersProcessor>>();
|
var loggerMock = new Mock<ILogger<SendTweetsToFollowersProcessor>>();
|
||||||
|
|
||||||
|
var settings = new InstanceSettings();
|
||||||
|
|
||||||
|
var removeFollowerMock = new Mock<IRemoveFollowerAction>(MockBehavior.Strict);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object);
|
var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object);
|
||||||
var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None);
|
var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None);
|
||||||
|
|
||||||
#region Validations
|
#region Validations
|
||||||
sendTweetsToInboxTaskMock.VerifyAll();
|
sendTweetsToInboxTaskMock.VerifyAll();
|
||||||
sendTweetsToSharedInboxTaskMock.VerifyAll();
|
sendTweetsToSharedInboxTaskMock.VerifyAll();
|
||||||
followersDalMock.VerifyAll();
|
followersDalMock.VerifyAll();
|
||||||
|
removeFollowerMock.VerifyAll();
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -790,15 +1013,20 @@ namespace BirdsiteLive.Pipeline.Tests.Processors
|
||||||
.Returns(Task.CompletedTask);
|
.Returns(Task.CompletedTask);
|
||||||
|
|
||||||
var loggerMock = new Mock<ILogger<SendTweetsToFollowersProcessor>>();
|
var loggerMock = new Mock<ILogger<SendTweetsToFollowersProcessor>>();
|
||||||
|
|
||||||
|
var settings = new InstanceSettings();
|
||||||
|
|
||||||
|
var removeFollowerMock = new Mock<IRemoveFollowerAction>(MockBehavior.Strict);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object);
|
var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object);
|
||||||
var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None);
|
var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None);
|
||||||
|
|
||||||
#region Validations
|
#region Validations
|
||||||
sendTweetsToInboxTaskMock.VerifyAll();
|
sendTweetsToInboxTaskMock.VerifyAll();
|
||||||
sendTweetsToSharedInboxTaskMock.VerifyAll();
|
sendTweetsToSharedInboxTaskMock.VerifyAll();
|
||||||
followersDalMock.VerifyAll();
|
followersDalMock.VerifyAll();
|
||||||
|
removeFollowerMock.VerifyAll();
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue