Skip to content

Commit

Permalink
Merge pull request #7205 from drew2a/refactoring/network_request
Browse files Browse the repository at this point in the history
Refactoring of the `TriblerNetworkRequest`
  • Loading branch information
drew2a authored Jan 31, 2023
2 parents 87916f7 + 7bcf112 commit cf5d52b
Show file tree
Hide file tree
Showing 30 changed files with 780 additions and 698 deletions.
19 changes: 19 additions & 0 deletions src/tribler/core/utilities/limited_ordered_dict.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from collections import OrderedDict


class LimitedOrderedDict(OrderedDict):
""" This class is an implementation of OrderedDict with size limit.
If the size of the dict exceeds the limit, the oldest entries will be deleted.
"""
def __init__(self, *args, limit: int = 200, **kwargs):
self.limit = limit
super().__init__(*args, **kwargs)

def __setitem__(self, key, value):
super().__setitem__(key, value)
self._adjust_size()

def _adjust_size(self):
while len(self) > self.limit:
self.popitem(last=False)
27 changes: 27 additions & 0 deletions src/tribler/core/utilities/tests/test_limited_ordered_dict.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from tribler.core.utilities.limited_ordered_dict import LimitedOrderedDict


def test_order():
d = LimitedOrderedDict()
d['first'] = '1'
d['second'] = '2'
d['third'] = '3'

assert list(d.keys()) == ['first', 'second', 'third']


def test_limit():
d = LimitedOrderedDict(limit=2)
d['first'] = '1'
d['second'] = '2'
d['third'] = '3'

assert list(d.keys()) == ['second', 'third']


def test_merge():
d1 = {'first': 1, 'second': 2}
d2 = {'third': 3, 'fourth': 4}

d = LimitedOrderedDict({**d1, **d2}, limit=2)
assert len(d) == 2
7 changes: 5 additions & 2 deletions src/tribler/gui/core_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@
from typing import Optional

from PyQt5.QtCore import QObject, QProcess, QProcessEnvironment, QTimer
from PyQt5.QtNetwork import QNetworkRequest

from tribler.core.utilities.process_manager import ProcessManager
from tribler.gui import gui_sentry_reporter
from tribler.gui.app_manager import AppManager
from tribler.gui.event_request_manager import EventRequestManager
from tribler.gui.exceptions import CoreConnectTimeoutError, CoreCrashedError
from tribler.gui.tribler_request_manager import ShutdownRequest, request_manager
from tribler.gui.network.request_manager import request_manager
from tribler.gui.utilities import connect


Expand Down Expand Up @@ -237,7 +238,9 @@ def send_shutdown_request(initial=False):
else:
self._logger.warning("Re-sending shutdown request to Tribler Core")

ShutdownRequest(shutdown_request_processed, on_cancel=send_shutdown_request)
request = request_manager.put("shutdown", shutdown_request_processed,
priority=QNetworkRequest.HighPriority)
request.cancellable = False

send_shutdown_request(initial=True)

Expand Down
83 changes: 43 additions & 40 deletions src/tribler/gui/debug_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
from tribler.gui.defs import DEBUG_PANE_REFRESH_TIMEOUT, GB, MB
from tribler.gui.dialogs.confirmationdialog import ConfirmationDialog
from tribler.gui.event_request_manager import received_events as tribler_received_events
from tribler.gui.network.request import Request
from tribler.gui.network.request_manager import request_manager
from tribler.gui.resource_monitor import GuiResourceMonitor
from tribler.gui.tribler_request_manager import TriblerNetworkRequest, performed_requests as tribler_performed_requests
from tribler.gui.utilities import connect, format_size, get_ui_file_path
from tribler.gui.widgets.graphs.timeseriesplot import TimeSeriesPlot
from tribler.gui.widgets.ipv8health import MonitorWidget
Expand Down Expand Up @@ -144,9 +145,7 @@ def hideEvent(self, hide_event):
def showEvent(self, show_event):
if self.ipv8_health_widget and self.ipv8_health_widget.isVisible():
self.ipv8_health_widget.resume()
TriblerNetworkRequest(
"ipv8/asyncio/drift", self.on_ipv8_health_enabled, data={"enable": True}, method='PUT'
)
request_manager.put("ipv8/asyncio/drift", self.on_ipv8_health_enabled, data={"enable": True})

