Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring of the TriblerNetworkRequest #7205

Merged
merged 15 commits into from
Jan 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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