Skip to content

Commit

Permalink
Add error handling for Navisworks internal errors
Browse files Browse the repository at this point in the history
  • Loading branch information
GeorgDangl committed May 29, 2024
1 parent 0a55ce2 commit d0e174f
Show file tree
Hide file tree
Showing 18 changed files with 439 additions and 61 deletions.
4 changes: 4 additions & 0 deletions src/IPA.Bcfier.App/Controllers/ViewpointsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ await ipcHandler.SendMessageAsync(JsonConvert.SerializeObject(new IpcMessage
else
{
IpcHandler.ReceivedMessages.Enqueue(message);
await Task.Delay(100);
}
}
}
Expand Down Expand Up @@ -108,6 +109,7 @@ await ipcHandler.SendMessageAsync(JsonConvert.SerializeObject(new IpcMessage
else
{
IpcHandler.ReceivedMessages.Enqueue(message);
await Task.Delay(100);
}
}
}
Expand Down Expand Up @@ -152,6 +154,7 @@ await ipcHandler.SendMessageAsync(JsonConvert.SerializeObject(new IpcMessage
else
{
IpcHandler.ReceivedMessages.Enqueue(message);
await Task.Delay(100);
}
}
}
Expand Down Expand Up @@ -197,6 +200,7 @@ await ipcHandler.SendMessageAsync(JsonConvert.SerializeObject(new IpcMessage
else
{
IpcHandler.ReceivedMessages.Enqueue(message);
await Task.Delay(100);
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions src/IPA.Bcfier.App/Hubs/BcfierHub.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Microsoft.AspNetCore.SignalR;

namespace IPA.Bcfier.App.Hubs
{
public class BcfierHub : Hub
{
}
}
1 change: 1 addition & 0 deletions src/IPA.Bcfier.App/IPA.Bcfier.App.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="8.0.5" />
<PackageReference Include="LightQuery.EntityFrameworkCore" Version="2.4.0" />
</ItemGroup>

Expand Down
55 changes: 55 additions & 0 deletions src/IPA.Bcfier.App/Services/PluginErrorListenerService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using IPA.Bcfier.App.Hubs;
using IPA.Bcfier.Ipc;
using Microsoft.AspNetCore.SignalR;
using Newtonsoft.Json;

namespace IPA.Bcfier.App.Services
{
public class PluginErrorListenerService : IHostedService
{
private bool _isListening;
private readonly IServiceProvider _serviceProvider;

public PluginErrorListenerService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}

public Task StartAsync(CancellationToken cancellationToken)
{
_isListening = true;
Task.Run(() => ListenAsync());
return Task.CompletedTask;
}

private async Task ListenAsync()
{
while (_isListening)
{
if (IpcHandler.ReceivedMessages.TryDequeue(out var message))
{
var ipcMessage = JsonConvert.DeserializeObject<IpcMessage>(message)!;
if (ipcMessage.Command == IpcMessageCommand.PluginErrorEncountered)
{
using var scope = _serviceProvider.CreateScope();
var hubContext = scope.ServiceProvider.GetRequiredService<IHubContext<BcfierHub>>();
await hubContext.Clients.All.SendAsync("InternalError", ipcMessage.Data);
}
else
{
IpcHandler.ReceivedMessages.Enqueue(message);
}
}


await Task.Delay(500);
}
}

public Task StopAsync(CancellationToken cancellationToken)
{
_isListening = true;
return Task.CompletedTask;
}
}
}
9 changes: 9 additions & 0 deletions src/IPA.Bcfier.App/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@
using ElectronNET.API;
using IPA.Bcfier.App.Configuration;
using IPA.Bcfier.App.Data;
using IPA.Bcfier.App.Hubs;
using IPA.Bcfier.App.Services;
using IPA.Bcfier.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json.Converters;

namespace IPA.Bcfier.App
{
Expand Down Expand Up @@ -33,6 +36,11 @@ public void ConfigureServices(IServiceCollection services)
services.AddTransient<DatabaseLocationService>();

AddDatabaseServices(services);

services.AddHostedService<PluginErrorListenerService>();

services.AddSignalR()
.AddNewtonsoftJsonProtocol(c => c.PayloadSerializerSettings.Converters.Add(new StringEnumConverter()));
}

private static void AddDatabaseServices(IServiceCollection services)
Expand Down Expand Up @@ -75,6 +83,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<BcfierHub>("/hubs/bcfier");
});

if (env.IsDevelopment())
Expand Down
10 changes: 10 additions & 0 deletions src/IPA.Bcfier.Navisworks/IpcNavisworksCommandListener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Newtonsoft.Json;
using IPA.Bcfier.Models.Bcf;
using IPA.Bcfier.Navisworks.Models;
using System.Collections.Concurrent;

namespace IPA.Bcfier.Navisworks
{
Expand Down Expand Up @@ -101,6 +102,15 @@ await _ipcHandler.SendMessageAsync(JsonConvert.SerializeObject(new IpcMessage
}
}

if (_navisworksTaskHandler.CadErrorMessages.TryDequeue(out var errorMessage))
{
await _ipcHandler.SendMessageAsync(JsonConvert.SerializeObject(new IpcMessage
{
Command = IpcMessageCommand.PluginErrorEncountered,
Data = errorMessage
}));
}

await Task.Delay(100);
}

Expand Down
106 changes: 65 additions & 41 deletions src/IPA.Bcfier.Navisworks/NavisworksTaskQueueHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Autodesk.Navisworks.Api;
using IPA.Bcfier.Navisworks.Services;
using Newtonsoft.Json.Serialization;
using System.Collections.Concurrent;

namespace IPA.Bcfier.Navisworks
{
Expand All @@ -14,6 +15,8 @@ public class NavisworksTaskQueueHandler
public Queue<ShowViewpointQueueItem> ShowViewpointQueueItems { get; } = new Queue<ShowViewpointQueueItem>();
public Queue<Func<string, Task>> GetAvailableNavisworksClashes { get; } = new Queue<Func<string, Task>>();
private bool shouldUnregister = false;
public ConcurrentQueue<string> CadErrorMessages { get; } = new ConcurrentQueue<string>();


public void OnIdling(object sender, EventArgs args)
{
Expand Down Expand Up @@ -84,56 +87,70 @@ private void HandleGetAvailableNavisworksClashes(Func<string, Task> callback, Do

private void HandleCreateNavisworksViewpointCallback(Func<string, Task> callback, Document uiDocument)
{
var viewpointService = new NavisworksViewpointCreationService(uiDocument);
var viewpoint = viewpointService.GenerateViewpoint();
var contractResolver = new DefaultContractResolver
{
NamingStrategy = new CamelCaseNamingStrategy()
};
var serializerSettings = new JsonSerializerSettings
{
ContractResolver = contractResolver,
Formatting = Formatting.Indented
};
Task.Run(async () =>
try
{
if (viewpoint == null)
var viewpointService = new NavisworksViewpointCreationService(uiDocument);
var viewpoint = viewpointService.GenerateViewpoint();
var contractResolver = new DefaultContractResolver
{
await callback("{}");
}
else
NamingStrategy = new CamelCaseNamingStrategy()
};
var serializerSettings = new JsonSerializerSettings
{
await callback(JsonConvert.SerializeObject(viewpoint, serializerSettings));
}
});
ContractResolver = contractResolver,
Formatting = Formatting.Indented
};
Task.Run(async () =>
{
if (viewpoint == null)
{
await callback("{}");
}
else
{
await callback(JsonConvert.SerializeObject(viewpoint, serializerSettings));
}
});
}
catch (Exception e)
{
CadErrorMessages.Enqueue($"Error during viewpoint creation: {Environment.NewLine}{e}");
}
}

private void HandleCreateNavisworksClashIssuesCallback(Func<string, Task> callback,
Document uiDocument,
Guid clashId)
{
var viewpointService = new NavisworksViewpointCreationService(uiDocument);
var clashIssues = viewpointService.CreateClashIssues(clashId);
var contractResolver = new DefaultContractResolver
try
{
NamingStrategy = new CamelCaseNamingStrategy()
};
var serializerSettings = new JsonSerializerSettings
{
ContractResolver = contractResolver,
Formatting = Formatting.Indented
};
Task.Run(async () =>
{
if (clashIssues == null)
var viewpointService = new NavisworksViewpointCreationService(uiDocument);
var clashIssues = viewpointService.CreateClashIssues(clashId);
var contractResolver = new DefaultContractResolver
{
await callback("[]");
}
else
NamingStrategy = new CamelCaseNamingStrategy()
};
var serializerSettings = new JsonSerializerSettings
{
await callback(JsonConvert.SerializeObject(clashIssues, serializerSettings));
}
});
ContractResolver = contractResolver,
Formatting = Formatting.Indented
};
Task.Run(async () =>
{
if (clashIssues == null)
{
await callback("[]");
}
else
{
await callback(JsonConvert.SerializeObject(clashIssues, serializerSettings));
}
});
}
catch (Exception e)
{
CadErrorMessages.Enqueue($"Error during clash issues creation: {Environment.NewLine}{e}");
}
}

private void HandleShowNavisworksViewpointCallback(Func<Task>? callback, BcfViewpoint? viewpoint, Document uiDocument)
Expand All @@ -143,9 +160,16 @@ private void HandleShowNavisworksViewpointCallback(Func<Task>? callback, BcfView
return;
}

var viewpointService = new NavisworksViewpointDisplayService(uiDocument);
viewpointService.DisplayViewpoint(viewpoint);
Task.Run(async () => await callback());
try
{
var viewpointService = new NavisworksViewpointDisplayService(uiDocument);
viewpointService.DisplayViewpoint(viewpoint);
Task.Run(async () => await callback());
}
catch (Exception e)
{
CadErrorMessages.Enqueue($"Error during viewpoint rendering: {Environment.NewLine}{e}");
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Autodesk.Navisworks.Api;
using Autodesk.Navisworks.Api;
using Autodesk.Navisworks.Api.Clash;
using IPA.Bcfier.Models.Bcf;
using IPA.Bcfier.Models.Clashes;
Expand All @@ -21,18 +21,10 @@ public NavisworksViewpointCreationService(Document doc)
///<returns></returns>
public BcfViewpoint? GenerateViewpoint()
{
try
{
var viewpoint = _doc.CurrentViewpoint.Value;
NavisUtils.GetGunits(_doc);
var v = GetViewpointFromNavisworksViewpoint(viewpoint);
return v;
}
catch
{
// We're not handling errors here at the moment, we just fail☹
return null;
}
var viewpoint = _doc.CurrentViewpoint.Value;
NavisUtils.GetGunits(_doc);
var v = GetViewpointFromNavisworksViewpoint(viewpoint);
return v;
}

private BcfViewpoint GetViewpointFromNavisworksViewpoint(Viewpoint viewpoint)
Expand Down
4 changes: 3 additions & 1 deletion src/IPA.Bcfier/Ipc/IpcMessageCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public enum IpcMessageCommand

GetNavisworksAvailableClashes = 7,

NavisworksAvailableClashes = 8
NavisworksAvailableClashes = 8,

PluginErrorEncountered = 9
}
}
Loading

0 comments on commit d0e174f

Please sign in to comment.