def run_with_timer(self, call_fn, timeout=DEBUG_PANE_REFRESH_TIMEOUT):
call_fn()
Expand Down Expand Up @@ -252,7 +251,7 @@ def create_and_add_widget_item(self, key, value, widget):
widget.addTopLevelItem(item)

def load_general_tab(self):
TriblerNetworkRequest("statistics/tribler", self.on_tribler_statistics)
request_manager.get("statistics/tribler", self.on_tribler_statistics)

def on_tribler_statistics(self, data):
if not data:
Expand Down Expand Up @@ -320,23 +319,24 @@ def show_gui_settings(self):

def load_requests_tab(self):
self.window().requests_tree_widget.clear()
for request, status_code in sorted(tribler_performed_requests, key=lambda rq: rq[0].time):
endpoint = request.url
for request in request_manager.performed_requests:
endpoint = request.endpoint
method = request.method
data = request.raw_data
data = request.data
timestamp = request.time
status_code = request.status_code

item = QTreeWidgetItem(self.window().requests_tree_widget)
item.setText(0, f"{method} {repr(endpoint)} {repr(data)}")
item.setText(1, ("%d" % status_code) if status_code else "unknown")
item.setText(1, str(status_code or "unknown"))
item.setText(2, f"{strftime('%H:%M:%S', localtime(timestamp))}")
self.window().requests_tree_widget.addTopLevelItem(item)

def load_bandwidth_accounting_tab(self) -> None:
"""
Initiate a request to the Tribler core to fetch statistics on bandwidth accounting.
"""
TriblerNetworkRequest("bandwidth/statistics", self.on_bandwidth_statistics)
request_manager.get("bandwidth/statistics", self.on_bandwidth_statistics)

