This blog post is the last of the series **Plug-and-play architecture in Asp.NET 5** and we will see how we can actually implement the plug-and-play execution pipeline. # Execution context vs execution pipeline? **Execution context** is the metadata that every request comes with. As we discussed in the [previous blog post](https://ecency.com/hive-169321/@dotnetguru/execution-context-in-plug-and) the context can hold data for a request id, principal, and everything else that we might need as part of each request. https://wakeupandcode.com/wp-content/uploads/2019/04/Blog-Diagram-Middleware-Pipeline.png <center>*[source](https://wakeupandcode.com/middleware-in-asp-net-core/)*</center> **Execution pipeline** on the other hand is a series of steps that each request goes through. Depending on the configuration we usually see a pipeline in the MVC architecture as described in the image above. We need to implement a pipeline for both queries and commands that implicitly will do some things for us, like logging exceptions or logging commands/events. First let's configure a pipeline interface that we will use to create the pipeline middlewares: ``` using PlugAndPlayExample.Infrastructure.Logging; using System; using System.Collections.Generic; using System.Linq; namespace PlugAndPlayExample.Services.Infrastructure { public interface IPipeline { TResponse Execute<TResponse>(Func<TResponse> inner) where TResponse : Response; IPipeline Next { get; set; } } } ``` And lets create two different middlewares that we will use: ``` using PlugAndPlayExample.Infrastructure.Logging; using System; using System.Collections.Generic; using System.Linq; namespace PlugAndPlayExample.Services.Infrastructure { public class LoggingPipeline : IPipeline { public IPipeline Next { get; set; } private readonly ILogger logger; public LoggingPipeline(ILogger logger) { this.logger = logger; } public TResponse Execute<TResponse>(Func<TResponse> inner) where TResponse : Response { try { return Next.Execute(inner); } catch (Exception ex) { logger.Error(ex.Message, ex); throw; } } } public class RunnerPipeline : IPipeline { public IPipeline Next { get; set; } public TResponse Execute<TResponse>(Func<TResponse> inner) where TResponse : Response { return inner(); } } } ``` The **logging** middleware executes a function and if it throws an exception, it logs it. The **runner** middleware just runs the function and we always use it as the last middleware with no <code>Next</code> property. Now we need to implement the command and query middleware configuration and order: ``` using PlugAndPlayExample.Infrastructure.Logging; using System; using System.Collections.Generic; using System.Linq; namespace PlugAndPlayExample.Services.Infrastructure { public interface ICommandPipeline { TResponse Execute<TResponse>(Func<TResponse> inner) where TResponse : Response; } public interface IQueryPipeline { TResponse Execute<TResponse>(Func<TResponse> inner) where TResponse : Response; } public class CommandPipeline : ICommandPipeline { private List<IPipeline> pipelines; public CommandPipeline(IServiceProvider serviceProvider) { pipelines = new List<IPipeline>(); pipelines.Add(serviceProvider.GetService(typeof(LoggingPipeline)) as LoggingPipeline); pipelines.Add(serviceProvider.GetService(typeof(RunnerPipeline)) as RunnerPipeline); for (int i = 0; i < pipelines.Count - 1; i++) { pipelines[i].Next = pipelines[i + 1]; } } public TResponse Execute<TResponse>(Func<TResponse> inner) where TResponse : Response { return pipelines.FirstOrDefault()?.Execute(inner); } } public class QueryPipeline : IQueryPipeline { private List<IPipeline> pipelines; public QueryPipeline(IServiceProvider serviceProvider) { pipelines = new List<IPipeline>(); pipelines.Add(serviceProvider.GetService(typeof(RunnerPipeline)) as RunnerPipeline); for (int i = 0; i < pipelines.Count - 1; i++) { pipelines[i].Next = pipelines[i + 1]; } } public TResponse Execute<TResponse>(Func<TResponse> inner) where TResponse : Response { return pipelines.FirstOrDefault()?.Execute(inner); } } } ``` We are finally ready to start using this middlewares in our mediator and have our plug and play architecture: ``` using System; namespace PlugAndPlayExample.Services.Infrastructure { public class Mediator { private readonly IServiceProvider serviceProvider; private readonly IQueryPipeline queryPipeline; private readonly ICommandPipeline commandPipeline; public Mediator(IServiceProvider serviceProvider, IQueryPipeline queryPipeline, ICommandPipeline commandPipeline) { this.serviceProvider = serviceProvider; this.queryPipeline = queryPipeline; this.commandPipeline = commandPipeline; } public TResult Dispatch<TCommand, TResult>(TCommand command) where TCommand : ICommand where TResult : Response { var commandHandler = serviceProvider.GetService(typeof(ICommandHandler<TCommand, TResult>)) as ICommandHandler<TCommand, TResult>; return commandPipeline.Execute(() => commandHandler.Handle(command)); } public TResult Get<TQuery, TResult>(TQuery query) where TQuery : IQuery where TResult : Response { var queryHandler = serviceProvider.GetService(typeof(IQueryHandler<TQuery, TResult>)) as IQueryHandler<TQuery, TResult>; return queryPipeline.Execute(() => queryHandler.Handle(query)); } } } ``` Finally let's not forget to register everything in the service container: ``` using Microsoft.Extensions.DependencyInjection; using PlugAndPlayExample.Infrastructure.Caching; using PlugAndPlayExample.Infrastructure.Logging; using PlugAndPlayExample.Services.Infrastructure; using System.IO; namespace PlugAndPlayExample.Configuration { public static class RegisterInfrastructureAspectsExtension { public static IServiceCollection RegisterInfrastructureAspects(this IServiceCollection services) { services.AddSingleton<ICache, InMemoryCache>(); services.AddSingleton<ILogger, FileLogger>(provider => new FileLogger(new FileInfo("my_log_file.log"))); services.AddSingleton<IQueryPipeline, QueryPipeline>(); services.AddSingleton<ICommandPipeline, CommandPipeline>(); services.AddSingleton<RunnerPipeline>(); services.AddSingleton<LoggingPipeline>(); return services; } } } ``` Hope you found this blog post helpful. 😄 _Happy coding,_ _DotNetGuru_
author | dotnetguru |
---|---|
permlink | execution-pipeline-in-plug-and |
category | hive-169321 |
json_metadata | {"links":["https://ecency.com/hive-169321/@dotnetguru/execution-context-in-plug-and","https://wakeupandcode.com/middleware-in-asp-net-core/"],"image":["https://wakeupandcode.com/wp-content/uploads/2019/04/Blog-Diagram-Middleware-Pipeline.png"],"thumbnails":["https://wakeupandcode.com/wp-content/uploads/2019/04/Blog-Diagram-Middleware-Pipeline.png"],"tags":["hive-169321","development","desing-patterns","programming"],"app":"ecency/3.0.20-vision","format":"markdown+html"} |
created | 2022-01-12 16:45:36 |
last_update | 2022-01-12 16:45:36 |
depth | 0 |
children | 6 |
last_payout | 2022-01-19 16:45:36 |
cashout_time | 1969-12-31 23:59:59 |
total_payout_value | 0.160 HBD |
curator_payout_value | 0.147 HBD |
pending_payout_value | 0.000 HBD |
promoted | 0.000 HBD |
body_length | 7,266 |
author_reputation | 380,629,995,451 |
root_title | "Execution pipeline in plug-and-play architecture in Asp.NET 5" |
beneficiaries | [] |
max_accepted_payout | 1,000,000.000 HBD |
percent_hbd | 0 |
post_id | 109,414,412 |
net_rshares | 195,914,271,256 |
author_curate_reward | "" |
voter | weight | wgt% | rshares | pct | time |
---|---|---|---|---|---|
abeba | 0 | 4,786,577,568 | 100% | ||
vgichar | 0 | 1,265,704,395 | 100% | ||
cyka-blyatko | 0 | 146,895,160 | 100% | ||
dushica | 0 | 841,904,249 | 100% | ||
tgc | 0 | 2,296,397,102 | 100% | ||
amidank | 0 | 1,722,671,194 | 100% | ||
mariuszkarowski | 0 | 1,307,206,205 | 10% | ||
cmplxty | 0 | 169,865,688,998 | 25% | ||
newacchud | 0 | 858,098,085 | 100% | ||
ssiena | 0 | 5,887,010,145 | 25% | ||
cocaaladioxine | 0 | 662,243,189 | 100% | ||
nasty-123 | 0 | 851,808,533 | 100% | ||
pure-gameplay | 0 | 976,033,528 | 100% | ||
news-bot | 0 | 898,424,554 | 100% | ||
aioflureedb | 0 | 1,160,202,513 | 99.5% | ||
abbesov | 0 | 0 | 45% | ||
dotnetguru | 0 | 1,167,304,013 | 100% | ||
techlhab | 0 | 1,220,101,825 | 100% |
I see you are writing some pretty great and helpful posts. I suggest you leave some comments though, those are critical for long-term success here. I know you are having issues with resource credits right now, I see that you are currently at .50% which is tough but if you spend time on comments, people will be more willing to help you out with some delegation of credits so you can keep it up. Hopefully you can take that into consideration!
author | cmplxty |
---|---|
permlink | re-dotnetguru-r5xers |
category | hive-169321 |
json_metadata | {"tags":["hive-169321"],"app":"peakd/2021.12.1"} |
created | 2022-01-18 22:07:06 |
last_update | 2022-01-18 22:07:06 |
depth | 1 |
children | 4 |
last_payout | 2022-01-25 22:07:06 |
cashout_time | 1969-12-31 23:59:59 |
total_payout_value | 0.000 HBD |
curator_payout_value | 0.000 HBD |
pending_payout_value | 0.000 HBD |
promoted | 0.000 HBD |
body_length | 443 |
author_reputation | 783,785,300,628,314 |
root_title | "Execution pipeline in plug-and-play architecture in Asp.NET 5" |
beneficiaries | [] |
max_accepted_payout | 1,000,000.000 HBD |
percent_hbd | 10,000 |
post_id | 109,620,363 |
net_rshares | 0 |
Thanks for the advice, I was on vacation for 6 days, but I will try to be more engaging with the community in the future. At this moment I'm preparing a post about the importance of algorithms and where to practice. I hope it will bring value to somebody. 😄
author | dotnetguru |
---|---|
permlink | re-cmplxty-2022120t22350420z |
category | hive-169321 |
json_metadata | {"tags":["hive-169321"],"app":"ecency/3.0.20-vision","format":"markdown+html"} |
created | 2022-01-20 21:35:00 |
last_update | 2022-01-20 21:35:00 |
depth | 2 |
children | 3 |
last_payout | 2022-01-27 21:35:00 |
cashout_time | 1969-12-31 23:59:59 |
total_payout_value | 0.010 HBD |
curator_payout_value | 0.010 HBD |
pending_payout_value | 0.000 HBD |
promoted | 0.000 HBD |
body_length | 257 |
author_reputation | 380,629,995,451 |
root_title | "Execution pipeline in plug-and-play architecture in Asp.NET 5" |
beneficiaries | [] |
max_accepted_payout | 1,000,000.000 HBD |
percent_hbd | 10,000 |
post_id | 109,699,813 |
net_rshares | 19,761,493,986 |
author_curate_reward | "" |
voter | weight | wgt% | rshares | pct | time |
---|---|---|---|---|---|
cmplxty | 0 | 19,761,493,986 | 3% |
That's great, no worries! Vacation is critical in my opinion lol I'm glad you responded! If you run out of resource credits and the blockchain yells at you let me know and I can delegate you some more! It takes a few weeks to get enough credits to be able to post and comment consistently. Usually around 50 Hive Power is good enough for whatever you need to do.
author | cmplxty |
---|---|
permlink | re-dotnetguru-r613ku |
category | hive-169321 |
json_metadata | {"tags":["hive-169321"],"app":"peakd/2021.12.1"} |
created | 2022-01-20 21:55:42 |
last_update | 2022-01-20 21:55:42 |
depth | 3 |
children | 2 |
last_payout | 2022-01-27 21:55:42 |
cashout_time | 1969-12-31 23:59:59 |
total_payout_value | 0.000 HBD |
curator_payout_value | 0.000 HBD |
pending_payout_value | 0.000 HBD |
promoted | 0.000 HBD |
body_length | 362 |
author_reputation | 783,785,300,628,314 |
root_title | "Execution pipeline in plug-and-play architecture in Asp.NET 5" |
beneficiaries | [] |
max_accepted_payout | 1,000,000.000 HBD |
percent_hbd | 10,000 |
post_id | 109,700,227 |
net_rshares | 0 |
Congratulations @dotnetguru! You have completed the following achievement on the Hive blockchain and have been rewarded with new badge(s): <table><tr><td><img src="https://images.hive.blog/60x70/http://hivebuzz.me/@dotnetguru/payout.png?202201131948"></td><td>You received more than 10 HP as payout for your posts and comments.<br>Your next payout target is 50 HP.<br><sub>The unit is Hive Power equivalent because your rewards can be split into HP and HBD</sub></td></tr> </table> <sub>_You can view your badges on [your board](https://hivebuzz.me/@dotnetguru) and compare yourself to others in the [Ranking](https://hivebuzz.me/ranking)_</sub> <sub>_If you no longer want to receive notifications, reply to this comment with the word_ `STOP`</sub> **Check out the last post from @hivebuzz:** <table><tr><td><a href="/hivebuzz/@hivebuzz/pum-202201-10"><img src="https://images.hive.blog/64x128/https://i.imgur.com/SLXQX7g.png"></a></td><td><a href="/hivebuzz/@hivebuzz/pum-202201-10">Hive Power Up Month - Feedback from day 10</a></td></tr></table> ###### Support the HiveBuzz project. [Vote](https://hivesigner.com/sign/update_proposal_votes?proposal_ids=%5B%22199%22%5D&approve=true) for [our proposal](https://peakd.com/me/proposals/199)!
author | hivebuzz |
---|---|
permlink | notify-dotnetguru-20220113t195507 |
category | hive-169321 |
json_metadata | {"image":["http://hivebuzz.me/notify.t6.png"]} |
created | 2022-01-13 19:55:03 |
last_update | 2022-01-13 19:55:03 |
depth | 1 |
children | 0 |
last_payout | 2022-01-20 19:55:03 |
cashout_time | 1969-12-31 23:59:59 |
total_payout_value | 0.000 HBD |
curator_payout_value | 0.000 HBD |
pending_payout_value | 0.000 HBD |
promoted | 0.000 HBD |
body_length | 1,248 |
author_reputation | 369,424,823,437,015 |
root_title | "Execution pipeline in plug-and-play architecture in Asp.NET 5" |
beneficiaries | [] |
max_accepted_payout | 1,000,000.000 HBD |
percent_hbd | 10,000 |
post_id | 109,456,215 |
net_rshares | 0 |