Skip to content

Commit

Permalink
bubble pipeline exceptions up to hangfire orchestrator
Browse files Browse the repository at this point in the history
  • Loading branch information
retailcoder committed Oct 28, 2024
1 parent f64802e commit c9ca781
Show file tree
Hide file tree
Showing 15 changed files with 92 additions and 88 deletions.
2 changes: 1 addition & 1 deletion rubberduckvba.Server/Api/Auth/AuthController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class AuthController(IOptions<GitHubSettings> configuration, IOptions<Api
{
[HttpGet("auth")]
[AllowAnonymous]
public async Task<ActionResult<UserViewModel>> Index()
public ActionResult<UserViewModel> Index()
{
var claims = HttpContext.User.Claims.ToDictionary(claim => claim.Type, claim => claim.Value);
var hasName = claims.TryGetValue(ClaimTypes.Name, out var name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public interface IPipeline<TContext, TResult>
{
TContext Context { get; }
IPipelineResult<TResult> Result { get; }
IEnumerable<Exception> Exceptions { get; }

void Start<TInput>(ITargetBlock<TInput> entryBlock, TInput input);
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
namespace rubberduckvba.com.Server.ContentSynchronization.Pipeline.Abstract;

public interface ISynchronizationPipeline<TContext>
public interface ISynchronizationPipeline<TContext, TResult> : IPipeline<TContext, TResult>
where TContext : class
{
TContext Context { get; }
Task<TContext> ExecuteAsync(SyncRequestParameters parameters, CancellationTokenSource tokenSource);
Task<IPipelineResult<TResult>> ExecuteAsync(SyncRequestParameters parameters, CancellationTokenSource tokenSource);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
public interface ISynchronizationPipelineFactory<TContext>
where TContext : class
{
ISynchronizationPipeline<TContext> Create<TParameters>(TParameters parameters, CancellationTokenSource tokenSource) where TParameters : IRequestParameters;
ISynchronizationPipeline<TContext, bool> Create<TParameters>(TParameters parameters, CancellationTokenSource tokenSource) where TParameters : IRequestParameters;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ protected PipelineBase(TContext context, CancellationTokenSource tokenSource, IL
Context = context;
TokenSource = tokenSource;
Token = TokenSource.Token;

Result = Parent?.Result ?? new PipelineResult<TResult>();
}

protected PipelineBase(IPipeline<TContext, TResult> parent, CancellationTokenSource tokenSource, ILogger logger)
: this(parent.Context, tokenSource, logger)
{
Logger = logger;
Parent = parent;
Result = new PipelineResult<TResult>();
}

protected ILogger Logger { get; }
Expand All @@ -30,6 +30,7 @@ protected PipelineBase(IPipeline<TContext, TResult> parent, CancellationTokenSou
public TContext Context { get; }

public IPipelineResult<TResult> Result { get; }
public IEnumerable<Exception> Exceptions => _sections.SelectMany(section => section.Result.Exceptions).ToList();

public virtual void Start<TInput>(ITargetBlock<TInput> entryBlock, TInput input)
{
Expand All @@ -38,12 +39,12 @@ public virtual void Start<TInput>(ITargetBlock<TInput> entryBlock, TInput input)
entryBlock.Complete();
}

protected IPipeline<TContext, TResult> Parent { get; }
protected IPipeline<TContext, TResult>? Parent { get; }

private readonly IList<PipelineSection<TContext>> _sections = new List<PipelineSection<TContext>>();
protected IEnumerable<PipelineSection<TContext>> Sections => _sections;

public void AddSections(SyncRequestParameters parameters, params PipelineSection<TContext>[] sections)
protected void AddSections(SyncRequestParameters parameters, params PipelineSection<TContext>[] sections)
{
foreach (var section in sections)
{
Expand All @@ -57,12 +58,12 @@ protected void LinkSections<TTarget>(ISourceBlock<TTarget> exitBlock, ITargetBlo
_links.Add(exitBlock.LinkTo(entryBlock, new DataflowLinkOptions { PropagateCompletion = true }));
}

protected void LinkSections(Task exitTask, ITargetBlock<TContext> successEntryBlock, ITargetBlock<TContext> faultedEntryBlock = null)
protected void LinkSections(Task exitTask, ITargetBlock<TContext> successEntryBlock, ITargetBlock<TContext>? faultedEntryBlock = null)
{
LinkSections(exitTask, Context, successEntryBlock, faultedEntryBlock);
}

protected void LinkSections<TTarget>(Task exitTask, TTarget input, ITargetBlock<TTarget> entryBlock, ITargetBlock<TTarget> faultedEntryBlock = null)
protected void LinkSections<TTarget>(Task exitTask, TTarget input, ITargetBlock<TTarget> entryBlock, ITargetBlock<TTarget>? faultedEntryBlock = null)
{
Task.WhenAll(exitTask).ContinueWith(t =>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class PipelineResult<TResult> : IPipelineResult<TResult>
private readonly ConcurrentBag<Exception> _exceptions = new ConcurrentBag<Exception>();

public TResult Result { get; set; }
public IEnumerable<Exception> Exceptions { get; }
public IEnumerable<Exception> Exceptions => _exceptions;

public void AddException(Exception exception)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public SynchronizationPipelineFactory(ILogger<PipelineLogger> logger, IRubberduc
_markdown = markdown;
}

public ISynchronizationPipeline<SyncContext> Create<TParameters>(TParameters parameters, CancellationTokenSource tokenSource) where TParameters : IRequestParameters
public ISynchronizationPipeline<SyncContext, bool> Create<TParameters>(TParameters parameters, CancellationTokenSource tokenSource) where TParameters : IRequestParameters
{
return parameters switch
{
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
using System.Threading.Tasks.Dataflow;

using rubberduckvba.com.Server.ContentSynchronization.Pipeline.Abstract;
using rubberduckvba.com.Server.ContentSynchronization.XmlDoc.Abstract;
using rubberduckvba.com.Server.ContentSynchronization.Pipeline.Abstract;
using rubberduckvba.com.Server.ContentSynchronization.Pipeline.Sections.SyncTags;
using rubberduckvba.com.Server.ContentSynchronization.XmlDoc.Abstract;
using rubberduckvba.com.Server.Services;

namespace rubberduckvba.com.Server.ContentSynchronization.Pipeline;

public class SynchronizeTagsPipeline : PipelineBase<SyncContext, bool>, ISynchronizationPipeline<SyncContext>
public class SynchronizeTagsPipeline : PipelineBase<SyncContext, bool>, ISynchronizationPipeline<SyncContext, bool>
{
private readonly IRubberduckDbService _content;
private readonly IGitHubClientService _github;
Expand All @@ -23,7 +21,7 @@ public SynchronizeTagsPipeline(IRequestParameters parameters, ILogger logger, IR
_staging = staging;
}

public async Task<SyncContext> ExecuteAsync(SyncRequestParameters parameters, CancellationTokenSource tokenSource)
public async Task<IPipelineResult<bool>> ExecuteAsync(SyncRequestParameters parameters, CancellationTokenSource tokenSource)
{
if (_isDisposed)
{
Expand All @@ -42,6 +40,8 @@ public async Task<SyncContext> ExecuteAsync(SyncRequestParameters parameters, Ca
Start(synchronizeTags.InputBlock, parameters);

// 04. await completion
return await synchronizeTags.OutputTask.ContinueWith(t => Context, tokenSource.Token);
await synchronizeTags.OutputTask;

return Result;
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
using System.Threading.Tasks.Dataflow;

using rubberduckvba.com.Server.ContentSynchronization.Pipeline.Abstract;
using rubberduckvba.com.Server.ContentSynchronization.XmlDoc.Abstract;
using rubberduckvba.com.Server.ContentSynchronization.Pipeline.Abstract;
using rubberduckvba.com.Server.ContentSynchronization.Pipeline.Sections.SyncXmldoc;
using rubberduckvba.com.Server.ContentSynchronization.XmlDoc.Abstract;
using rubberduckvba.com.Server.Services;

namespace rubberduckvba.com.Server.ContentSynchronization.Pipeline;

public class SynchronizeXmlPipeline : PipelineBase<SyncContext, bool>, ISynchronizationPipeline<SyncContext>
public class SynchronizeXmlPipeline : PipelineBase<SyncContext, bool>, ISynchronizationPipeline<SyncContext, bool>
{
private readonly IRubberduckDbService _content;
private readonly IGitHubClientService _github;
Expand All @@ -25,7 +23,7 @@ public SynchronizeXmlPipeline(IRequestParameters parameters, ILogger logger, IRu
_markdown = markdown;
}

public async Task<SyncContext> ExecuteAsync(SyncRequestParameters parameters, CancellationTokenSource tokenSource)
public async Task<IPipelineResult<bool>> ExecuteAsync(SyncRequestParameters parameters, CancellationTokenSource tokenSource)
{
if (_isDisposed)
{
Expand All @@ -45,6 +43,8 @@ public async Task<SyncContext> ExecuteAsync(SyncRequestParameters parameters, Ca
Start(synchronizeFeatureItems.InputBlock!, xmldocRequest);

// 04. await completion
return await synchronizeFeatureItems.OutputBlock.Completion.ContinueWith(t => Context);
await synchronizeFeatureItems.OutputBlock.Completion;

return Result;
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
using System.Reflection;
using System.Xml.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json;
using rubberduckvba.com.Server.ContentSynchronization.XmlDoc.Schema;
using rubberduckvba.com.Server.Data;
using System.Reflection;
using System.Xml.Linq;

namespace rubberduckvba.com.Server.ContentSynchronization.XmlDoc;

public class AnnotationProperties
{
public AnnotationArgInfo[] Parameters { get; set; }
public AnnotationArgInfo[] Parameters { get; set; } = [];
}

public class XmlDocAnnotation
{
public XmlDocAnnotation(string name, XElement node, bool isPreRelease)
{
SourceObject = node.Attribute("name").Value.Substring(2).Substring(name.LastIndexOf(".", StringComparison.Ordinal) + 1);
SourceObject = node.Attribute("name")!.Value.Substring(2).Substring(name.LastIndexOf(".", StringComparison.Ordinal) + 1);
IsPreRelease = isPreRelease;

AnnotationName = name;
Expand Down Expand Up @@ -84,7 +84,7 @@ private BeforeAndAfterCodeExample[] ParseExamples(XElement node)
*/
var modules = example.Elements(XmlDocSchema.Annotation.Example.Module.ElementName).AsParallel();
var simpleExamples = modules.Where(m => m.Nodes().OfType<XCData>().Any())
.Select((e, i) => new BeforeAndAfterCodeExample(new[] { ExtractCodeModule(e, i) }, modulesAfter: null))
.Select((e, i) => new BeforeAndAfterCodeExample([ExtractCodeModule(e, i)], modulesAfter: []))
.ToArray();
if (simpleExamples.Length > 0)
{
Expand All @@ -93,7 +93,7 @@ private BeforeAndAfterCodeExample[] ParseExamples(XElement node)
}

IEnumerable<ExampleModule> before = Enumerable.Empty<ExampleModule>();
IEnumerable<ExampleModule> after = null;
IEnumerable<ExampleModule>? after = null;

if (modules.Any())
{
Expand All @@ -110,8 +110,8 @@ private BeforeAndAfterCodeExample[] ParseExamples(XElement node)
* </module>
* </example>
*/
before = modules.Select((e, i) => ExtractCodeModule(e.Element(XmlDocSchema.Annotation.Example.Module.Before.ElementName), i, "(code pane)"));
after = modules.Select((e, i) => ExtractCodeModule(e.Element(XmlDocSchema.Annotation.Example.Module.After.ElementName), i, "(synchronized, hidden attributes shown)"));
before = modules.Select((e, i) => ExtractCodeModule(e.Element(XmlDocSchema.Annotation.Example.Module.Before.ElementName)!, i, "(code pane)"));
after = modules.Select((e, i) => ExtractCodeModule(e.Element(XmlDocSchema.Annotation.Example.Module.After.ElementName)!, i, "(synchronized, hidden attributes shown)"));
}

if (example.Elements(XmlDocSchema.Annotation.Example.Before.ElementName).Any())
Expand All @@ -132,9 +132,9 @@ private BeforeAndAfterCodeExample[] ParseExamples(XElement node)
* </example>
*/
before = example.Elements(XmlDocSchema.Annotation.Example.Before.ElementName)
.Select((e, i) => ExtractCodeModule(e.Element(XmlDocSchema.Annotation.Example.Before.Module.ElementName), i, "(code pane)"));
.Select((e, i) => ExtractCodeModule(e.Element(XmlDocSchema.Annotation.Example.Before.Module.ElementName)!, i, "(code pane)"));
after = example.Elements(XmlDocSchema.Annotation.Example.After.ElementName)
.Select((e, i) => ExtractCodeModule(e.Element(XmlDocSchema.Annotation.Example.After.Module.ElementName), i, "(synchronized, hidden attributes shown)"));
.Select((e, i) => ExtractCodeModule(e.Element(XmlDocSchema.Annotation.Example.After.Module.ElementName)!, i, "(synchronized, hidden attributes shown)"));
}

if (before.Any() && after.Any())
Expand All @@ -156,7 +156,7 @@ private BeforeAndAfterCodeExample[] ParseExamples(XElement node)
.GetMembers()
.Select(m => (m.Name, m.GetCustomAttributes().OfType<System.ComponentModel.DescriptionAttribute>().SingleOrDefault()?.Description))
.Where(m => m.Description != null)
.ToDictionary(m => m.Description, m => (ExampleModuleType)Enum.Parse(typeof(ExampleModuleType), m.Name, true));
.ToDictionary(m => m.Description!, m => (ExampleModuleType)Enum.Parse(typeof(ExampleModuleType), m.Name, true));

private static string GetDefaultModuleName(ExampleModuleType type, int index = 1)
{
Expand All @@ -174,12 +174,11 @@ private static string GetDefaultModuleName(ExampleModuleType type, int index = 1
}
}

private ExampleModule ExtractCodeModule(XElement cdataParent, int index, string description = null)
private ExampleModule ExtractCodeModule(XElement cdataParent, int index, string? description = null)
{
var module = cdataParent.AncestorsAndSelf(XmlDocSchema.Annotation.Example.Module.ElementName).Single();
var moduleType = ModuleTypes.TryGetValue(module.Attribute(XmlDocSchema.Annotation.Example.Module.ModuleTypeAttribute)?.Value, out var type) ? type : ExampleModuleType.Any;
var name = module.Attribute(XmlDocSchema.Annotation.Example.Module.ModuleNameAttribute)?.Value
?? GetDefaultModuleName(moduleType, index);
var moduleType = ModuleTypes.TryGetValue(module.Attribute(XmlDocSchema.Annotation.Example.Module.ModuleTypeAttribute)?.Value ?? string.Empty, out var type) ? type : ExampleModuleType.Any;
var name = module.Attribute(XmlDocSchema.Annotation.Example.Module.ModuleNameAttribute)?.Value ?? GetDefaultModuleName(moduleType, index);
var code = cdataParent.Nodes().OfType<XCData>().Single().Value;

var model = new ExampleModule
Expand All @@ -194,17 +193,9 @@ private ExampleModule ExtractCodeModule(XElement cdataParent, int index, string
}
}

public class AnnotationArgInfo
public class AnnotationArgInfo(string name, string type, string description)
{
public AnnotationArgInfo() { }
public AnnotationArgInfo(string name, string type, string description)
{
Name = name;
Type = type;
Description = description;
}

public string Name { get; set; }
public string Type { get; set; }
public string Description { get; set; }
public string Name { get; set; } = name;
public string Type { get; set; } = type;
public string Description { get; set; } = description;
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
using System.ComponentModel;
using rubberduckvba.com.Server.ContentSynchronization.XmlDoc.Schema;
using rubberduckvba.com.Server.Data;
using rubberduckvba.com.Server.Services;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Reflection;
using System.Text.Json;
using System.Xml.Linq;
using RubberduckServices;
using rubberduckvba.com.Server.ContentSynchronization.XmlDoc.Schema;
using rubberduckvba.com.Server.Data;
using rubberduckvba.com.Server.Services;

namespace rubberduckvba.com.Server.ContentSynchronization.XmlDoc;

Expand All @@ -29,7 +28,6 @@ public class XmlDocInspection
private static readonly string _defaultInspectionType = "CodeQualityIssues";
private readonly IMarkdownFormattingService _markdownService;

private InspectionProperties _properties;
public XmlDocInspection(IMarkdownFormattingService markdownService)
{
_markdownService = markdownService;
Expand Down
2 changes: 1 addition & 1 deletion rubberduckvba.Server/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace rubberduckvba.com.Server;

public class HangfireAuthenticationFilter : IDashboardAuthorizationFilter
{
public bool Authorize([NotNull] DashboardContext context) => true;
public bool Authorize([NotNull] DashboardContext context) => context.Request.RemoteIpAddress == context.Request.LocalIpAddress;
}

public class Program
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,25 @@ public class InstallerDownloadStatsOrchestrator(ISynchronizationPipelineFactory<
public async Task UpdateContentAsync(TagSyncRequestParameters request, CancellationTokenSource tokenSource)
{
var pipeline = factory.Create(request, tokenSource);
await pipeline.ExecuteAsync(request, tokenSource);
try
{
await pipeline.ExecuteAsync(request, tokenSource);
}
catch (TaskCanceledException)
{
var exceptions = pipeline.Exceptions.ToList();
if (exceptions.Count > 0)
{
if (exceptions.Count == 1)
{
throw exceptions[0];
}
else
{
throw new AggregateException(exceptions);
}
}
throw;
}
}
}
Loading

0 comments on commit c9ca781

Please sign in to comment.