Skip to content

Commit d85f88c

Browse files
authored
chore[websocket]: improve websocket factory start (#1145)
1 parent 22f478c commit d85f88c

File tree

7 files changed

+42
-9
lines changed

7 files changed

+42
-9
lines changed

hathor/builder/resources_builder.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,6 @@ def create_resources(self) -> server.Site:
297297
address_index=self.manager.tx_storage.indexes.addresses)
298298
if self._args.disable_ws_history_streaming:
299299
ws_factory.disable_history_streaming()
300-
ws_factory.start()
301300
root.putChild(b'ws', WebSocketResource(ws_factory))
302301

303302
if settings.CONSENSUS_ALGORITHM.is_pow():
@@ -322,8 +321,8 @@ def create_resources(self) -> server.Site:
322321
status_server = SiteProfiler(real_root)
323322
self.log.info('with status', listen=self._args.status, with_wallet_api=with_wallet_api)
324323

325-
# Set websocket factory in metrics
326-
self.manager.metrics.websocket_factory = ws_factory
324+
# Set websocket factory in metrics. It'll be started when the manager is started.
325+
self.manager.websocket_factory = ws_factory
327326

328327
self._built_status = True
329328
return status_server

hathor/builder/sysctl_builder.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def build(self) -> Sysctl:
3838
root.put_child('core', core)
3939
root.put_child('p2p', ConnectionsManagerSysctl(self.artifacts.p2p_manager))
4040

41-
ws_factory = self.artifacts.manager.metrics.websocket_factory
41+
ws_factory = self.artifacts.manager.websocket_factory
4242
if ws_factory is not None:
4343
root.put_child('ws', WebsocketManagerSysctl(ws_factory))
4444

hathor/cli/run_node.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,6 @@ def prepare(self, *, register_resources: bool = True) -> None:
198198

199199
self.tx_storage = self.manager.tx_storage
200200
self.wallet = self.manager.wallet
201-
self.start_manager()
202201

203202
if self._args.stratum:
204203
assert self.manager.stratum_factory is not None
@@ -219,6 +218,8 @@ def prepare(self, *, register_resources: bool = True) -> None:
219218
assert status_server is not None
220219
self.reactor.listenTCP(self._args.status, status_server)
221220

221+
self.start_manager()
222+
222223
from hathor.builder.builder import BuildArtifacts
223224
self.artifacts = BuildArtifacts(
224225
peer=self.manager.my_peer,

hathor/manager.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import time
1818
from cProfile import Profile
1919
from enum import Enum
20-
from typing import Iterator, NamedTuple, Optional, Union
20+
from typing import TYPE_CHECKING, Iterator, NamedTuple, Optional, Union
2121

2222
from hathorlib.base_transaction import tx_or_block_from_bytes as lib_tx_or_block_from_bytes
2323
from structlog import get_logger
@@ -65,6 +65,9 @@
6565
from hathor.vertex_handler import VertexHandler
6666
from hathor.wallet import BaseWallet
6767

68+
if TYPE_CHECKING:
69+
from hathor.websocket.factory import HathorAdminWebsocketFactory
70+
6871
logger = get_logger()
6972
cpu = get_cpu_profiler()
7073

@@ -117,6 +120,8 @@ def __init__(
117120
full_verification: bool = False,
118121
enable_event_queue: bool = False,
119122
poa_block_producer: PoaBlockProducer | None = None,
123+
# Websocket factory
124+
websocket_factory: Optional['HathorAdminWebsocketFactory'] = None
120125
) -> None:
121126
"""
122127
:param reactor: Twisted reactor which handles the mainloop and the events.
@@ -199,12 +204,15 @@ def __init__(
199204
self.vertex_handler = vertex_handler
200205
self.vertex_parser = vertex_parser
201206

207+
self.websocket_factory = websocket_factory
208+
202209
self.metrics = Metrics(
203210
pubsub=self.pubsub,
204211
avg_time_between_blocks=settings.AVG_TIME_BETWEEN_BLOCKS,
205212
connections=self.connections,
206213
tx_storage=self.tx_storage,
207214
reactor=self.reactor,
215+
websocket_factory=self.websocket_factory,
208216
)
209217

210218
self.wallet = wallet
@@ -322,6 +330,10 @@ def start(self) -> None:
322330
self.tx_storage.set_allow_scope(TxAllowScope.VALID)
323331
self.tx_storage.enable_lock()
324332

333+
# Preferably start before self.metrics
334+
if self.websocket_factory:
335+
self.websocket_factory.start()
336+
325337
# Metric starts to capture data
326338
self.metrics.start()
327339

@@ -360,6 +372,9 @@ def stop(self) -> Deferred:
360372
# Metric stops to capture data
361373
self.metrics.stop()
362374

375+
if self.websocket_factory:
376+
self.websocket_factory.stop()
377+
363378
if self.lc_check_sync_state.running:
364379
self.lc_check_sync_state.stop()
365380

hathor/metrics.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ def set_websocket_data(self) -> None:
217217
""" Set websocket metrics data. Connections and addresses subscribed.
218218
"""
219219
if self.websocket_factory:
220+
assert self.websocket_factory.is_running, 'Websocket factory has not been started'
221+
220222
self.websocket_connections = len(self.websocket_factory.connections)
221223
self.subscribed_addresses = len(self.websocket_factory.address_connections)
222224

tests/cli/test_run_node.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from unittest.mock import ANY, patch
2+
13
from hathor.cli.run_node import RunNode
24
from tests import unittest
35

@@ -15,3 +17,17 @@ def register_signal_handlers(self) -> None:
1517

1618
run_node = CustomRunNode(argv=['--memory-storage'])
1719
self.assertTrue(run_node is not None)
20+
21+
@patch('twisted.internet.reactor.listenTCP')
22+
def test_listen_tcp_ipv4(self, mock_listenTCP):
23+
class CustomRunNode(RunNode):
24+
def start_manager(self) -> None:
25+
pass
26+
27+
def register_signal_handlers(self) -> None:
28+
pass
29+
30+
run_node = CustomRunNode(argv=['--memory-storage', '--status', '1234'])
31+
self.assertTrue(run_node is not None)
32+
33+
mock_listenTCP.assert_called_with(1234, ANY)

tests/cli/test_sysctl_init.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def test_sysctl_builder_fail_with_invalid_property(self):
3939
# prepare to register only p2p commands
4040
artifacts = Mock(**{
4141
'p2p_manager': Mock(),
42-
'manager.metrics.websocket_factory.return_value': None
42+
'manager.websocket_factory.return_value': None
4343
})
4444

4545
with self.assertRaises(SysctlEntryNotFound) as context:
@@ -68,7 +68,7 @@ def test_sysctl_builder_fail_with_invalid_value(self):
6868
# prepare to register only p2p commands
6969
artifacts = Mock(**{
7070
'p2p_manager': Mock(),
71-
'manager.metrics.websocket_factory.return_value': None
71+
'manager.websocket_factory.return_value': None
7272
})
7373

7474
with self.assertRaises(SysctlRunnerException) as context:
@@ -85,7 +85,7 @@ def test_syctl_init_file_fail_with_empty_or_invalid_file(self):
8585
# prepare to register only p2p commands
8686
artifacts = Mock(**{
8787
'p2p_manager': Mock(),
88-
'manager.metrics.websocket_factory.return_value': None
88+
'manager.websocket_factory.return_value': None
8989
})
9090

9191
with self.assertRaises(AssertionError):

0 commit comments

Comments
 (0)