Skip to content

Commit f21d54a

Browse files
committed
Resolve the discovery service and use it as the base URL for the refresh component
- Use the resolved URL when initializing the refresh component - Perform the resolution in PanelClient and expose it as a property Signed-off-by: Joe Friedrichsen <[email protected]>
1 parent 098c4b2 commit f21d54a

File tree

5 files changed

+68
-28
lines changed

5 files changed

+68
-28
lines changed

src/nipanel/_panel_client.py

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
SetValueRequest,
1616
)
1717
from ni.pythonpanel.v1.python_panel_service_pb2_grpc import PythonPanelServiceStub
18-
from ni_measurement_plugin_sdk_service.discovery import DiscoveryClient
18+
from ni_measurement_plugin_sdk_service.discovery import DiscoveryClient, ServiceLocation
1919
from ni_measurement_plugin_sdk_service.grpc.channelpool import GrpcChannelPool
2020
from typing_extensions import ParamSpec
2121

@@ -57,8 +57,14 @@ def __init__(
5757
self._discovery_client = discovery_client
5858
self._grpc_channel_pool = grpc_channel_pool
5959
self._grpc_channel = grpc_channel
60+
self._proxy_location: ServiceLocation | None = None
6061
self._stub: PythonPanelServiceStub | None = None
6162

63+
@property
64+
def proxy_location(self) -> ServiceLocation:
65+
"""Return the ServiceLocation for the panel's proxy."""
66+
return self._get_proxy_location()
67+
6268
def start_panel(self, panel_id: str, panel_script_path: str, python_path: str) -> str:
6369
"""Start the panel.
6470
@@ -134,29 +140,61 @@ def get_value(self, panel_id: str, value_id: str) -> tuple[bool, object]:
134140
else:
135141
return False, None
136142

143+
def _get_proxy_location(self) -> ServiceLocation:
144+
if self._proxy_location is None:
145+
self._proxy_location = self._resolve_discovery_service()
146+
return self._proxy_location
147+
137148
def _get_stub(self) -> PythonPanelServiceStub:
138149
if self._stub is None:
139150
if self._grpc_channel is not None:
140151
self._stub = PythonPanelServiceStub(self._grpc_channel)
141152
else:
142-
with self._initialization_lock:
143-
if self._grpc_channel_pool is None:
144-
_logger.debug("Creating unshared GrpcChannelPool.")
145-
self._grpc_channel_pool = GrpcChannelPool()
146-
if self._discovery_client is None:
147-
_logger.debug("Creating unshared DiscoveryClient.")
148-
self._discovery_client = DiscoveryClient(
149-
grpc_channel_pool=self._grpc_channel_pool
150-
)
151-
152-
service_location = self._discovery_client.resolve_service(
153-
provided_interface=self._provided_interface,
154-
service_class=self._service_class,
155-
)
156-
channel = self._grpc_channel_pool.get_channel(service_location.insecure_address)
157-
self._stub = PythonPanelServiceStub(channel)
153+
channel = self._get_panel_service_channel()
154+
self._stub = PythonPanelServiceStub(channel)
158155
return self._stub
159156

157+
def _get_grpc_channel_pool(self) -> GrpcChannelPool:
158+
if self._grpc_channel_pool is None:
159+
_logger.debug("Creating unshared GrpcChannelPool.")
160+
self._grpc_channel_pool = GrpcChannelPool()
161+
return self._grpc_channel_pool
162+
163+
def _get_discovery_client(self, channel_pool: GrpcChannelPool) -> DiscoveryClient:
164+
if self._discovery_client is None:
165+
_logger.debug("Creating unshared DiscoveryClient.")
166+
self._discovery_client = DiscoveryClient(grpc_channel_pool=channel_pool)
167+
return self._discovery_client
168+
169+
def _resolve_service(
170+
self, discovery_client: DiscoveryClient, provided_interface: str, service_class: str = ""
171+
) -> ServiceLocation:
172+
_logger.debug("Resolving '%s'.", provided_interface)
173+
service_location = discovery_client.resolve_service(
174+
provided_interface=provided_interface,
175+
service_class=service_class,
176+
)
177+
return service_location
178+
179+
def _get_panel_service_channel(self) -> grpc.Channel:
180+
with self._initialization_lock:
181+
grpc_channel_pool = self._get_grpc_channel_pool()
182+
discovery_client = self._get_discovery_client(grpc_channel_pool)
183+
panel_location = self._resolve_service(
184+
discovery_client, self._provided_interface, self._service_class
185+
)
186+
channel = grpc_channel_pool.get_channel(panel_location.insecure_address)
187+
return channel
188+
189+
def _resolve_discovery_service(self) -> ServiceLocation:
190+
with self._initialization_lock:
191+
grpc_channel_pool = self._get_grpc_channel_pool()
192+
discovery_client = self._get_discovery_client(grpc_channel_pool)
193+
discovery_location = self._resolve_service(
194+
discovery_client, provided_interface="ni.http1.proxy"
195+
)
196+
return discovery_location
197+
160198
def _invoke_with_retry(
161199
self, method: Callable[_P, _T], *args: _P.args, **kwargs: _P.kwargs
162200
) -> _T:

src/nipanel/_panel_value_accessor.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from typing import TypeVar, overload
77

88
import grpc
9-
from ni_measurement_plugin_sdk_service.discovery import DiscoveryClient
9+
from ni_measurement_plugin_sdk_service.discovery import DiscoveryClient, ServiceLocation
1010
from ni_measurement_plugin_sdk_service.grpc.channelpool import GrpcChannelPool
1111

1212
from nipanel._panel_client import PanelClient
@@ -55,6 +55,11 @@ def panel_id(self) -> str:
5555
"""Read-only accessor for the panel ID."""
5656
return self._panel_id
5757

58+
@property
59+
def proxy_location(self) -> ServiceLocation:
60+
"""Read-only accessor for the panel's proxy location."""
61+
return self._panel_client.proxy_location
62+
5863
@overload
5964
def get_value(self, value_id: str) -> object: ...
6065

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
11
STREAMLIT_PYTHON_PANEL_SERVICE = "ni.pythonpanel.v1.PythonPanelService"
2-
STREAMLIT_REFRESH_COMPONENT_URL = "http://localhost:42001/panel-service/refresh"

src/nipanel/_streamlit_panel_initializer.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ def get_panel_accessor() -> StreamlitPanelValueAccessor:
6363

6464
panel = cast(StreamlitPanelValueAccessor, st.session_state[PANEL_ACCESSOR_KEY])
6565
_sync_session_state(panel)
66-
refresh_component = initialize_refresh_component(panel.panel_id)
66+
proxy_url = panel.proxy_location.insecure_address
67+
refresh_component = initialize_refresh_component(proxy_url, panel.panel_id)
6768
refresh_component()
6869
return panel
6970

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
"""Initializes a refresh component for Streamlit."""
22

3-
from typing import Any
3+
from streamlit.components.v1 import declare_component
4+
from streamlit.components.v1.custom_component import CustomComponent
45

5-
import streamlit.components.v1 as components
66

7-
from nipanel._streamlit_constants import STREAMLIT_REFRESH_COMPONENT_URL
8-
9-
10-
def initialize_refresh_component(panel_id: str) -> Any:
7+
def initialize_refresh_component(proxy_url: str, panel_id: str) -> CustomComponent:
118
"""Initialize a refresh component to the Streamlit app."""
12-
_refresh_component_func = components.declare_component(
9+
_refresh_component_func = declare_component(
1310
"panelRefreshComponent",
14-
url=f"{STREAMLIT_REFRESH_COMPONENT_URL}/{panel_id}",
11+
url=f"http://{proxy_url}/panel-service/refresh/{panel_id}",
1512
)
1613

1714
return _refresh_component_func

0 commit comments

Comments
 (0)