Skip to content

Commit 76174f6

Browse files
committed
Support http2 keep-alive
Signed-off-by: Sahas Subramanian <[email protected]>
1 parent 93cd8df commit 76174f6

File tree

2 files changed

+33
-3
lines changed

2 files changed

+33
-3
lines changed

src/frequenz/client/base/channel.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,16 @@ class ChannelOptions:
5151
ssl: SslOptions = SslOptions()
5252
"""SSL options for the channel."""
5353

54+
keep_alive_time_ms: int | None = None
55+
"""The time in milliseconds between HTTP2 keep-alive pings.
56+
57+
If None, keep-alive is disabled."""
58+
59+
keep_alive_timeout_ms: int = 20_000
60+
"""The time in milliseconds to wait for a HTTP2 keep-alive response.
61+
62+
This is only used if `keep_alive_time_ms` is not None."""
63+
5464

5565
def parse_grpc_uri(
5666
uri: str,
@@ -120,6 +130,15 @@ def parse_grpc_uri(
120130
parsed_uri.netloc if parsed_uri.port else f"{parsed_uri.netloc}:{defaults.port}"
121131
)
122132

133+
channel_options = (
134+
[
135+
("grpc.keepalive_time_ms", defaults.keep_alive_time_ms),
136+
("grpc.keepalive_timeout_ms", defaults.keep_alive_timeout_ms),
137+
]
138+
if defaults.keep_alive_time_ms is not None
139+
else None
140+
)
141+
123142
ssl = defaults.ssl.enabled if options.ssl is None else options.ssl
124143
if ssl:
125144
return secure_channel(
@@ -141,8 +160,9 @@ def parse_grpc_uri(
141160
defaults.ssl.certificate_chain,
142161
),
143162
),
163+
channel_options,
144164
)
145-
return insecure_channel(target)
165+
return insecure_channel(target, channel_options)
146166

147167

148168
def _to_bool(value: str) -> bool:

tests/test_channel.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,14 @@ def test_parse_uri_ok( # pylint: disable=too-many-locals
198198

199199
assert channel == expected_channel
200200
expected_target = f"{expected_host}:{expected_port}"
201+
expected_channel_options = (
202+
[
203+
("grpc.keepalive_time_ms", defaults.keep_alive_time_ms),
204+
("grpc.keepalive_timeout_ms", defaults.keep_alive_timeout_ms),
205+
]
206+
if defaults.keep_alive_time_ms is not None
207+
else None
208+
)
201209
if expected_ssl:
202210
if isinstance(expected_root_certificates, pathlib.Path):
203211
get_contents_mock.assert_any_call(
@@ -223,10 +231,12 @@ def test_parse_uri_ok( # pylint: disable=too-many-locals
223231
certificate_chain=expected_certificate_chain,
224232
)
225233
secure_channel_mock.assert_called_once_with(
226-
expected_target, expected_credentials
234+
expected_target, expected_credentials, expected_channel_options
227235
)
228236
else:
229-
insecure_channel_mock.assert_called_once_with(expected_target)
237+
insecure_channel_mock.assert_called_once_with(
238+
expected_target, expected_channel_options
239+
)
230240

231241

232242
@pytest.mark.parametrize("value", ["true", "on", "1", "TrUe", "On", "ON", "TRUE"])

0 commit comments

Comments
 (0)