Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better align shutdown semantics of testing event loops #2800

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

simonjbeaumont
Copy link
Contributor

@simonjbeaumont simonjbeaumont commented Jul 19, 2024

Motivation:

The two testing event loops—EmbeddedEventLoop and NIOAsyncTestingEventLoop—have different semantics for outstanding work during shutdown, which are both different from the production SelectableEventLoop, specifically with newly scheduled tasks that result from running existing scheduled work at the time of shutdown.

There are three axes to consider:

  1. Scheduled tasks that are at or past their deadline.
  2. Scheduled tasks with a deadline in the future.
  3. Newly scheduled work that result from either running or cancelling (1) and (2).
(1) (2) (3)
SelectableEventLoop Run Cancel Quiesce over 1000 ticks, repeatedly run resulting (1) and cancel resulting (2)
EmbeddedEventLoop Run Cancel Cancel resulting (1) and resulting (2)
NIOAsyncTestingEventLoop Run Run Run resulting (1) and resulting (2)

Note that NIOAsyncTestingEventLoop may never terminate because of this.

Modifications:

This PR aligns EmbeddedEventLoop and NIOTestingEventLoop and makes them more similar to SelectableEventLoop and less surprising semantics.

Result:

(1) (2) (3)
SelectableEventLoop Run Cancel Quiesce over 1000 ticks, repeatedly run resulting (1) and cancel resulting (2)
EmbeddedEventLoop Run Cancel Cancel resulting (1) and resulting (2)
NIOAsyncTestingEventLoop Run Cancel Cancel resulting (1) and resulting (2)

Future work:

Given both the EmbeddedEventLoop and NIOAsyncTestingEventLoop are used in tests of NIO applications that run with SelectableEventLoop in production, it might be worth extending both to also support quiescing to give a more representative shutdown behaviour in tests.

@simonjbeaumont simonjbeaumont marked this pull request as ready for review July 19, 2024 16:08
@Lukasa Lukasa added the patch-version-bump-only For PRs that when merged will only cause a bump of the patch version, ie. 1.0.x -> 1.0.(x+1) label Jul 19, 2024
@@ -95,6 +95,10 @@ public final class NIOAsyncTestingEventLoop: EventLoop, @unchecked Sendable {
/// The queue on which we run all our operations.
private let queue = DispatchQueue(label: "io.swiftnio.AsyncEmbeddedEventLoop")

private enum State: Int, AtomicValue { case open, closing, closed }
private let _state = ManagedAtomic(State.open)
private var state: State { self._state.load(ordering: .relaxed) }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The atomic ordering here seems likely to be logically wrong. We should probably force ourselves to express it at all points.

@@ -150,6 +154,15 @@ public final class NIOAsyncTestingEventLoop: EventLoop, @unchecked Sendable {
let promise: EventLoopPromise<T> = self.makePromise()
let taskID = self.scheduledTaskCounter.loadThenWrappingIncrement(ordering: .relaxed)

switch self.state {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The load here should be acquiring.

@@ -324,9 +334,11 @@ public final class NIOAsyncTestingEventLoop: EventLoop, @unchecked Sendable {

/// The concurrency-aware equivalent of `shutdownGracefully(queue:_:)`.
public func shutdownGracefully() async {
await withCheckedContinuation { (continuation: CheckedContinuation<Void, Never>) in
await withCheckedContinuation { continuation in
self._state.store(.closing, ordering: .relaxed)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These stores should be releasing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
patch-version-bump-only For PRs that when merged will only cause a bump of the patch version, ie. 1.0.x -> 1.0.(x+1)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants