Skip to content

chore: revert non-CI changes from main branch#5

Merged
BenjaminMichaelis merged 7 commits into
mainfrom
benjaminmichaelis/remove-non-ci-changes
May 29, 2026
Merged

chore: revert non-CI changes from main branch#5
BenjaminMichaelis merged 7 commits into
mainfrom
benjaminmichaelis/remove-non-ci-changes

Conversation

@BenjaminMichaelis

@BenjaminMichaelis BenjaminMichaelis commented May 29, 2026

Copy link
Copy Markdown
Owner

The fork's main branch is a PR submitted upstream to dotnet/interactive. The only changes it should contain are the DevOps-to-GHA CI migration. Several accidental non-CI changes had crept in and need to be removed before the upstream PR can be cleanly reviewed.

What was reverted

Five files restored to their upstream dotnet/interactive state:

  • src/dotnet-interactive/KernelExtensions.cs -- Barrier-based form input synchronization refactor (replaced TaskCompletionSource approach)
  • src/Microsoft.DotNet.Interactive.Jupyter/JupyterKernel.cs -- inline-await refactor
  • src/Microsoft.DotNet.Interactive.Jupyter/JupyterKernelCommandHandlers.cs -- inline-await refactor
  • README.md -- fork branding ("Polyglossy Interactive") that must not go upstream
  • Directory.Build.targets -- spurious blank line

What was intentionally kept

The src/polyglot-notebooks*/package-lock.json files contain registry URL changes from pkgs.dev.azure.com (Azure DevOps internal feed) to registry.npmjs.org. These are CI-related -- they are required for npm ci to succeed on public GitHub Actions runners and must stay in the upstream PR.

Remove accidental non-CI changes that should not be part of the
DevOps-to-GHA CI migration PR:
- Revert KernelExtensions.cs Barrier refactor
- Revert JupyterKernel.cs and JupyterKernelCommandHandlers.cs inline-await refactors
- Revert README.md to upstream content
- Revert Directory.Build.targets whitespace change

Package-lock.json registry URL changes (npmjs.org) are kept as they
are required for npm ci to work on public GitHub Actions runners.
On fast Linux GHA runners the Jupyter reply can arrive before
reply.ToTask(token) subscribes to the observable, causing the task
to hang indefinitely (missed message, no more OnNext ever fires).

Subscribe first, then send -- so no reply is ever missed:

  var replyTask = reply.ToTask(token);   // subscribe
  await sender.SendAsync(request);       // then send
  var results = await replyTask;

Same fix applied to processMessages in JupyterKernelCommandHandlers.
This was the root cause of consistent 10-min hang-dumps on Linux CI.
Add two deterministic tests using Subject<Message> (identical to the
real IMessageReceiver.Messages hot observable) that prove:

- Buggy order (send then subscribe): reply emitted before ToTask()
  subscribes is permanently missed -- task hangs, never completes.

- Fixed order (subscribe then send): subscription is active when
  reply arrives -- task completes immediately with the correct result.

This documents the root cause of the consistent 10-min hang-dumps
seen on Linux GHA runners where in-process mock senders complete
synchronously before ToTask() establishes its subscription.
Add two test classes to Microsoft.DotNet.Interactive.Jupyter.Tests:

- RunOnKernelAsyncRaceConditionTests: pattern-level proof using Subject<Message>
  directly. Shows that fire-before-subscribe on a hot observable permanently
  misses the message (buggy order), and subscribe-before-fire captures it (fixed
  order). Verified passing locally.

- JupyterKernelCreateAsync_SynchronousSenderTests: integrated test calling
  JupyterKernel.CreateAsync with a SynchronousKernelInfoSender that fires
  KernelInfoReply synchronously inside SendAsync. Fails with upstream code
  (subscribe-after-send); passes with the fix (subscribe-before-send).

Also add InternalsVisibleTo for the test project to the Jupyter csproj so
JupyterKernel (internal class) is accessible from tests.
…ition test

The previous approach used InternalsVisibleTo on the production assembly to access
JupyterKernel (internal class) directly from tests. This is unnecessary and obscures
the design.

The new approach tests through the existing public test infrastructure:
  SynchronousKernelInfoTracker (IMessageTracker)
  -> TestJupyterKernelConnection -> TestJupyterConnection
  -> SimulatedJupyterConnectionOptions -> CreateJupyterKernelAsync

This exercises the full production stack (ConnectJupyterKernelDirective
-> JupyterKernelConnector.CreateKernelAsync -> JupyterKernel.CreateAsync
-> RunOnKernelAsync) without any InternalsVisibleTo.

Also removes the RunOnKernelAsyncRaceConditionTests pattern tests, which only
exercised System.Reactive and did not test any production code.
@BenjaminMichaelis
BenjaminMichaelis merged commit 04643d7 into main May 29, 2026
2 checks passed
BenjaminMichaelis added a commit that referenced this pull request May 29, 2026
…-non-ci-changes

chore: revert non-CI changes from main branch
BenjaminMichaelis added a commit that referenced this pull request May 29, 2026
…-non-ci-changes

chore: revert non-CI changes from main branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant