From b9d4e0a6066cae82a7f8d8f1dd4c8fb883606710 Mon Sep 17 00:00:00 2001 From: Filipe Esch Date: Mon, 14 Jun 2021 16:06:47 +0100 Subject: [PATCH] feat: changes how to serve client app files --- .github/workflows/build.yml | 5 ++ samples/KafkaFlow.Sample.Dashboard/Startup.cs | 1 - .../ApplicationBuilderExtensions.cs | 24 +++++- .../KafkaFlow.Admin.Dashboard.csproj | 7 +- .../ServeClientFilesMiddleware.cs | 74 ------------------- .../ServiceCollectionExtensions.cs | 21 ------ .../ClusterConfigurationBuilderExtensions.cs | 16 ++-- src/KafkaFlow.Admin/TelemetryScheduler.cs | 68 +++++++++-------- 8 files changed, 76 insertions(+), 140 deletions(-) delete mode 100644 src/KafkaFlow.Admin.Dashboard/ServeClientFilesMiddleware.cs delete mode 100644 src/KafkaFlow.Admin.Dashboard/ServiceCollectionExtensions.cs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 37d694201..491b446d3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,6 +34,11 @@ jobs: with: dotnet-version: 3.1.403 + - name: Use Node 14.x + uses: actions/setup-node@v1 + with: + node-version: '14.x' + - name: Build run: dotnet build ./src/KafkaFlow.sln -c Release diff --git a/samples/KafkaFlow.Sample.Dashboard/Startup.cs b/samples/KafkaFlow.Sample.Dashboard/Startup.cs index acdb97cfd..ead047113 100644 --- a/samples/KafkaFlow.Sample.Dashboard/Startup.cs +++ b/samples/KafkaFlow.Sample.Dashboard/Startup.cs @@ -31,7 +31,6 @@ public void ConfigureServices(IServiceCollection services) ); services - .AddKafkaFlowDashboard() .AddControllers(); } diff --git a/src/KafkaFlow.Admin.Dashboard/ApplicationBuilderExtensions.cs b/src/KafkaFlow.Admin.Dashboard/ApplicationBuilderExtensions.cs index 5eb312047..961e8be2b 100644 --- a/src/KafkaFlow.Admin.Dashboard/ApplicationBuilderExtensions.cs +++ b/src/KafkaFlow.Admin.Dashboard/ApplicationBuilderExtensions.cs @@ -1,6 +1,9 @@ namespace KafkaFlow.Admin.Dashboard { + using System.Reflection; using Microsoft.AspNetCore.Builder; + using Microsoft.AspNetCore.Http; + using Microsoft.Extensions.FileProviders; /// /// Extension methods over IApplicationBuilder @@ -14,8 +17,25 @@ public static class ApplicationBuilderExtensions /// public static IApplicationBuilder UseKafkaFlowDashboard(this IApplicationBuilder app) { - app - .UseMiddleware(); + app.Map( + "/kafka-flow", + builder => + { + var provider = new ManifestEmbeddedFileProvider( + Assembly.GetAssembly(typeof(ApplicationBuilderExtensions)), + "ClientApp/dist"); + + builder.UseStaticFiles(new StaticFileOptions { FileProvider = provider }); + + builder.Run( + async context => + { + if (context.Request.Path == "/") + { + await context.Response.SendFileAsync(provider.GetFileInfo("index.html")); + } + }); + }); return app; } diff --git a/src/KafkaFlow.Admin.Dashboard/KafkaFlow.Admin.Dashboard.csproj b/src/KafkaFlow.Admin.Dashboard/KafkaFlow.Admin.Dashboard.csproj index b91216253..34869d2ba 100644 --- a/src/KafkaFlow.Admin.Dashboard/KafkaFlow.Admin.Dashboard.csproj +++ b/src/KafkaFlow.Admin.Dashboard/KafkaFlow.Admin.Dashboard.csproj @@ -5,7 +5,8 @@ true Latest true - Library + Library + true @@ -14,4 +15,8 @@ + + + + diff --git a/src/KafkaFlow.Admin.Dashboard/ServeClientFilesMiddleware.cs b/src/KafkaFlow.Admin.Dashboard/ServeClientFilesMiddleware.cs deleted file mode 100644 index f4256c5b8..000000000 --- a/src/KafkaFlow.Admin.Dashboard/ServeClientFilesMiddleware.cs +++ /dev/null @@ -1,74 +0,0 @@ -namespace KafkaFlow.Admin.Dashboard -{ - using System; - using System.IO; - using System.Linq; - using System.Net; - using System.Threading.Tasks; - using Microsoft.AspNetCore.Http; - using Microsoft.Extensions.Primitives; - - internal class ServeClientFilesMiddleware : IMiddleware - { - private const string DashboardUrlPrefix = "/kafka-flow"; - - private readonly string[] homeUrls = - { - DashboardUrlPrefix, - DashboardUrlPrefix + "/", - DashboardUrlPrefix + "/index.html", - }; - - public async Task InvokeAsync(HttpContext context, RequestDelegate next) - { - var requestUrl = context.Request.Path.Value.ToLower(); - - if (!requestUrl.StartsWith(DashboardUrlPrefix)) - { - await next(context); - return; - } - - var fileName = this.IsHomeUrl(requestUrl) ? - "index.html" : - Path.GetFileName(requestUrl); - - await this.RespondResourceFileAsync(context, fileName); - } - - private static StringValues ResolveContentType(string resourceName) - { - return Path.GetExtension(resourceName) switch - { - ".js" => "text/javascript", - ".css" => "text/css", - ".html" => "text/html", - _ => throw new NotSupportedException("MIME type not supported") - }; - } - - private async Task RespondResourceFileAsync(HttpContext context, string fileName) - { - var assembly = this.GetType().Assembly; - - var resourceName = assembly.GetManifestResourceNames().FirstOrDefault(x => x.EndsWith(fileName)); - - if (resourceName is null) - { - context.Response.StatusCode = (int) HttpStatusCode.NotFound; - await context.Response.WriteAsync(string.Empty); - return; - } - - var resourceStream = assembly.GetManifestResourceStream(resourceName); - - context.Response.Headers["Content-Type"] = ResolveContentType(resourceName); - await resourceStream.CopyToAsync(context.Response.Body); - } - - private bool IsHomeUrl(string url) - { - return this.homeUrls.Any(home => home == url); - } - } -} diff --git a/src/KafkaFlow.Admin.Dashboard/ServiceCollectionExtensions.cs b/src/KafkaFlow.Admin.Dashboard/ServiceCollectionExtensions.cs deleted file mode 100644 index ae7f0e96a..000000000 --- a/src/KafkaFlow.Admin.Dashboard/ServiceCollectionExtensions.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace KafkaFlow.Admin.Dashboard -{ - using Microsoft.Extensions.DependencyInjection; - - /// - /// Extension methods over IServiceCollection - /// - public static class ServiceCollectionExtensions - { - /// - /// Configures a KafkaFlow Dashboard - /// - /// Instance of - /// - public static IServiceCollection AddKafkaFlowDashboard(this IServiceCollection services) - { - return services - .AddSingleton(); - } - } -} diff --git a/src/KafkaFlow.Admin/Extensions/ClusterConfigurationBuilderExtensions.cs b/src/KafkaFlow.Admin/Extensions/ClusterConfigurationBuilderExtensions.cs index 85018a1d0..f6516bc38 100644 --- a/src/KafkaFlow.Admin/Extensions/ClusterConfigurationBuilderExtensions.cs +++ b/src/KafkaFlow.Admin/Extensions/ClusterConfigurationBuilderExtensions.cs @@ -1,14 +1,10 @@ namespace KafkaFlow { using System; - using System.Linq; using System.Reflection; using KafkaFlow.Admin; using KafkaFlow.Admin.Handlers; - using KafkaFlow.Admin.Messages; using KafkaFlow.Configuration; - using KafkaFlow.Consumers; - using KafkaFlow.Producers; using KafkaFlow.Serializer; using KafkaFlow.TypedHandler; using Microsoft.Extensions.Caching.Memory; @@ -30,10 +26,8 @@ public static IClusterConfigurationBuilder EnableAdminMessages( string adminTopic, string adminConsumerGroup) { - cluster.DependencyConfigurator.AddSingleton(); - - cluster.DependencyConfigurator.AddSingleton(); - cluster.DependencyConfigurator.AddSingleton(); + cluster.DependencyConfigurator + .AddSingleton(); return cluster .AddProducer( @@ -80,8 +74,10 @@ public static IClusterConfigurationBuilder EnableTelemetry( string topicName, string consumerGroup) { - cluster.DependencyConfigurator.AddSingleton(); - cluster.DependencyConfigurator.AddSingleton(); + cluster.DependencyConfigurator + .AddSingleton() + .AddSingleton() + .AddSingleton(); var groupId = $"{consumerGroup}-{Environment.MachineName}-{Convert.ToBase64String(Guid.NewGuid().ToByteArray())}"; var name = $"telemetry-{Convert.ToBase64String(Guid.NewGuid().ToByteArray())}"; diff --git a/src/KafkaFlow.Admin/TelemetryScheduler.cs b/src/KafkaFlow.Admin/TelemetryScheduler.cs index 0ab76b9ad..3631fc7d8 100644 --- a/src/KafkaFlow.Admin/TelemetryScheduler.cs +++ b/src/KafkaFlow.Admin/TelemetryScheduler.cs @@ -25,40 +25,18 @@ public void Start(string key, string topicName) var consumers = this.dependencyResolver .Resolve() .All - .Where(c => !c.ManagementDisabled && - c.ClusterName.Equals(this.dependencyResolver - .Resolve()[key] - .ClusterName)); + .Where( + c => !c.ManagementDisabled && + c.ClusterName.Equals( + this.dependencyResolver + .Resolve()[key] + .ClusterName)) + .ToList(); var producer = this.dependencyResolver.Resolve().GetProducer(key); this.timers[key] = new Timer( - _ => - { - producer.BatchProduceAsync( - consumers.SelectMany(c => c.Assignment.Select(a => - new BatchProduceItem( - topicName, - Guid.NewGuid(), - new ConsumerMetric() - { - ConsumerName = c.ConsumerName, - Topic = a.Topic, - GroupId = c.GroupId, - InstanceName = $"{Environment.MachineName}-{c.MemberId}", - PausedPartitions = c.PausedPartitions - .Where(p => p.Topic == a.Topic) - .Select(p => p.Partition.Value), - RunningPartitions = c.RunningPartitions - .Where(p => p.Topic == a.Topic) - .Select(p => p.Partition.Value), - SentAt = DateTime.Now, - }, - null))) - .ToList()) - .GetAwaiter() - .GetResult(); - }, + _ => ProduceTelemetry(topicName, consumers, producer), null, TimeSpan.Zero, TimeSpan.FromSeconds(1)); @@ -72,5 +50,33 @@ public void Stop(string key) this.timers.Remove(key); } } + + private static void ProduceTelemetry( + string topicName, + IReadOnlyCollection consumers, + IMessageProducer producer) + { + var items = consumers.SelectMany( + c => c.Assignment.Select( + a => new ConsumerMetric() + { + ConsumerName = c.ConsumerName, + Topic = a.Topic, + GroupId = c.GroupId, + InstanceName = $"{Environment.MachineName}-{c.MemberId}", + PausedPartitions = c.PausedPartitions + .Where(p => p.Topic == a.Topic) + .Select(p => p.Partition.Value), + RunningPartitions = c.RunningPartitions + .Where(p => p.Topic == a.Topic) + .Select(p => p.Partition.Value), + SentAt = DateTime.Now, + })); + + foreach (var item in items) + { + producer.Produce(topicName, Guid.NewGuid().ToByteArray(), item); + } + } } -} \ No newline at end of file +}