mesa icon indicating copy to clipboard operation
mesa copied to clipboard

Modular Server doesn't handle multiple connections properly

Open NeilW opened this issue 5 years ago • 3 comments

Describe the bug If you open multiple tabs in your browser to the Mesa server you still only get one model running. Altering the paramenters on one tab affects the model output on all the others.

Expected behavior Each tab should run its own instance of the model. Messages from the client should be applied to the model associated with the web socket.

To Reproduce Open multiple tabs and point them at the mesa server. Adjusting the parameters on one tab will alter the output on the others.

Additional context This fault stops the mesa server from being used as a public facing application server. It's fairly easy to fix. The model just has to be lifted from the application to the socket handler and the socket can act as the session layer. I've made the necessary alterations here: https://github.com/newwayland/baseline-economy/blob/master/BaselineEconomy/ModularVisualization.py

NeilW avatar Jun 17 '20 07:06 NeilW

Thank you for the bug report! Could you submit your patch as a Pull Request??

Corvince avatar Jun 30 '20 10:06 Corvince

@NeilW I saw that you have a fix for this issue on your fork. Can you submit a PR with that? Don't worry about failing tests or something, I can add/modify them if you don't want to do that. I could also copy paste your fix, but I would like to give the credit to you

Corvince avatar Oct 25 '20 19:10 Corvince

I've added a PR. Apologies for not getting onto the tests. They looked like they may need a bit of refactoring and I haven't had the bandwidth to tackle them

NeilW avatar Oct 25 '20 21:10 NeilW

I tested running multiple tabs for the Solara viz, and one of the tabs crashed. It looks like the only way for the Solara viz to be accessed in parallel in public is via Jupyter.

rht avatar Aug 07 '23 05:08 rht

Interesting, what was the error message?

Corvince avatar Aug 07 '23 12:08 Corvince

It's a deep traceback:

  File "/venv/lib/python3.10/site-packages/ipywidgets/widgets/widget.py", line 220, in m
    return(method(self, *args, **kwargs))
  File "/venv/lib/python3.10/site-packages/ipywidgets/widgets/widget.py", line 773, in _handle_msg
    self.set_state(state)
  File "/venv/lib/python3.10/site-packages/ipywidgets/widgets/widget.py", line 650, in set_state
    with self._lock_property(**sync_data), self.hold_trait_notifications():
  File "/run/current-system/sw/lib/python3.10/contextlib.py", line 142, in __exit__
    next(self.gen)
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 369, in hold_trait_notifications_extra
    with rc, hold_trait_notifications(*args, **kwargs):
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 1143, in __exit__
    self._possible_rerender()
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 1335, in _possible_rerender
    self.render(self.element, self.container)
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 1433, in render
    widget = self._reconsolidate(self.element, default_key="/", parent_key=ROOT_KEY)
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 1794, in _reconsolidate
    widget = self._reconsolidate(child_context.root_element_next, "/", new_parent_key)
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 1794, in _reconsolidate
    widget = self._reconsolidate(child_context.root_element_next, "/", new_parent_key)
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 1914, in _reconsolidate
    kwargs = reconsolidate_children()
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 1882, in reconsolidate_children
    new_kwargs = self._visit_children_values(kwargs, key, parent_key, self._reconsolidate)
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 2120, in _visit_children_values
    return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 2120, in <dictcomp>
    return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 2115, in _visit_children_values
    values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 2115, in <listcomp>
    values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 2112, in _visit_children_values
    return f(value, key, parent_key)
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 1794, in _reconsolidate
    widget = self._reconsolidate(child_context.root_element_next, "/", new_parent_key)
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 1794, in _reconsolidate
    widget = self._reconsolidate(child_context.root_element_next, "/", new_parent_key)
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 1794, in _reconsolidate
    widget = self._reconsolidate(child_context.root_element_next, "/", new_parent_key)
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 1914, in _reconsolidate
    kwargs = reconsolidate_children()
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 1882, in reconsolidate_children
    new_kwargs = self._visit_children_values(kwargs, key, parent_key, self._reconsolidate)
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 2120, in _visit_children_values
    return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 2120, in <dictcomp>
    return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 2115, in _visit_children_values
    values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 2115, in <listcomp>
    values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 2112, in _visit_children_values
    return f(value, key, parent_key)
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 1794, in _reconsolidate
    widget = self._reconsolidate(child_context.root_element_next, "/", new_parent_key)
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 1794, in _reconsolidate
    widget = self._reconsolidate(child_context.root_element_next, "/", new_parent_key)
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 1914, in _reconsolidate
    kwargs = reconsolidate_children()
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 1882, in reconsolidate_children
    new_kwargs = self._visit_children_values(kwargs, key, parent_key, self._reconsolidate)
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 2120, in _visit_children_values
    return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 2120, in <dictcomp>
    return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 2115, in _visit_children_values
    values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 2115, in <listcomp>
    values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 2112, in _visit_children_values
    return f(value, key, parent_key)
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 1794, in _reconsolidate
    widget = self._reconsolidate(child_context.root_element_next, "/", new_parent_key)
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 1794, in _reconsolidate
    widget = self._reconsolidate(child_context.root_element_next, "/", new_parent_key)
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 1914, in _reconsolidate
    kwargs = reconsolidate_children()
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 1882, in reconsolidate_children
    new_kwargs = self._visit_children_values(kwargs, key, parent_key, self._reconsolidate)
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 2120, in _visit_children_values
    return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 2120, in <dictcomp>
    return {k: self._visit_children_values(v, f"{key}{k}/", parent_key, f) for k, v in value.items()}
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 2115, in _visit_children_values
    values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 2115, in <listcomp>
    values = [self._visit_children_values(v, f"{key}{index}/", parent_key, f) for index, v in enumerate(value)]
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 2112, in _visit_children_values
    return f(value, key, parent_key)
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 1794, in _reconsolidate
    widget = self._reconsolidate(child_context.root_element_next, "/", new_parent_key)
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 1998, in _reconsolidate
    self._remove_element(self.context.elements[key], key, parent_key=parent_key)
  File "/venv/lib/python3.10/site-packages/reacton/core.py", line 2066, in _remove_element
    assert widget.model_id in widgets.Widget.widgets
AssertionError

rht avatar Aug 07 '23 12:08 rht

I just tested with 2 tabs (one in incognito) via Jupyter. The 2 simulations in the 2 tabs run in parallel, independently. This means that we can offload #481 to point to how to expose a Jupyter server to be web public.

rht avatar Aug 07 '23 12:08 rht

One complication is that, some users probably don't want to expose their full source code. I will ask at Solara Discord about this topic.

rht avatar Aug 07 '23 12:08 rht

It seems to be a fixable problem. From Solara Discord:

Solara should work in multiple tabs. I can be that somewhere, your app has global shared state that's accessed from multiple threads (each tab runs in it's own thread)

rht avatar Aug 07 '23 14:08 rht

Fixed in #1759 for Solara.

rht avatar Aug 07 '23 15:08 rht