Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
91188b9
Added the new error states, as well as an enum to define the behavior…
nkleiner Apr 28, 2026
4c3679f
Error handling updates
nkleiner Apr 29, 2026
25ce589
Merge branch 'Develop' into UserDefinableErrorHandling
nkleiner May 8, 2026
454cc83
Settings menu now has a functionable selection process for handling e…
nkleiner May 12, 2026
f49f299
Working towards integrating the new settings into the loop. First wit…
nkleiner May 12, 2026
fc27ce1
Spacing change
nkleiner May 12, 2026
6d6186c
Working on adding some general settings
nkleiner May 14, 2026
6edeb8e
Forgot some additional changes
nkleiner May 14, 2026
8460a5e
Some cleanup and additional UI for general settings
nkleiner May 14, 2026
8cc1d74
Most error handling cases are now working. Only outlier left is the "…
nkleiner May 14, 2026
1f417d7
Basic implementation of the user decision request for when commands f…
nkleiner May 15, 2026
a792cb8
Updates to solidify execution logic in the new "state based" executio…
nkleiner May 18, 2026
d9b1fc1
Updates to support durations in settings values
nkleiner May 18, 2026
612daa3
Updated entity configurations
nkleiner May 18, 2026
3f1c39f
Updated system settings to handle new duration type gracefully
nkleiner May 18, 2026
201a0a8
Merge branch 'Develop' into UserDefinableErrorHandling
nkleiner Jun 1, 2026
78eee8d
Merge branch 'Develop' into UserDefinableErrorHandling
nkleiner Jun 3, 2026
a83c5b0
Fixed some tests
nkleiner Jun 3, 2026
271774b
Fixed some bugs in the retry command logic. Added notifications to co…
nkleiner Jun 4, 2026
0564bc1
Updates to make the notification stream a bit more stable and thread …
nkleiner Jun 4, 2026
6531f6c
Report status consistently
nkleiner Jun 4, 2026
4519ca9
Migration updates
nkleiner Jun 4, 2026
f555277
Fixed some tests
nkleiner Jun 4, 2026
e0ef999
Fixed the waiting for user not working
nkleiner Jun 4, 2026
cb18639
Fixed duplicate entity config. Fixed visual bug in execution screen.
nkleiner Jun 4, 2026
66cdacf
Provide status code to plan requests
nkleiner Jun 10, 2026
ef7e72a
Merge branch 'Develop' into UserDefinableErrorHandling
nkleiner Jun 17, 2026
824d734
Working on campaign executor
nkleiner Jun 17, 2026
153cdc6
Updated toolkit version
nkleiner Jun 18, 2026
c593475
Merge branch 'Develop' into UserDefinableErrorHandling
nkleiner Jun 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Ares.Core.Tests/Execution/CampaignExecutorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ public void SetUp()
It.IsAny<RequestMetadata>(),
It.IsAny<IEnumerable<Parameter>>(),
It.IsAny<IEnumerable<Ares.Datamodel.Analyzing.Analysis>>(),
It.IsAny<IEnumerable<ExperimentOverview>>(),
It.IsAny<IEnumerable<ExperimentOverview>>(),
It.IsAny<PlanStatusCode>(),
It.IsAny<CancellationToken>()))
.ReturnsAsync(true);

Expand Down Expand Up @@ -217,7 +218,8 @@ public async Task Replan_Composes_And_Executes_Experiment_Again()
It.IsAny<RequestMetadata>(),
It.IsAny<IEnumerable<Parameter>>(),
It.IsAny<IEnumerable<Ares.Datamodel.Analyzing.Analysis>>(),
It.IsAny<IEnumerable<ExperimentOverview>>(),
It.IsAny<IEnumerable<ExperimentOverview>>(),
It.IsAny<PlanStatusCode>(),
It.IsAny<CancellationToken>()), Times.Once);
}

Expand Down
8 changes: 8 additions & 0 deletions Ares.Core/Execution/Enums/ExperimentLoopOutcome.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Ares.Core.Execution.Enums;

public enum ExperimentLoopOutcome
{
Succeeded,
Failed,
Canceled
}
15 changes: 15 additions & 0 deletions Ares.Core/Execution/Enums/ExperimentPhase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Ares.Core.Execution.Enums;

public enum ExperimentPhase
{
Initialize,
Plan,
Compose,
Execute,
Analyze,
Retry,
Replan,
Complete,
Failed,
Canceled
}
60 changes: 33 additions & 27 deletions Ares.Core/Execution/Executors/CampaignExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Ares.Core.Device.State.Logging;
using Ares.Core.Exceptions;
using Ares.Core.Execution.ControlTokens;
using Ares.Core.Execution.Enums;
using Ares.Core.Execution.Executors.Composers;
using Ares.Core.Execution.Extensions;
using Ares.Core.Execution.Safety;
Expand All @@ -13,6 +14,7 @@
using Ares.Core.Settings;
using Ares.Datamodel;
using Ares.Datamodel.Analyzing;
using Ares.Datamodel.Planning;
using Ares.Datamodel.Templates;
using Google.Protobuf.WellKnownTypes;
using Microsoft.Extensions.Logging;
Expand All @@ -22,28 +24,7 @@
namespace Ares.Core.Execution.Executors;

public class CampaignExecutor : ICampaignExecutor
{
private enum ExperimentPhase
{
Initialize,
Plan,
Compose,
Execute,
Analyze,
Retry,
Replan,
Complete,
Failed,
Canceled
}

private enum ExperimentLoopOutcome
{
Succeeded,
Failed,
Canceled
}

{
private readonly IExecutionReporter _executionReporter;
private readonly ISubject<CampaignExecutionStatus> _executionStatusSubject;
private readonly ICommandComposer<ExperimentTemplate, ExperimentExecutor> _experimentComposer;
Expand All @@ -66,6 +47,7 @@ private enum ExperimentLoopOutcome
private ExperimentTemplate? _currentExperimentTemplate = null;
private int _experimentCount = 0;
private TaskCompletionSource<ErrorHandling>? _userDecisionSource;
private PlanStatusCode _latestPlanStatusCode = PlanStatusCode.PlanStatusUnspecified;

internal CampaignExecutor(ICommandComposer<ExperimentTemplate, ExperimentExecutor> experimentComposer,
IPlanningHelper planningHelper,
Expand Down Expand Up @@ -227,7 +209,11 @@ private async Task NotifyCampaignStart()
return (true, startupSummary);
}

private async Task<ExperimentLoopOutcome> ExecuteExperimentLoop(string campaignPath, List<Analysis> analyses, List<ExperimentExecutionSummary> experimentSummaries, ExecutionControlToken token, ExperimentExecutionSummary startupSummary)
private async Task<ExperimentLoopOutcome> ExecuteExperimentLoop(string campaignPath,
List<Analysis> analyses,
List<ExperimentExecutionSummary> experimentSummaries,
ExecutionControlToken token,
ExperimentExecutionSummary startupSummary)
{
var currentPhase = ExperimentPhase.Initialize;
var currentExperimentPath = "";
Expand Down Expand Up @@ -398,9 +384,17 @@ private async Task<ExperimentPhase> ExecuteCurrentExperiment(string currentExper
.SelectMany(s => s.CommandSummaries)
.FirstOrDefault(c => !c.Result.Success);

return failedCommandSummary is null
? ExperimentPhase.Analyze
: await HandleError(failedCommandSummary, token);
if(failedCommandSummary is null)
{
_latestPlanStatusCode = PlanStatusCode.PlanAccepted;
return ExperimentPhase.Analyze;
}

else
{
UpdatePlanStatus(failedCommandSummary.StatusCode);
return await HandleError(failedCommandSummary, token);
}
}

private async Task<ExperimentPhase> AnalyzeCurrentExperiment(ExperimentExecutionSummary startupSummary, List<Analysis> analyses, List<ExperimentExecutionSummary> experimentSummaries, ExecutionControlToken token)
Expand Down Expand Up @@ -480,6 +474,7 @@ private async Task<ExperimentPhase> HandleError(CommandExecutionSummary cmdSumma

var decisionSource = new TaskCompletionSource<ErrorHandling>(TaskCreationOptions.RunContinuationsAsynchronously);
_userDecisionSource = decisionSource;

try
{
errorHandling = await decisionSource.Task.WaitAsync(token.CancellationToken);
Expand Down Expand Up @@ -517,6 +512,15 @@ private async Task<ExperimentPhase> HandleError(CommandExecutionSummary cmdSumma
}
}

private void UpdatePlanStatus(CommandStatusCode failCode)
{
if(failCode == CommandStatusCode.OutOfRange || failCode == CommandStatusCode.ParametersUnachievable)
_latestPlanStatusCode = PlanStatusCode.PlanUnachievable;

else
_latestPlanStatusCode = PlanStatusCode.PlanFailed;
}

private async Task<bool> PlanExperiment(List<Analysis> analyses, ExperimentTemplate currentExperimentTemplate, List<ExperimentExecutionSummary> experimentSummaries, ExecutionControlToken token)
{
Status.PlannerState = PlannerState.PlanningInProgress;
Expand All @@ -537,6 +541,7 @@ private async Task<bool> PlanExperiment(List<Analysis> analyses, ExperimentTempl
currentExperimentTemplate.GetAllPlannedParameters(),
analyses,
experimentSummaries.Select(es => es.ExperimentOverview),
_latestPlanStatusCode,
token.CancellationToken);

if(!resolveSuccess)
Expand Down Expand Up @@ -745,7 +750,8 @@ private async Task<ExperimentExecutorResult> GenerateExperimentExecutor(Experime
metadata,
experimentTemplate.GetAllPlannedParameters(),
analyses,
previousExperiments,
previousExperiments,
PlanStatusCode.PlanAccepted,
cancellationToken);

if(!resolveSuccess)
Expand Down
1 change: 0 additions & 1 deletion Ares.Core/Execution/Executors/CommandExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ public async Task<CommandExecutionSummary> Execute(ExecutionControlToken token,

Status.Result = result.Result;
_stateSubject.OnNext(Status);
_stateSubject.OnCompleted();

return ExecutorSummaryHelpers.CreateCommandExecutionSummary(Template, result, timeStarted, DateTime.UtcNow);
}
Expand Down
3 changes: 2 additions & 1 deletion Ares.Core/Execution/Executors/ExecutorSummaryHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ public static CommandExecutionSummary CreateCommandExecutionSummary(CommandTempl
CommandDescription = template.Metadata.Description,
CommandName = template.Metadata.Name,
StatusCode = deviceResult?.StatusCode ?? CommandStatusCode.StatusUnspecified
};
};


if(template.HasOutputVarName)
commandExecutionSummary.VarName = template.OutputVarName;
Expand Down
1 change: 1 addition & 0 deletions Ares.Core/Execution/Executors/ExperimentExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public ExperimentExecutor(ExperimentTemplate template, IExecutor<StepExecutionSu

Status.StepExecutionStatuses.AddRange(experimentStepExecutors.Select(executor => executor.Status));


var experimentStepExecutionObservation = experimentStepExecutors.Select(executor =>
{
return executor.ExperimentStatusObservable.Select(_ =>
Expand Down
1 change: 1 addition & 0 deletions Ares.Core/Planning/IPlanningHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Task<bool> TryResolveParameters(IEnumerable<PlannerAllocation> plannerAllocation
IEnumerable<Parameter> parameters,
IEnumerable<Analysis> seedAnalyses,
IEnumerable<ExperimentOverview> seedExperiments,
PlanStatusCode code,
CancellationToken cancellationToken);

/// <summary>
Expand Down
2 changes: 2 additions & 0 deletions Ares.Core/Planning/PlanningHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
IEnumerable<Parameter> parameters,
IEnumerable<Analysis> seedAnalyses,
IEnumerable<ExperimentOverview> seedExperiments,
PlanStatusCode statusCode,
CancellationToken cancellationToken)
{
var parameterArray = parameters.ToArray();
Expand Down Expand Up @@ -72,6 +73,7 @@
var planRequest = new PlanningRequest();
planRequest.PlanningParameters.AddRange(plannableParameters.Select(parameter => ConvertToPlanningParameter(parameter, seedExperiments)));
planRequest.AnalysisResults.AddRange(seedAnalysesArr.Select(a => (double)a.Result));
planRequest.PreviousPlanStatusCode = statusCode;
planRequest.Metadata = metadata;
planTransaction.PlanningRequest = planRequest;

Expand All @@ -79,13 +81,13 @@
planTransaction.TimeResponseReceived = DateTime.UtcNow.ToTimestamp();
planTransaction.PlanningResponse = planResponse;

if(planResponse.PlanningOutcome == Outcome.Failure)

Check warning on line 84 in Ares.Core/Planning/PlanningHelper.cs

View workflow job for this annotation

GitHub Actions / build-and-test

'PlanningResponse.PlanningOutcome' is obsolete
{
if(string.IsNullOrWhiteSpace(planResponse.ErrorString))

Check warning on line 86 in Ares.Core/Planning/PlanningHelper.cs

View workflow job for this annotation

GitHub Actions / build-and-test

'PlanningResponse.ErrorString' is obsolete
await _notifier.Notify("Planner Error!", "Planner reported that planning failed, but did not provide any specific error as to why.", NotificationSeverityEnum.Error);

else
await _notifier.Notify($"Planner Reported Error: {planResponse.ErrorString}", "Planner Error!", NotificationSeverityEnum.Error);

Check warning on line 90 in Ares.Core/Planning/PlanningHelper.cs

View workflow job for this annotation

GitHub Actions / build-and-test

'PlanningResponse.ErrorString' is obsolete

return false;
}
Expand Down
1 change: 1 addition & 0 deletions UI/Components/Layouts/MainLayout.razor
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@
Tracker.OnSystemReady -= HandleSystemReady;
notificationService.OnNotificationReceived -= HandleBackgroundNotification;
_driverSubscription?.Dispose();

_cts.Cancel();
_cts.Dispose();
}
Expand Down
1 change: 1 addition & 0 deletions UI/Features/Execution/ExecutionViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ private async Task RefreshExecutionEligibility()
LastExecutionEligibility = await _automationClient.CheckExecutionEligibility(new Empty(), null);
}


public async Task ExecutionNotesUploaded(Stream fileStream)
{
using var reader = new StreamReader(fileStream);
Expand Down
Loading