Browse Source

1. Remove dead code.

2. Remove RabbitMq consumer.
3. Fix background health check.
pull/978/head
Sebastian 3 years ago
parent
commit
bf375aa5ac
  1. 15
      backend/Squidex.sln
  2. 96
      backend/src/Squidex.Infrastructure.RabbitMq/CQRS/Events/RabbitMqEventConsumer.cs
  3. 29
      backend/src/Squidex.Infrastructure.RabbitMq/Squidex.Infrastructure.RabbitMq.csproj
  4. 68
      backend/src/Squidex.Infrastructure.Redis/RedisPubSub.cs
  5. 99
      backend/src/Squidex.Infrastructure.Redis/RedisSubscription.cs
  6. 24
      backend/src/Squidex.Infrastructure.Redis/Squidex.Infrastructure.Redis.csproj
  7. 64
      backend/src/Squidex.Infrastructure/EventSourcing/Consume/EventConsumersHealthCheck.cs
  8. 72
      backend/src/Squidex/Config/Domain/EventPublishersServices.cs
  9. 4
      backend/src/Squidex/Config/Domain/HealthCheckServices.cs
  10. 6
      backend/src/Squidex/Config/Web/WebExtensions.cs
  11. 1
      backend/src/Squidex/Squidex.csproj
  12. 1
      backend/src/Squidex/Startup.cs
  13. 12
      backend/src/Squidex/appsettings.json
  14. 112
      backend/tests/Squidex.Infrastructure.Tests/EventSourcing/Consume/EventConsumersHealthCheckTests.cs

15
backend/Squidex.sln

@ -18,8 +18,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Domain.Apps.Core.Te
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Infrastructure.MongoDb", "src\Squidex.Infrastructure.MongoDb\Squidex.Infrastructure.MongoDb.csproj", "{6A811927-3C37-430A-90F4-503E37123956}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Infrastructure.RabbitMq", "src\Squidex.Infrastructure.RabbitMq\Squidex.Infrastructure.RabbitMq.csproj", "{C1E5BBB6-6B6A-4DE5-B19D-0538304DE343}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{94207AA6-4923-4183-A558-E0F8196B8CA3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Shared", "src\Squidex.Shared\Squidex.Shared.csproj", "{5E75AB7D-6F01-4313-AFF1-7F7128FFD71F}"
@ -118,18 +116,6 @@ Global
{6A811927-3C37-430A-90F4-503E37123956}.Release|Any CPU.Build.0 = Release|Any CPU
{6A811927-3C37-430A-90F4-503E37123956}.Release|x64.ActiveCfg = Release|Any CPU
{6A811927-3C37-430A-90F4-503E37123956}.Release|x86.ActiveCfg = Release|Any CPU
{C1E5BBB6-6B6A-4DE5-B19D-0538304DE343}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C1E5BBB6-6B6A-4DE5-B19D-0538304DE343}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C1E5BBB6-6B6A-4DE5-B19D-0538304DE343}.Debug|x64.ActiveCfg = Debug|Any CPU
{C1E5BBB6-6B6A-4DE5-B19D-0538304DE343}.Debug|x64.Build.0 = Debug|Any CPU
{C1E5BBB6-6B6A-4DE5-B19D-0538304DE343}.Debug|x86.ActiveCfg = Debug|Any CPU
{C1E5BBB6-6B6A-4DE5-B19D-0538304DE343}.Debug|x86.Build.0 = Debug|Any CPU
{C1E5BBB6-6B6A-4DE5-B19D-0538304DE343}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C1E5BBB6-6B6A-4DE5-B19D-0538304DE343}.Release|Any CPU.Build.0 = Release|Any CPU
{C1E5BBB6-6B6A-4DE5-B19D-0538304DE343}.Release|x64.ActiveCfg = Release|Any CPU
{C1E5BBB6-6B6A-4DE5-B19D-0538304DE343}.Release|x64.Build.0 = Release|Any CPU
{C1E5BBB6-6B6A-4DE5-B19D-0538304DE343}.Release|x86.ActiveCfg = Release|Any CPU
{C1E5BBB6-6B6A-4DE5-B19D-0538304DE343}.Release|x86.Build.0 = Release|Any CPU
{5E75AB7D-6F01-4313-AFF1-7F7128FFD71F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5E75AB7D-6F01-4313-AFF1-7F7128FFD71F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5E75AB7D-6F01-4313-AFF1-7F7128FFD71F}.Debug|x64.ActiveCfg = Debug|Any CPU
@ -308,7 +294,6 @@ Global
{7FD0A92B-7862-4BB1-932B-B52A9CACB56B} = {8CF53B92-5EB1-461D-98F8-70DA9B603FBF}
{FD0AFD44-7A93-4F9E-B5ED-72582392E435} = {4C6B06C2-6D77-4E0E-AE32-D7050236433A}
{6A811927-3C37-430A-90F4-503E37123956} = {8CF53B92-5EB1-461D-98F8-70DA9B603FBF}
{C1E5BBB6-6B6A-4DE5-B19D-0538304DE343} = {8CF53B92-5EB1-461D-98F8-70DA9B603FBF}
{5E75AB7D-6F01-4313-AFF1-7F7128FFD71F} = {7EDE8CF1-B1E4-4005-B154-834B944E0D7A}
{F7771E22-47BD-45C4-A133-FD7F1DE27CA0} = {7EDE8CF1-B1E4-4005-B154-834B944E0D7A}
{27CF800D-890F-4882-BF05-44EC3233537D} = {7EDE8CF1-B1E4-4005-B154-834B944E0D7A}

