fix: correlate script-driven PXP-OA command events
This commit is contained in:
+26
-6
@@ -24,6 +24,7 @@ internal static class ScriptDrivenFirstApplyAutomation
|
||||
private static readonly List<string> transitions = [];
|
||||
private static readonly List<string> commandEvents = [];
|
||||
private static readonly List<AutomationSentinelEvidence> sentinels = [];
|
||||
private static readonly List<AutomationCommandCorrelationEvidence> correlations = [];
|
||||
private static PxpOaDiscoveryEvidence? discovery;
|
||||
private static bool prepared;
|
||||
private static bool terminal;
|
||||
@@ -104,7 +105,9 @@ internal static class ScriptDrivenFirstApplyAutomation
|
||||
Guard(() =>
|
||||
{
|
||||
commandEvents.Add("WillStart:" + args.GlobalCommandName);
|
||||
if (!IsFixture(sender) || !IsPxp(args.GlobalCommandName) || runs.Count >= 2) return;
|
||||
var correlation = Correlate("WillStart", sender, args.GlobalCommandName, runs.Count < 2);
|
||||
correlations.Add(correlation);
|
||||
if (correlation.RejectionReason is not null) return;
|
||||
runs.Add(new Run(runs.Count + 1, null, [], null, 0, 0, Dbmod(), null, Counts(database!), null, true, false, false, false, null, null));
|
||||
transitions.Add("PxpOaWillStart:" + runs.Count);
|
||||
});
|
||||
@@ -116,8 +119,11 @@ internal static class ScriptDrivenFirstApplyAutomation
|
||||
{
|
||||
Guard(() =>
|
||||
{
|
||||
commandEvents.Add((failed ? "Failed:" : cancelled ? "Cancelled:" : "Ended:") + args.GlobalCommandName);
|
||||
if (!IsFixture(sender) || !IsPxp(args.GlobalCommandName) || runs.Count == 0) return;
|
||||
var kind = failed ? "Failed" : cancelled ? "Cancelled" : "Ended";
|
||||
commandEvents.Add(kind + ":" + args.GlobalCommandName);
|
||||
var correlation = Correlate(kind, sender, args.GlobalCommandName, runs.Count > 0);
|
||||
correlations.Add(correlation);
|
||||
if (correlation.RejectionReason is not null) return;
|
||||
var last = runs[^1];
|
||||
if (last.Ended || last.Failed || last.Cancelled) return;
|
||||
runs[^1] = last with { Ended = !failed && !cancelled, Failed = failed, Cancelled = cancelled, DbmodAfter = Dbmod(), After = Counts(database!) };
|
||||
@@ -125,8 +131,22 @@ internal static class ScriptDrivenFirstApplyAutomation
|
||||
Write(false, null);
|
||||
});
|
||||
}
|
||||
private static bool IsFixture(object sender) => !terminal && fixture is not null && ReferenceEquals(sender, fixture) && database is not null && ReferenceEquals(fixture.Database, database);
|
||||
private static bool IsPxp(string name) => string.Equals(name.TrimStart('.', '_'), "PXP-OA", StringComparison.OrdinalIgnoreCase);
|
||||
private static AutomationCommandCorrelationEvidence Correlate(string kind, object sender, string rawName, bool sequenceAccepted)
|
||||
{
|
||||
var normalized = rawName.Trim();
|
||||
var command = string.Equals(normalized, "PXP-OA", StringComparison.OrdinalIgnoreCase);
|
||||
var state = prepared && !terminal && config is not null && fixture is not null && database is not null;
|
||||
var senderDocument = sender as Document;
|
||||
var senderPath = senderDocument?.Name;
|
||||
var expectedPath = config?.OrthoDrawingPath;
|
||||
var activePath = AcadApplication.DocumentManager.MdiActiveDocument?.Name;
|
||||
var fixturePath = senderPath is not null && expectedPath is not null && SamePath(senderPath, expectedPath);
|
||||
var activeFixture = activePath is not null && expectedPath is not null && SamePath(activePath, expectedPath);
|
||||
var document = fixturePath && activeFixture;
|
||||
var databaseMatch = senderDocument?.Database is not null && database is not null && SamePath(senderDocument.Database.Filename, database.Filename);
|
||||
var rejection = !command ? "COMMAND_NAME_MISMATCH" : !state ? "NOT_PREPARED" : !document ? "DOCUMENT_IDENTITY_MISMATCH" : !databaseMatch ? "DATABASE_IDENTITY_MISMATCH" : !sequenceAccepted ? "UNEXPECTED_SEQUENCE" : null;
|
||||
return new(kind, rawName, normalized, command, state, document, databaseMatch, fixturePath, sequenceAccepted, rejection, sender.GetType().FullName, senderPath, expectedPath, activePath, runs.Count, DateTimeOffset.UtcNow);
|
||||
}
|
||||
private static void Guard(Action action) { try { if (!terminal) action(); } catch (System.Exception ex) { Fail("AUTOMATION_EVENT_HANDLER_FAILED", ex); } }
|
||||
private static void Fail(string code, System.Exception exception) { if (terminal) return; terminal = true; transitions.Add("Failed:" + code); try { Write(false, code + ":" + exception); } finally { Unsubscribe(); } }
|
||||
private static void Unsubscribe() { if (fixture is null) return; try { fixture.CommandWillStart -= OnWillStart; fixture.CommandEnded -= OnEnded; fixture.CommandFailed -= OnFailed; fixture.CommandCancelled -= OnCancelled; } catch { } }
|
||||
@@ -154,7 +174,7 @@ internal static class ScriptDrivenFirstApplyAutomation
|
||||
{
|
||||
if (config is null) return;
|
||||
var first = runs.ElementAtOrDefault(0); var second = runs.ElementAtOrDefault(1);
|
||||
var evidence = new FirstApplyAutomationEvidence { Phase = config.Phase, Completed = completed, Prepared = prepared, FunctionalEvidenceCompleted = completed, ErrorCode = error, DbmodBefore = dbmodBaseline, DbmodAfterCommand1 = first?.DbmodAfter, DbmodAfterCommand2 = second?.DbmodAfter, Baseline = baseline, AfterCommand1 = first?.After, AfterCommand2 = second?.After, CompletedCommands = runs.Where(x => x.Ended).Select(x => "PXP-OA").ToArray(), PlanIdRun1 = first?.PlanId, PlanIdRun2 = second?.PlanId, PlanIdsEqual = first is not null && second is not null ? string.Equals(first.PlanId, second.PlanId, StringComparison.Ordinal) : null, EligibleCandidateCount = first?.Candidates.Count, SelectedCandidateHash = first?.Candidates.OrderBy(x => x, StringComparer.Ordinal).FirstOrDefault(), ViewHash = first?.View, CreateRun1 = first?.Create, CreateRun2 = second?.Create, SkipRun2 = second?.Skip, CommandsCompleted = runs.Count == 2 && runs.All(x => x.Ended), InspectorsCompleted = baseline is not null && first?.After is not null && second?.After is not null, EvidenceFlushed = true, CurrentState = terminal ? (completed ? "Completed" : "Failed") : "Prepared", StateTransitions = transitions, PxpOaDiscovery = discovery, Sentinels = sentinels, CommandEvents = commandEvents };
|
||||
var evidence = new FirstApplyAutomationEvidence { Phase = config.Phase, Completed = completed, Prepared = prepared, FunctionalEvidenceCompleted = completed, ErrorCode = error, DbmodBefore = dbmodBaseline, DbmodAfterCommand1 = first?.DbmodAfter, DbmodAfterCommand2 = second?.DbmodAfter, Baseline = baseline, AfterCommand1 = first?.After, AfterCommand2 = second?.After, CompletedCommands = runs.Where(x => x.Ended).Select(x => "PXP-OA").ToArray(), PlanIdRun1 = first?.PlanId, PlanIdRun2 = second?.PlanId, PlanIdsEqual = first is not null && second is not null ? string.Equals(first.PlanId, second.PlanId, StringComparison.Ordinal) : null, EligibleCandidateCount = first?.Candidates.Count, SelectedCandidateHash = first?.Candidates.OrderBy(x => x, StringComparer.Ordinal).FirstOrDefault(), ViewHash = first?.View, CreateRun1 = first?.Create, CreateRun2 = second?.Create, SkipRun2 = second?.Skip, CommandsCompleted = runs.Count == 2 && runs.All(x => x.Ended), InspectorsCompleted = baseline is not null && first?.After is not null && second?.After is not null, EvidenceFlushed = true, CurrentState = terminal ? (completed ? "Completed" : "Failed") : "Prepared", StateTransitions = transitions, PxpOaDiscovery = discovery, Sentinels = sentinels, CommandEvents = commandEvents, CommandCorrelations = correlations };
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(config.EvidencePath)!);
|
||||
var temp = config.EvidencePath + ".tmp"; File.WriteAllText(temp, JsonSerializer.Serialize(evidence)); File.Move(temp, config.EvidencePath, true);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user