fix: wait for AutoCAD command-queue readiness barrier

This commit is contained in:
codex
2026-08-04 07:28:32 +03:00
parent 1b4ff816ba
commit 98564b807f
3 changed files with 23 additions and 2 deletions
@@ -50,6 +50,12 @@ public sealed class EntryPoint : IExtensionApplication
[CommandMethod("PHP_REC_AUTOMATION_START", CommandFlags.Session)] [CommandMethod("PHP_REC_AUTOMATION_START", CommandFlags.Session)]
public void AutomationStartCommand() => FirstLimitedApplyAutomationBootstrap.Arm(); public void AutomationStartCommand() => FirstLimitedApplyAutomationBootstrap.Arm();
// Test-only command-queue barrier. It deliberately performs no Plant or
// drawing work; its CommandEnded event proves the activated document is
// ready before the coordinator calls the Plant APIs.
[CommandMethod("PHP_REC_AUTOMATION_READY")]
public void AutomationReadyCommand() { }
private static void RunDiagnostic(string commandName) private static void RunDiagnostic(string commandName)
{ {
var operationId = Guid.NewGuid().ToString("N"); var operationId = Guid.NewGuid().ToString("N");
@@ -204,7 +204,7 @@ internal sealed class FirstLimitedApplyAutomationCoordinator
{ {
fixtureDocumentActivated = true; fixtureDocumentActivated = true;
transitions.Add("FixtureDocumentActiveAfterOpen"); transitions.Add("FixtureDocumentActiveAfterOpen");
TryActivateProjectAndVerifyContext(); QueueReadinessBarrier();
} }
} }
catch (System.Exception ex) { FailFromCallback("Start", ex, "AUTOMATION_START_FAILED"); } catch (System.Exception ex) { FailFromCallback("Start", ex, "AUTOMATION_START_FAILED"); }
@@ -270,11 +270,23 @@ internal sealed class FirstLimitedApplyAutomationCoordinator
transitions.Add("CommandQueued:" + command); transitions.Add("CommandQueued:" + command);
document.SendStringToExecute(command + " ", true, false, false); document.SendStringToExecute(command + " ", true, false, false);
} }
private void QueueReadinessBarrier()
{
if (IsTerminal || document is null) return;
transitions.Add("ReadinessBarrierQueued");
document.SendStringToExecute("PHP_REC_AUTOMATION_READY ", true, false, false);
}
private void OnCommandEnded(object sender, CommandEventArgs e) private void OnCommandEnded(object sender, CommandEventArgs e)
{ {
RunCallback("CommandEnded", () => RunCallback("CommandEnded", () =>
{ {
var name = e.GlobalCommandName?.Trim().TrimStart('.', '_').ToUpperInvariant(); var name = e.GlobalCommandName?.Trim().TrimStart('.', '_').ToUpperInvariant();
if (name == "PHP_REC_AUTOMATION_READY")
{
transitions.Add("ReadinessBarrierCompleted");
TryActivateProjectAndVerifyContext();
return;
}
if (name is not ("PXP-OA" or "UNDO" or "U")) return; if (name is not ("PXP-OA" or "UNDO" or "U")) return;
completed.Add(name); completed.Add(name);
transitions.Add("CommandCompleted:" + name); transitions.Add("CommandCompleted:" + name);
@@ -61,6 +61,7 @@ public sealed class FoundationTests
Assert.Contains("[CommandMethod(\"PHP_REC_ANNOT\")]", source); Assert.Contains("[CommandMethod(\"PHP_REC_ANNOT\")]", source);
Assert.Contains("[CommandMethod(\"PXP-AAV\")]", source); Assert.Contains("[CommandMethod(\"PXP-AAV\")]", source);
Assert.Contains("[CommandMethod(\"PXP-OA\")]", source); Assert.Contains("[CommandMethod(\"PXP-OA\")]", source);
Assert.Contains("PHP_REC_AUTOMATION_READY", source);
} }
[Fact] public void AutomationBootstrap_DefersPlantAndDocumentAccessUntilCoordinator() [Fact] public void AutomationBootstrap_DefersPlantAndDocumentAccessUntilCoordinator()
@@ -104,7 +105,9 @@ public sealed class FoundationTests
var start = source[source.IndexOf("public void Start()", StringComparison.Ordinal)..source.IndexOf("private void CompleteLifecycleProbe", StringComparison.Ordinal)]; var start = source[source.IndexOf("public void Start()", StringComparison.Ordinal)..source.IndexOf("private void CompleteLifecycleProbe", StringComparison.Ordinal)];
Assert.Contains("FixtureDocumentActiveAfterOpen", start); Assert.Contains("FixtureDocumentActiveAfterOpen", start);
Assert.Contains("string.Equals(activeDocument.Name, document.Name", start); Assert.Contains("string.Equals(activeDocument.Name, document.Name", start);
Assert.Contains("TryActivateProjectAndVerifyContext();", start); Assert.Contains("QueueReadinessBarrier();", start);
Assert.Contains("ReadinessBarrierCompleted", source);
Assert.Contains("TryActivateProjectAndVerifyContext();", source);
} }
[Fact] public void AutomationControlledExit_QueuesNativeQuitAfterPublicCommand() [Fact] public void AutomationControlledExit_QueuesNativeQuitAfterPublicCommand()