Skip to content

Conversation

@normanmaurer
Copy link
Member

…also udate channel state before.

Motivation:

We not always ensure correct ordering which made it quite hard to reason about things. We should always first notify the promise before we call the fire* method that belongs to the event. Beside this we sometimes fired events or notified promised before correctly update the active state / addresses of a Channel which could result in unexpected results when query the Channel during execution of callbacks and handlers.

Modifications:

  • Ensure we always notify promise first
  • Always correctly update channel state before notify promise
  • Add test to verify notification order.

Result:

Correct ordering of events which makes things easier to reason about and which follows what netty is doing.

@normanmaurer normanmaurer requested review from Lukasa and weissi March 16, 2018 15:32
Copy link
Contributor

@Lukasa Lukasa left a comment

Choose a reason for hiding this comment

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

Cool, so this is basically pretty good! I'd like to see this test pulled out to its own file so you can declare the lifecycle handlers outside the test function, but otherwise this is basically good (plus notes).

try socket.close()
} catch {
promise?.fail(error: error)
return
Copy link
Contributor

Choose a reason for hiding this comment

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

Wait, why are we returning here? If we fail to close the socket we don't cancel the pending writes?

Copy link
Member Author

Choose a reason for hiding this comment

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

maybe we should still do ... Good question. I guess there is not much we can do in this case.

XCTAssertTrue(closePromise.futureResult.fulfilled, "closePromise not fullfilled before channelInactive was called")
} else {
XCTFail("close(...) not called before channelInactive")
}
Copy link
Contributor

Choose a reason for hiding this comment

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

We can reduce this duplicate code by writing a pair of helper functions:

func assertFulfilled(promise: EventLoopPromise<Void>?, promiseName: String, trigger: String, setter: String, file: String = #file, line: Uint = #line) {
        if let promise = promise {
            XCTAssertTrue(promise.futureResult.fulfilled, "\(promiseName) not fulfilled before \(trigger) was called", file: file, line: line)
        } else {
            XCTFail("\(setter) not called before \(trigger)", file: file, line: line
        }
    }

This would let us truncate this file substantially and better express the criteria of these assertions.

XCTAssertNil(self.connectPromise)
XCTAssertNil(self.closePromise)

promise?.futureResult.whenSuccess {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you actually accept this promise being nil?

Copy link
Member Author

Choose a reason for hiding this comment

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

nope it should not be null ever so I think we can just make it a force unwrap.

XCTAssertNil(self.connectPromise)
XCTAssertNil(self.closePromise)

promise?.futureResult.whenSuccess {
Copy link
Contributor

Choose a reason for hiding this comment

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

Or this one?

XCTAssertNotNil(self.connectPromise)
XCTAssertNil(self.closePromise)

promise?.futureResult.whenSuccess {
Copy link
Contributor

Choose a reason for hiding this comment

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

Or this one?

@normanmaurer normanmaurer force-pushed the event_notification_order branch 2 times, most recently from 87694f5 to a4fd3a1 Compare March 16, 2018 19:23
@normanmaurer
Copy link
Member Author

@Lukasa I think I addressed all of your comments (hopefully).

p = promise
} catch {
promise?.fail(error: error)
p = nil
Copy link
Contributor

Choose a reason for hiding this comment

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

This code cannot possibly be right. What's the intended behaviour here?

p = promise
} catch {
promise?.fail(error: error)
p = nil
Copy link
Member Author

Choose a reason for hiding this comment

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

ok let me explain what I wanted to do ... Basically because we fail the promise here I wanted to ensure we pass nil to becomeInactive0 so we not try to notify the promise again.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, ok. Please put a comment to that effect here.

Copy link
Member Author

Choose a reason for hiding this comment

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

done

…also udate channel state before.

Motivation:

We not always ensure correct ordering which made it quite hard to reason about things. We should always first notify the promise before we call the fire* method that belongs to the event. Beside this we sometimes fired events or notified promised before correctly update the active state / addresses of a Channel which could result in unexpected results when query the Channel during execution of callbacks and handlers.

Modifications:

- Ensure we always notify promise first
- Always correctly update channel state before notify promise
- Add test to verify notification order.

Result:

Correct ordering of events which makes things easier to reason about and which follows what netty is doing.
@normanmaurer normanmaurer force-pushed the event_notification_order branch from a4fd3a1 to f4811b7 Compare March 19, 2018 10:59
@Lukasa Lukasa added the 🔨 semver/patch No public API change. label Mar 19, 2018
@Lukasa Lukasa added this to the 1.3.0 milestone Mar 19, 2018
@Lukasa Lukasa merged commit edfbe50 into apple:master Mar 19, 2018
@normanmaurer normanmaurer deleted the event_notification_order branch April 23, 2018 12:09
weissi pushed a commit to weissi/swift-nio that referenced this pull request Feb 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔨 semver/patch No public API change.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants