-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ability to manually shut down channels (#384)
* Add ability to manually shut down channels Addresses grpc/grpc-swift#198. It's currently not possible to manually shut down a gRPC channel, which means that the only way to shut down a channel is to deallocate it. This requirement is a bit fragile for cases where a consumer wants to manually shut down a channel, since it requires confidence that nothing else is holding a strong reference to the channel. This PR: - Adds a `shutdown` function to `Channel`, allowing consumers to arbitrarily shut down connections - Cancels all existing calls that are using the channel upon shutdown - Validates that existing calls will throw errors when attempting to read/write from a previously shut down channel - Ensures creating new calls using previously shut down channels will result in the initializer throwing (already handled by code generators) This change is increasingly relevant because consumers will need to shut down channels and restart them to help mitigate issues when switching between wifi/cellular as mentioned here: grpc/grpc-swift#337. * CR * try! -> try * support linux * CR
- Loading branch information
Showing
7 changed files
with
204 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/* | ||
* Copyright 2018, gRPC Authors All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
@testable import SwiftGRPC | ||
import XCTest | ||
|
||
final class ChannelShutdownTests: BasicEchoTestCase { | ||
static var allTests: [(String, (ChannelShutdownTests) -> () throws -> Void)] { | ||
return [ | ||
("testThrowsWhenCreatingCallWithAlreadyShutDownChannel", testThrowsWhenCreatingCallWithAlreadyShutDownChannel), | ||
("testCallReceiveThrowsWhenChannelIsShutDown", testCallReceiveThrowsWhenChannelIsShutDown), | ||
("testCallCloseThrowsWhenChannelIsShutDown", testCallCloseThrowsWhenChannelIsShutDown), | ||
("testCallCloseAndReceiveThrowsWhenChannelIsShutDown", testCallCloseAndReceiveThrowsWhenChannelIsShutDown), | ||
("testCallSendThrowsWhenChannelIsShutDown", testCallSendThrowsWhenChannelIsShutDown), | ||
("testCancelsActiveCallWhenShutdownIsCalled", testCancelsActiveCallWhenShutdownIsCalled), | ||
] | ||
} | ||
} | ||
|
||
extension ChannelShutdownTests { | ||
func testThrowsWhenCreatingCallWithAlreadyShutDownChannel() { | ||
self.client.channel.shutdown() | ||
|
||
XCTAssertThrowsError(try self.client.channel.makeCall("foobar")) { error in | ||
XCTAssertEqual(.alreadyShutdown, error as? Channel.Error) | ||
} | ||
} | ||
|
||
func testCallReceiveThrowsWhenChannelIsShutDown() { | ||
let call = try! self.client.channel.makeCall("foo") | ||
self.client.channel.shutdown() | ||
|
||
XCTAssertThrowsError(try call.receiveMessage { _ in }) { error in | ||
XCTAssertEqual(.completionQueueShutdown, error as? CallError) | ||
} | ||
} | ||
|
||
func testCallCloseThrowsWhenChannelIsShutDown() { | ||
let call = try! self.client.channel.makeCall("foo") | ||
self.client.channel.shutdown() | ||
|
||
XCTAssertThrowsError(try call.close()) { error in | ||
XCTAssertEqual(.completionQueueShutdown, error as? CallError) | ||
} | ||
} | ||
|
||
func testCallCloseAndReceiveThrowsWhenChannelIsShutDown() { | ||
let call = try! self.client.channel.makeCall("foo") | ||
self.client.channel.shutdown() | ||
|
||
XCTAssertThrowsError(try call.closeAndReceiveMessage { _ in }) { error in | ||
XCTAssertEqual(.completionQueueShutdown, error as? CallError) | ||
} | ||
} | ||
|
||
func testCallSendThrowsWhenChannelIsShutDown() { | ||
let call = try! self.client.channel.makeCall("foo") | ||
self.client.channel.shutdown() | ||
|
||
XCTAssertThrowsError(try call.sendMessage(data: Data())) { error in | ||
XCTAssertEqual(.completionQueueShutdown, error as? CallError) | ||
} | ||
} | ||
|
||
func testCancelsActiveCallWhenShutdownIsCalled() { | ||
let errorExpectation = self.expectation(description: "error is returned to call when channel is shut down") | ||
let call = try! self.client.channel.makeCall("foo") | ||
|
||
try! call.receiveMessage { result in | ||
XCTAssertFalse(result.success) | ||
errorExpectation.fulfill() | ||
} | ||
|
||
self.client.channel.shutdown() | ||
self.waitForExpectations(timeout: 0.1) | ||
|
||
XCTAssertThrowsError(try call.close()) { error in | ||
XCTAssertEqual(.completionQueueShutdown, error as? CallError) | ||
} | ||
} | ||
} |
Oops, something went wrong.