96
backend/src/Squidex.Infrastructure.RabbitMq/CQRS/Events/RabbitMqEventConsumer.cs

@ -1,96 +0,0 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Text;
using RabbitMQ.Client;
using Squidex.Hosting;
using Squidex.Hosting.Configuration;
using Squidex.Infrastructure.EventSourcing;
using Squidex.Infrastructure.Json;
namespace Squidex.Infrastructure.CQRS.Events;
public sealed class RabbitMqEventConsumer : DisposableObjectBase, IInitializable, IEventConsumer
{
private readonly IJsonSerializer serializer;
private readonly string eventPublisherName;
private readonly string exchange;
private readonly string eventsFilter;
private readonly ConnectionFactory connectionFactory;
private readonly Lazy<IConnection> connection;
private readonly Lazy<IModel> channel;
public string Name
{
get => eventPublisherName;
}
public string EventsFilter
{
get => eventsFilter;
}
public RabbitMqEventConsumer(IJsonSerializer serializer, string eventPublisherName, string uri, string exchange, string eventsFilter)
{
connectionFactory = new ConnectionFactory { Uri = new Uri(uri, UriKind.Absolute) };
connection = new Lazy<IConnection>(connectionFactory.CreateConnection);
channel = new Lazy<IModel>(connection.Value.CreateModel);
this.exchange = exchange;
this.eventsFilter = eventsFilter;
this.eventPublisherName = eventPublisherName;
this.serializer = serializer;
}
protected override void DisposeObject(bool disposing)
{
if (connection.IsValueCreated)
{
connection.Value.Close();
connection.Value.Dispose();
}
}
public Task InitializeAsync(
CancellationToken ct)
{
try
{
var currentConnection = connection.Value;
if (!currentConnection.IsOpen)
{
var error = new ConfigurationError($"RabbitMq event bus failed to connect to {connectionFactory.Endpoint}.");
throw new ConfigurationException(error);
}
return Task.CompletedTask;
}
catch (Exception ex)
{
var error = new ConfigurationError($"RabbitMq event bus failed to connect to {connectionFactory.Endpoint}.");
throw new ConfigurationException(error, ex);
}
}
public Task On(Envelope<IEvent> @event)
{
if (@event.Headers.Restored())
{
return Task.CompletedTask;
}
var jsonString = serializer.Serialize(@event);
var jsonBytes = Encoding.UTF8.GetBytes(jsonString);
channel.Value.BasicPublish(exchange, string.Empty, null, jsonBytes);
return Task.CompletedTask;
}
}

29
backend/src/Squidex.Infrastructure.RabbitMq/Squidex.Infrastructure.RabbitMq.csproj

@ -1,29 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<RootNamespace>Squidex.Infrastructure</RootNamespace>
<LangVersion>10.0</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>True</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Meziantou.Analyzer" Version="1.0.756">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="RabbitMQ.Client" Version="6.4.0" />
<PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Squidex.Infrastructure\Squidex.Infrastructure.csproj" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="..\..\stylecop.json" Link="stylecop.json" />
</ItemGroup>
</Project>

68
backend/src/Squidex.Infrastructure.Redis/RedisPubSub.cs

@ -1,68 +0,0 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using Squidex.Infrastructure.Json;
using Squidex.Infrastructure.Log;
using Squidex.Infrastructure.Tasks;
using StackExchange.Redis;
namespace Squidex.Infrastructure
{
public sealed class RedisPubSub : IPubSub, IInitializable
{
private readonly ConcurrentDictionary<string, object> subscriptions = new ConcurrentDictionary<string, object>();
private readonly IConnectionMultiplexer redis;
private readonly IJsonSerializer serializer;
private readonly ISemanticLog log;
private ISubscriber redisSubscriber;
public RedisPubSub(IConnectionMultiplexer redis, IJsonSerializer serializer, ISemanticLog log)
{
this.log = log;
this.redis = redis;
this.serializer = serializer;
}
public Task InitializeAsync(
CancellationToken ct = default)
{
try
{
redisSubscriber = redis.GetSubscriber();
redis.GetStatus();
return TaskHelper.Done;
}
catch (Exception ex)
{
throw new ConfigurationException($"Redis connection failed to connect to database {redis.Configuration}", ex);
}
}
public void Publish<T>(T value, bool notifySelf)
{
GetSubscriber<T>().Publish(value, notifySelf);
}
public IDisposable Subscribe<T>(Action<T> handler)
{
return GetSubscriber<T>().Subscribe(handler);
}
private RedisSubscription<T> GetSubscriber<T>()
{
var typeName = typeof(T).FullName;
return (RedisSubscription<T>)subscriptions.GetOrAdd(typeName, this, (k, c) => new RedisSubscription<T>(c.redisSubscriber, serializer, k, c.log));
}
}
}

99
backend/src/Squidex.Infrastructure.Redis/RedisSubscription.cs

@ -1,99 +0,0 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Reactive.Subjects;
using Squidex.Infrastructure.Json;
using Squidex.Infrastructure.Log;
using StackExchange.Redis;
#pragma warning disable SA1401 // Fields must be private
namespace Squidex.Infrastructure
{
internal sealed class RedisSubscription<T>
{
private readonly Guid selfId = Guid.NewGuid();
private readonly Subject<T> subject = new Subject<T>();
private readonly ISubscriber subscriber;
private readonly IJsonSerializer serializer;
private readonly ISemanticLog log;
private readonly string channelName;
private sealed class Envelope
{
public T Payload;
public Guid Sender;
}
public RedisSubscription(ISubscriber subscriber, IJsonSerializer serializer, string channelName, ISemanticLog log)
{
this.log = log;
this.serializer = serializer;
this.subscriber = subscriber;
this.subscriber.Subscribe(channelName, (channel, value) => HandleMessage(value));
this.channelName = channelName;
}
public void Publish(object value, bool notifySelf)
{
try
{
var senderId = notifySelf ? Guid.Empty : selfId;
var envelope = serializer.Serialize(new Envelope { Sender = senderId, Payload = (T)value });
subscriber.Publish(channelName, envelope);
}
catch (Exception ex)
{
log.LogError(ex, channelName, (logChannel, w) => w
.WriteProperty("action", "PublishRedisMessage")
.WriteProperty("status", "Failed")
.WriteProperty("channel", logChannel));
}
}
private void HandleMessage(string value)
{
try
{
if (string.IsNullOrWhiteSpace(value))
{
return;
}
var envelope = serializer.Deserialize<Envelope>(value);
if (envelope.Sender != selfId)
{
subject.OnNext(envelope.Payload);
log.LogDebug(channelName, (logChannel, w) => w
.WriteProperty("action", "ReceiveRedisMessage")
.WriteProperty("channel", logChannel)
.WriteProperty("status", "Received"));
}
}
catch (Exception ex)
{
log.LogError(ex, channelName, (logChannel, w) => w
.WriteProperty("action", "ReceiveRedisMessage")
.WriteProperty("channel", logChannel)
.WriteProperty("status", "Failed"));
}
}
public IDisposable Subscribe(Action<T> handler)
{
return subject.Subscribe(handler);
}
}
}

24
backend/src/Squidex.Infrastructure.Redis/Squidex.Infrastructure.Redis.csproj

@ -1,24 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<RootNamespace>Squidex.Infrastructure</RootNamespace>
<LangVersion>10.0</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>True</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Squidex.Infrastructure\Squidex.Infrastructure.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" />
<PackageReference Include="StackExchange.Redis.StrongName" Version="1.2.6" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="..\..\stylecop.json" Link="stylecop.json" />
</ItemGroup>
</Project>

64
backend/src/Squidex.Infrastructure/EventSourcing/Consume/EventConsumersHealthCheck.cs

@ -0,0 +1,64 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace Squidex.Infrastructure.EventSourcing.Consume;
public sealed class EventConsumersHealthCheck : IHealthCheck
{
private readonly IEventConsumerManager eventConsumerManager;
public EventConsumersHealthCheck(IEventConsumerManager eventConsumerManager)
{
this.eventConsumerManager = eventConsumerManager;
}
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context,
CancellationToken cancellationToken = default)
{
var eventConsumers = await eventConsumerManager.GetConsumersAsync(cancellationToken);
var data = new Dictionary<string, object>();
var numTotal = 0;
var numFailed = 0;
foreach (var eventConsumer in eventConsumers)
{
var status = "Running";
if (eventConsumer.Error != null)
{
status = "Failed";
numFailed++;
}
else if (eventConsumer.IsStopped)
{
status = "Stopped";
}
data[eventConsumer.Name] = status;
numTotal++;
}
if (numTotal > 0 && numFailed == numTotal)
{
return HealthCheckResult.Unhealthy("All event consumers failed", null, data);
}
else if (numFailed > 0)
{
return HealthCheckResult.Degraded("One or more event consumers failed", null, data);
}
else
{
return HealthCheckResult.Healthy(data: data);
}
}
}

72
backend/src/Squidex/Config/Domain/EventPublishersServices.cs

@ -1,72 +0,0 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using Squidex.Hosting.Configuration;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.EventSourcing;
using Squidex.Infrastructure.Json;
namespace Squidex.Config.Domain;
public static class EventPublishersServices
{
public static void AddSquidexEventPublisher(this IServiceCollection services, IConfiguration config)
{
var eventPublishers = config.GetSection("eventPublishers");
foreach (var child in eventPublishers.GetChildren())
{
var eventPublisherType = child.GetValue<string>("type");
if (string.IsNullOrWhiteSpace(eventPublisherType))
{
var error = new ConfigurationError("Value is required.", "eventPublishers:{child.Key}:type");
throw new ConfigurationException(error);
}
var eventsFilter = child.GetValue<string>("eventsFilter") ?? string.Empty;
var enabled = child.GetValue<bool>("enabled");
if (string.Equals(eventPublisherType, "RabbitMq", StringComparison.OrdinalIgnoreCase))
{
var publisherConfig = child.GetValue<string>("configuration");
if (string.IsNullOrWhiteSpace(publisherConfig))
{
var error = new ConfigurationError("Value is required.", "eventPublishers:{child.Key}:configuration");
throw new ConfigurationException(error);
}
var exchange = child.GetValue<string>("exchange");
if (string.IsNullOrWhiteSpace(exchange))
{
var error = new ConfigurationError("Value is required.", "eventPublishers:{child.Key}:exchange");
throw new ConfigurationException(error);
}
var name = $"EventPublishers_{child.Key}";
if (enabled)
{
services.AddSingletonAs(c => new RabbitMqEventConsumer(c.GetRequiredService<IJsonSerializer>(), name, publisherConfig, exchange, eventsFilter))
.As<IEventConsumer>();
}
}
else
{
var error = new ConfigurationError($"Unsupported value '{child.Key}", "eventPublishers:{child.Key}:type.");
throw new ConfigurationException(error);
}
}
}
}

4
backend/src/Squidex/Config/Domain/HealthCheckServices.cs

@ -6,6 +6,7 @@
// ==========================================================================
using Squidex.Infrastructure.Diagnostics;
using Squidex.Infrastructure.EventSourcing.Consume;
namespace Squidex.Config.Domain;
@ -17,6 +18,7 @@ public static class HealthCheckServices
"diagnostics:gc");
services.AddHealthChecks()
.AddCheck<GCHealthCheck>("GC", tags: new[] { "node" });
.AddCheck<GCHealthCheck>("GC", tags: new[] { "node" })
.AddCheck<EventConsumersHealthCheck>("EventConsumers", tags: new[] { "background" });
}
}

6
backend/src/Squidex/Config/Web/WebExtensions.cs

@ -108,12 +108,6 @@ public static class WebExtensions
ResponseWriter = writer
});
app.UseHealthChecks("/cluster-healthz", new HealthCheckOptions
{
Predicate = check => check.Tags.Contains("cluster"),
ResponseWriter = writer
});
app.UseHealthChecks("/background-healthz", new HealthCheckOptions
{
Predicate = check => check.Tags.Contains("background"),

1
backend/src/Squidex/Squidex.csproj

@ -27,7 +27,6 @@
<ProjectReference Include="..\Squidex.Domain.Users\Squidex.Domain.Users.csproj" />
<ProjectReference Include="..\Squidex.Domain.Users.MongoDb\Squidex.Domain.Users.MongoDb.csproj" />
<ProjectReference Include="..\Squidex.Infrastructure.GetEventStore\Squidex.Infrastructure.GetEventStore.csproj" />
<ProjectReference Include="..\Squidex.Infrastructure.RabbitMq\Squidex.Infrastructure.RabbitMq.csproj" />
<ProjectReference Include="..\Squidex.Infrastructure\Squidex.Infrastructure.csproj" />
<ProjectReference Include="..\Squidex.Infrastructure.MongoDb\Squidex.Infrastructure.MongoDb.csproj" />
<ProjectReference Include="..\Squidex.Shared\Squidex.Shared.csproj" />

1
backend/src/Squidex/Startup.cs

@ -49,7 +49,6 @@ public sealed class Startup
services.AddSquidexComments();
services.AddSquidexContents(config);
services.AddSquidexControllerServices(config);
services.AddSquidexEventPublisher(config);
services.AddSquidexEventSourcing(config);
services.AddSquidexGraphQL();
services.AddSquidexHealthChecks(config);

12
backend/src/Squidex/appsettings.json

@ -499,18 +499,6 @@
}
},
"eventPublishers": {
// Additional event publishers (advanced usage only): (Name => Config)
"allToRabbitMq": {
// Example:: Push all events to RabbitMq.
"type": "RabbitMq",
"configuration": "amqp://guest:guest@localhost/",
"exchange": "squidex",
"enabled": false,
"eventsFilter": ".*"
}
},
"store": {
// Define the type of the read store.
//

112
backend/tests/Squidex.Infrastructure.Tests/EventSourcing/Consume/EventConsumersHealthCheckTests.cs

@ -0,0 +1,112 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace Squidex.Infrastructure.EventSourcing.Consume;
public class EventConsumersHealthCheckTests
{
private readonly IEventConsumerManager eventConsumerManager = A.Fake<IEventConsumerManager>();
private readonly List<EventConsumerInfo> consumers = new List<EventConsumerInfo>();
private readonly CancellationTokenSource cts = new CancellationTokenSource();
private readonly CancellationToken ct;
private readonly EventConsumersHealthCheck sut;
public EventConsumersHealthCheckTests()
{
ct = cts.Token;
A.CallTo(() => eventConsumerManager.GetConsumersAsync(ct))
.Returns(consumers);
sut = new EventConsumersHealthCheck(eventConsumerManager);
}
[Fact]
public async Task Should_return_healthy_if_no_consumer_found()
{
var status = await sut.CheckHealthAsync(null!, ct);
Assert.Equal(HealthStatus.Healthy, status.Status);
}
[Fact]
public async Task Should_return_healthy_if_no_consumer_failed()
{
consumers.Add(new EventConsumerInfo
{
Name = "Consumer1"
});
consumers.Add(new EventConsumerInfo
{
Name = "Consumer2"
});
consumers.Add(new EventConsumerInfo
{
Name = "Consumer2"
});
var status = await sut.CheckHealthAsync(null!, ct);
Assert.Equal(HealthStatus.Healthy, status.Status);
}
[Fact]
public async Task Should_return_unhealthy_if_all_consumers_failed()
{
consumers.Add(new EventConsumerInfo
{
Name = "Consumer1",
Error = "Failed1"
});
consumers.Add(new EventConsumerInfo
{
Name = "Consumer2",
Error = "Failed2"
});
consumers.Add(new EventConsumerInfo
{
Name = "Consumer3",
Error = "Failed3"
});
var status = await sut.CheckHealthAsync(null!, ct);
Assert.Equal(HealthStatus.Unhealthy, status.Status);
}
[Fact]
public async Task Should_return_degrated_if_at_least_one_consumers_failed()
{
consumers.Add(new EventConsumerInfo
{
Name = "Consumer1",
Error = "Failed1"
});
consumers.Add(new EventConsumerInfo
{
Name = "Consumer2",
IsStopped = true
});
consumers.Add(new EventConsumerInfo
{
Name = "Consumer3",
IsStopped = false
});
var status = await sut.CheckHealthAsync(null!, ct);
Assert.Equal(HealthStatus.Degraded, status.Status);
}
}
Loading…
Cancel
Save