Skip to content

[fix] Real time updates on visualizer view#257

Merged
nemesifier merged 15 commits intomasterfrom
bug/visualizer-view-realtime-updates
Aug 4, 2025
Merged

[fix] Real time updates on visualizer view#257
nemesifier merged 15 commits intomasterfrom
bug/visualizer-view-realtime-updates

Conversation

@Dhanus3133
Copy link
Copy Markdown
Member

Closes #250 #251

Copy link
Copy Markdown
Member

@nemesifier nemesifier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably you need to modify the CI or test requirements to install the channels branch which has the patch for the live server?

Comment thread tests/openwisp2/settings.py Outdated
"ENGINE": "openwisp_utils.db.backends.spatialite",
"NAME": os.path.join(BASE_DIR, "openwisp_network_topology.db"),
"TEST": {
"NAME": os.path.join(BASE_DIR, "test_openwisp_network_topology.db"),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really needed?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, ChannelLiveServerTestCase can't run with an in-memory database.

@Dhanus3133
Copy link
Copy Markdown
Member Author

When running tests in parallel with Django versions < 5, I encounter an error due to ChannelLiveServerTestCase:

ERROR: test_real_time_link_status_update (openwisp_network_topology.tests.test_realtime.TestRealTime)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/opt/hostedtoolcache/Python/3.10.18/x64/lib/python3.10/site-packages/django/test/testcases.py", line 407, in _setup_and_call
    self._pre_setup()
  File "/opt/hostedtoolcache/Python/3.10.18/x64/lib/python3.10/site-packages/channels/testing/live.py", line 61, in _pre_setup
    self._server_process.start()
  File "/opt/hostedtoolcache/Python/3.10.18/x64/lib/python3.10/multiprocessing/process.py", line 118, in start
    assert not _current_process._config.get('daemon'), \
AssertionError: daemonic processes are not allowed to have children

https://github.com/openwisp/openwisp-network-topology/actions/runs/16502989458/job/46666342034?pr=257#step:10:83

@nemesifier nemesifier force-pushed the bug/visualizer-view-realtime-updates branch from da4f489 to 425b480 Compare July 30, 2025 15:34
Copy link
Copy Markdown
Member

@nemesifier nemesifier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're almost there with this one.

The following test is too flaky in my environment:

[Retry] Retrying "openwisp_network_topology.tests.test_realtime.TestRealTime.test_node_link_update", attempt 1/5. 
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
[Retry] Retrying "openwisp_network_topology.tests.test_realtime.TestRealTime.test_node_link_update", attempt 2/5. 
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
[Retry] Retrying "openwisp_network_topology.tests.test_realtime.TestRealTime.test_node_link_update", attempt 3/5. 
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
[Retry] Retrying "openwisp_network_topology.tests.test_realtime.TestRealTime.test_node_link_update", attempt 4/5. 
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
[Retry] Retrying "openwisp_network_topology.tests.test_realtime.TestRealTime.test_node_link_update", attempt 5/5. 
--------------------------------------------------------------------------------

I disabled the retry logic in opernwisp-utils to see the stacktrace:

ERROR: test_node_link_update (openwisp_network_topology.tests.test_realtime.TestRealTime)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.10/site-packages/asgiref/sync.py", line 262, in __call__
    return call_result.result()
  File "/usr/lib/python3.10/concurrent/futures/_base.py", line 451, in result
    return self.__get_result()
  File "/usr/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
    raise self._exception
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.10/site-packages/asgiref/sync.py", line 302, in main_wrap
    result = await awaitable
  File "/home/nemesis/Code/openwisp/openwisp-network-topology/openwisp_network_topology/tests/test_realtime.py", line 190, in test_node_link_update
    len(self.web_driver.execute_script("return graph.data;")["links"]),
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py", line 528, in execute_script
    return self.execute(command, {"script": script, "args": converted_args})["value"]
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py", line 429, in execute
    self.error_handler.check_response(response)
  File "/home/nemesis/.virtualenvs/openwisp2/lib/python3.10/site-packages/selenium/webdriver/remote/errorhandler.py", line 232, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.JavascriptException: Message: ReferenceError: graph is not defined
Stacktrace:
@moz-nullprincipal:{5659b005-1c36-40dd-a1c2-c1026854d042}:2:7
@moz-nullprincipal:{5659b005-1c36-40dd-a1c2-c1026854d042}:3:8

This is what I see if I use to stop the testing right before the failing line (with ipdb):

Screenshot from 2025-07-30 12-30-43

An empty tab, which of course doesn't yield the desired result. Can you please change the test to fix this issue? I suggest using ipdb to run the code line by line in this test and find a different way to implement it that doesn't cause flakyness.

@coveralls
Copy link
Copy Markdown

coveralls commented Jul 31, 2025

Coverage Status

coverage: 98.987% (+0.7%) from 98.29%
when pulling a22fafc on bug/visualizer-view-realtime-updates
into 920624c on master.

@nemesifier nemesifier added the bug label Jul 31, 2025
Copy link
Copy Markdown
Member

@nemesifier nemesifier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a test for the non-admin visualizer though (which #250 is all about)?

@Dhanus3133
Copy link
Copy Markdown
Member Author

LGTM!

@nemesifier nemesifier merged commit f8bb68c into master Aug 4, 2025
13 checks passed
@nemesifier nemesifier deleted the bug/visualizer-view-realtime-updates branch August 4, 2025 17:36
Copy link
Copy Markdown
Member

@pandafy pandafy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Dhanus3133 While debugging some issues in openwisp/openwisp-firmware-upgrader#320, I had some doubts.

node_model = Node
link_model = Link
topology_model = Topology
application = import_string(getattr(settings, "ASGI_APPLICATION"))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this? This is imported when the class is loaded. This may happen before ready for all app config is executed.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wasn't imported. I tried it.

class CreateGraphObjectsMixin(object):
def _create_topology(self, **kwargs):
options = dict(
label="TestNetwork",
parser="netdiff.OlsrParser",
strategy="fetch",
url="http://127.0.0.1:9090",
protocol="OLSR",
version="0.8",
metric="ETX",
created="2017-07-10T20:02:52.483Z",
modified="2015-07-14T20:02:52.483Z",
)
options.update(kwargs)
t = self.topology_model(**options)
t.full_clean()
t.save()
return t

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I thought you were talking about models since GitHub highlighted those too. Yeah, it seems like we could have used it as well. I used this as a reference after seeing it in another test:

application = import_string(getattr(settings, "ASGI_APPLICATION"))

self.org = org

async def _prepare(self, admin=True):
communicator = await self._get_communicator(self.admin_client, self.topology.pk)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the use of communicator in selenium tests? Aren't we making sending/receiving data using the browser directly?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To verify WebSocket changes. No, we are updating directly using queries.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't we ensuring that the UI updates after receiving data from the websocket?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't we ensuring that the UI updates after receiving data from the websocket?

Dhanus here verified both:

  1. data is received as expected
  2. the UI updates as expected, with some limitations here due to the use of canvas but we're checking the JS data structures have updated as expected

I think it's a solid approach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] Real-time updates does not work on the visualizer view

4 participants