Merge pull request #12 from StevanFreeborn/stevanfreeborn/fix/11-avoid-duplicate-stream-notifications
feat(youtube): multiple stream notifications
This commit is contained in:
@@ -12,6 +12,8 @@ internal static class NotificationHandler
|
|||||||
CancellationToken cancellationToken = default
|
CancellationToken cancellationToken = default
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
lastPostedStreamStore.RemoveValuesOlderThan24Hours();
|
||||||
|
|
||||||
using StreamReader stream = new(context.Request.Body);
|
using StreamReader stream = new(context.Request.Body);
|
||||||
var body = await stream.ReadToEndAsync(cancellationToken);
|
var body = await stream.ReadToEndAsync(cancellationToken);
|
||||||
|
|
||||||
|
|||||||
@@ -4,4 +4,5 @@ internal interface ILastPostedStreamStore
|
|||||||
{
|
{
|
||||||
void SetValue(string value);
|
void SetValue(string value);
|
||||||
bool HasValue(string value);
|
bool HasValue(string value);
|
||||||
|
void RemoveValuesOlderThan24Hours();
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,45 @@
|
|||||||
namespace StevesBot.Webhook.YouTube;
|
namespace StevesBot.Webhook.YouTube;
|
||||||
|
|
||||||
internal class LastPostedStreamStore : ILastPostedStreamStore
|
internal class LastPostedStreamStore(TimeProvider timeProvider) : ILastPostedStreamStore
|
||||||
{
|
{
|
||||||
private string _value = string.Empty;
|
private readonly TimeProvider _timeProvider = timeProvider;
|
||||||
|
private readonly ConcurrentDictionary<string, long> _values = [];
|
||||||
|
|
||||||
public void SetValue(string value)
|
public void SetValue(string value)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(value);
|
ArgumentNullException.ThrowIfNull(value);
|
||||||
_value = value;
|
_values[value] = _timeProvider.GetUtcNow()
|
||||||
|
.ToUnixTimeMilliseconds();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasValue(string value)
|
public bool HasValue(string value)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(value);
|
ArgumentNullException.ThrowIfNull(value);
|
||||||
return _value.Equals(value, StringComparison.OrdinalIgnoreCase);
|
return _values.TryGetValue(value, out var _);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveValuesOlderThan24Hours()
|
||||||
|
{
|
||||||
|
var currentTime = _timeProvider.GetUtcNow();
|
||||||
|
var twentyFourHoursAgo = currentTime
|
||||||
|
.AddHours(-24)
|
||||||
|
.ToUnixTimeMilliseconds();
|
||||||
|
|
||||||
|
var keysToRemove = new List<string>();
|
||||||
|
|
||||||
|
foreach (var (k, v) in _values)
|
||||||
|
{
|
||||||
|
if (v > twentyFourHoursAgo)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
keysToRemove.Add(k);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var k in keysToRemove)
|
||||||
|
{
|
||||||
|
_values.Remove(k, out var _);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
namespace StevesBot.Webhook.Tests.Unit;
|
|
||||||
|
|
||||||
public class LastPostedStreamStoreTests
|
|
||||||
{
|
|
||||||
[Fact]
|
|
||||||
public void SetValue_WhenCalledWithNull_ItShouldThrowArgumentNullException()
|
|
||||||
{
|
|
||||||
var store = new LastPostedStreamStore();
|
|
||||||
|
|
||||||
var act = () => store.SetValue(null!);
|
|
||||||
|
|
||||||
act.Should().Throw<ArgumentNullException>();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void HasValue_WhenCalledWithNull_ItShouldThrowArgumentNullException()
|
|
||||||
{
|
|
||||||
var store = new LastPostedStreamStore();
|
|
||||||
|
|
||||||
var act = () => store.HasValue(null!);
|
|
||||||
|
|
||||||
act.Should().Throw<ArgumentNullException>();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void SetValueHasValue_WhenCalled_ItShouldStoreValue()
|
|
||||||
{
|
|
||||||
var store = new LastPostedStreamStore();
|
|
||||||
var streamId = "test-stream-id";
|
|
||||||
|
|
||||||
store.SetValue(streamId);
|
|
||||||
|
|
||||||
store.HasValue(streamId).Should().BeTrue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
namespace StevesBot.Webhook.Tests.Unit;
|
||||||
|
|
||||||
|
public class LastPostedStreamStoreTests
|
||||||
|
{
|
||||||
|
private readonly Mock<TimeProvider> _mockTimeProvider = new();
|
||||||
|
private readonly LastPostedStreamStore _sut;
|
||||||
|
|
||||||
|
public LastPostedStreamStoreTests()
|
||||||
|
{
|
||||||
|
_sut = new(_mockTimeProvider.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SetValue_WhenCalledWithNull_ItShouldThrowArgumentNullException()
|
||||||
|
{
|
||||||
|
var act = () => _sut.SetValue(null!);
|
||||||
|
|
||||||
|
act.Should().Throw<ArgumentNullException>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void HasValue_WhenCalledWithNull_ItShouldThrowArgumentNullException()
|
||||||
|
{
|
||||||
|
var act = () => _sut.HasValue(null!);
|
||||||
|
|
||||||
|
act.Should().Throw<ArgumentNullException>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SetValueHasValue_WhenCalled_ItShouldStoreValue()
|
||||||
|
{
|
||||||
|
var streamId = "test-stream-id";
|
||||||
|
|
||||||
|
_sut.SetValue(streamId);
|
||||||
|
|
||||||
|
_sut.HasValue(streamId).Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RemoveValuesOlderThan24Hours_WhenCalled_ItShouldRemoveItemsOlderThan24Hours()
|
||||||
|
{
|
||||||
|
var oldStreamId = "test-stream-id-old";
|
||||||
|
var currentStreamId = "test-stream-id-current";
|
||||||
|
|
||||||
|
var currentTime = DateTimeOffset.UtcNow;
|
||||||
|
var invalidTime = DateTimeOffset.UtcNow.AddHours(-25);
|
||||||
|
var validTime = DateTimeOffset.UtcNow.AddHours(-10);
|
||||||
|
|
||||||
|
_mockTimeProvider.SetupSequence(static m => m.GetUtcNow())
|
||||||
|
.Returns(invalidTime)
|
||||||
|
.Returns(validTime)
|
||||||
|
.Returns(currentTime);
|
||||||
|
|
||||||
|
_sut.SetValue(oldStreamId);
|
||||||
|
_sut.SetValue(currentStreamId);
|
||||||
|
|
||||||
|
_sut.RemoveValuesOlderThan24Hours();
|
||||||
|
|
||||||
|
_sut.HasValue(oldStreamId).Should().BeFalse();
|
||||||
|
_sut.HasValue(currentStreamId).Should().BeTrue();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user