def on_bandwidth_statistics(self, data: Dict) -> None:
"""
Expand All @@ -350,7 +350,7 @@ def on_bandwidth_statistics(self, data: Dict) -> None:
self.create_and_add_widget_item(key, value, self.window().bandwidth_tree_widget)

def load_ipv8_general_tab(self):
TriblerNetworkRequest("statistics/ipv8", self.on_ipv8_general_stats)
request_manager.get("statistics/ipv8", self.on_ipv8_general_stats)

def on_ipv8_general_stats(self, data):
if not data:
Expand All @@ -364,7 +364,7 @@ def on_ipv8_general_stats(self, data):
self.create_and_add_widget_item(key, value, self.window().ipv8_general_tree_widget)

def load_ipv8_communities_tab(self):
TriblerNetworkRequest("ipv8/overlays", self.on_ipv8_community_stats)
request_manager.get("ipv8/overlays", self.on_ipv8_community_stats)

def _colored_peer_count(self, peer_count, max_peers):
limits = [20, max_peers + 1]
Expand Down Expand Up @@ -440,7 +440,7 @@ def update_community_peers(self, item):
def load_ipv8_community_details_tab(self):
if self.ipv8_statistics_enabled:
self.window().ipv8_statistics_error_label.setHidden(True)
TriblerNetworkRequest("ipv8/overlays/statistics", self.on_ipv8_community_detail_stats)
request_manager.get("ipv8/overlays/statistics", self.on_ipv8_community_detail_stats)
else:
self.window().ipv8_statistics_error_label.setHidden(False)
self.window().ipv8_communities_details_widget.setHidden(True)
Expand Down Expand Up @@ -489,7 +489,7 @@ def load_ipv8_health_monitor(self):
# We already loaded the widget, just resume it.
self.ipv8_health_widget.resume()
# Whether the widget is newly loaded or not, start the measurements.
TriblerNetworkRequest("ipv8/asyncio/drift", self.on_ipv8_health_enabled, data={"enable": True}, method='PUT')
request_manager.put("ipv8/asyncio/drift", self.on_ipv8_health_enabled, data={"enable": True})

def hide_ipv8_health_widget(self):
"""
Expand All @@ -500,7 +500,7 @@ def hide_ipv8_health_widget(self):
"""
if self.ipv8_health_widget is not None and not self.ipv8_health_widget.is_paused:
self.ipv8_health_widget.pause()
TriblerNetworkRequest("ipv8/asyncio/drift", lambda _: None, data={"enable": False}, method='PUT')
request_manager.put("ipv8/asyncio/drift", data={"enable": False})

def on_ipv8_health(self, data):
"""
Expand All @@ -518,7 +518,11 @@ def on_ipv8_health_enabled(self, data):
"""
if not data:
return
self.run_with_timer(lambda: TriblerNetworkRequest("ipv8/asyncio/drift", self.on_ipv8_health), 100)

def send_request():
request_manager.get("ipv8/asyncio/drift", self.on_ipv8_health)

self.run_with_timer(send_request, 100)

def add_items_to_tree(self, tree, items, keys):
tree.clear()
Expand All @@ -536,7 +540,7 @@ def add_items_to_tree(self, tree, items, keys):

def load_tunnel_circuits_tab(self):
self.window().circuits_tree_widget.setColumnWidth(3, 200)
TriblerNetworkRequest("ipv8/tunnel/circuits", self.on_tunnel_circuits)
request_manager.get("ipv8/tunnel/circuits", self.on_tunnel_circuits)

def on_tunnel_circuits(self, circuits):
if not circuits:
Expand All @@ -553,7 +557,7 @@ def on_tunnel_circuits(self, circuits):
)

def load_tunnel_relays_tab(self):
TriblerNetworkRequest("ipv8/tunnel/relays", self.on_tunnel_relays)
request_manager.get("ipv8/tunnel/relays", self.on_tunnel_relays)

def on_tunnel_relays(self, data):
if data:
Expand All @@ -564,7 +568,7 @@ def on_tunnel_relays(self, data):
)

def load_tunnel_exits_tab(self):
TriblerNetworkRequest("ipv8/tunnel/exits", self.on_tunnel_exits)
request_manager.get("ipv8/tunnel/exits", self.on_tunnel_exits)

def on_tunnel_exits(self, data):
if data:
Expand All @@ -575,7 +579,7 @@ def on_tunnel_exits(self, data):
)

def load_tunnel_swarms_tab(self):
TriblerNetworkRequest("ipv8/tunnel/swarms", self.on_tunnel_swarms)
request_manager.get("ipv8/tunnel/swarms", self.on_tunnel_swarms)

def on_tunnel_swarms(self, data):
if data:
Expand All @@ -596,7 +600,7 @@ def on_tunnel_swarms(self, data):

def load_tunnel_peers_tab(self):
self.window().peers_tree_widget.setColumnWidth(2, 300)
TriblerNetworkRequest("ipv8/tunnel/peers", self.on_tunnel_peers)
request_manager.get("ipv8/tunnel/peers", self.on_tunnel_peers)

def on_tunnel_peers(self, data):
if data:
Expand All @@ -605,7 +609,7 @@ def on_tunnel_peers(self, data):
)

def load_dht_statistics_tab(self):
TriblerNetworkRequest("ipv8/dht/statistics", self.on_dht_statistics)
request_manager.get("ipv8/dht/statistics", self.on_dht_statistics)

def on_dht_statistics(self, data):
if not data:
Expand All @@ -615,7 +619,7 @@ def on_dht_statistics(self, data):
self.create_and_add_widget_item(key, value, self.window().dhtstats_tree_widget)

def load_dht_buckets_tab(self):
TriblerNetworkRequest("ipv8/dht/buckets", self.on_dht_buckets)
request_manager.get("ipv8/dht/buckets", self.on_dht_buckets)

def on_dht_buckets(self, data):
if data:
Expand Down Expand Up @@ -661,7 +665,7 @@ def load_open_files_tab(self):
except psutil.AccessDenied as exc:
gui_item.setText(0, f"Unable to get open files for GUI ({exc})")

TriblerNetworkRequest("debug/open_files", self.on_core_open_files)
request_manager.get("debug/open_files", self.on_core_open_files)

def on_core_open_files(self, data):
if not data:
Expand All @@ -677,7 +681,7 @@ def on_core_open_files(self, data):
core_item.addChild(item)

def load_open_sockets_tab(self):
TriblerNetworkRequest("debug/open_sockets", self.on_core_open_sockets)
request_manager.get("debug/open_sockets", self.on_core_open_sockets)

def on_core_open_sockets(self, data):
if not data:
Expand All @@ -703,7 +707,7 @@ def on_core_open_sockets(self, data):
self.window().open_sockets_tree_widget.addTopLevelItem(item)

def load_threads_tab(self):
TriblerNetworkRequest("debug/threads", self.on_core_threads)
request_manager.get("debug/threads", self.on_core_threads)

def on_core_threads(self, data):
if not data:
Expand Down Expand Up @@ -741,7 +745,7 @@ def load_cpu_tab(self):
def refresh_cpu_plot(self):
# To update the core CPU graph, call Debug REST API to get the history
# and update the CPU graph after receiving the response.
TriblerNetworkRequest("debug/cpu/history", self.on_core_cpu_history)
request_manager.get("debug/cpu/history", self.on_core_cpu_history)

# GUI CPU graph can be simply updated using the data from GuiResourceMonitor object.
self._update_cpu_graph(self.gui_cpu_plot, self.resource_monitor.get_cpu_history_dict())
Expand Down Expand Up @@ -779,7 +783,7 @@ def load_memory_tab(self):

def load_profiler_tab(self):
self.window().toggle_profiler_button.setEnabled(False)
TriblerNetworkRequest("debug/profiler", self.on_profiler_info)
request_manager.get("debug/profiler", self.on_profiler_info)

def on_profiler_info(self, data):
if not data:
Expand All @@ -795,7 +799,8 @@ def on_toggle_profiler_button_clicked(self, checked=False):
self.toggling_profiler = True
self.window().toggle_profiler_button.setEnabled(False)
method = "DELETE" if self.profiler_enabled else "PUT"
TriblerNetworkRequest("debug/profiler", self.on_profiler_state_changed, method=method)
request = Request("debug/profiler", self.on_profiler_state_changed, method=method)
request_manager.add(request)

def on_profiler_state_changed(self, data):
if not data:
Expand All @@ -812,7 +817,7 @@ def on_profiler_state_changed(self, data):
def refresh_memory_plot(self):
# To update the core memory graph, call Debug REST API to get the history
# and update the memory graph after receiving the response.
TriblerNetworkRequest("debug/memory/history", self.on_core_memory_history)
request_manager.get("debug/memory/history", self.on_core_memory_history)

# GUI memory graph can be simply updated using the data from GuiResourceMonitor object.
self._update_memory_graph(self.gui_memory_plot, self.resource_monitor.get_memory_history_dict())
Expand All @@ -831,7 +836,7 @@ def _update_memory_graph(self, memory_graph, history_data):

def closeEvent(self, close_event):
if self.rest_request:
self.rest_request.cancel_request()
self.rest_request.cancel()
if self.cpu_plot_timer:
self.cpu_plot_timer.stop()

Expand All @@ -845,8 +850,8 @@ def load_logs_tab(self):
tab_index = self.window().log_tab_widget.currentIndex()
tab_name = "core" if tab_index == 0 else "gui"

params = {'process': tab_name, 'max_lines': max_log_lines}
TriblerNetworkRequest(f"debug/log", url_params=params, reply_callback=self.display_logs)
request_manager.get("debug/log", self.display_logs,
url_params={'process': tab_name, 'max_lines': max_log_lines})

def display_logs(self, data):
if not data:
Expand Down Expand Up @@ -899,9 +904,8 @@ def load_libtorrent_data(self, export=False):
self.load_libtorrent_sessions_tab(hop, export=export)

def load_libtorrent_settings_tab(self, hop, export=False):
TriblerNetworkRequest(
"libtorrent/settings?hop=%d" % hop, lambda data: self.on_libtorrent_settings_received(data, export=export)
)
request_manager.get(endpoint=f"libtorrent/settings?hop={hop}",
on_finish=lambda data: self.on_libtorrent_settings_received(data, export=export))
self.window().libtorrent_settings_tree_widget.clear()

def on_libtorrent_settings_received(self, data, export=False):
Expand All @@ -916,9 +920,8 @@ def on_libtorrent_settings_received(self, data, export=False):
self.save_to_file("libtorrent_settings.json", data)

def load_libtorrent_sessions_tab(self, hop, export=False):
TriblerNetworkRequest(
"libtorrent/session?hop=%d" % hop, lambda data: self.on_libtorrent_session_received(data, export=export)
)
request_manager.get(endpoint=f"libtorrent/session?hop={hop}",
on_finish=lambda data: self.on_libtorrent_session_received(data, export=export))
self.window().libtorrent_session_tree_widget.clear()

def on_libtorrent_session_received(self, data, export=False):
Expand Down Expand Up @@ -962,7 +965,7 @@ def on_channels_peers(self, data):
widget.addTopLevelItem(channel_item)

def load_channels_peers_tab(self):
TriblerNetworkRequest("remote_query/channels_peers", self.on_channels_peers)
request_manager.get("remote_query/channels_peers", self.on_channels_peers)

def channels_tab_changed(self, index):
if index == 0:
Expand Down
Loading

0 comments on commit cf5d52b

Please sign in to comment.