1
0
Эх сурвалжийг харах

Merge branch 'main' into 1.4

# Conflicts:
#	nicegui/nicegui.py
#	poetry.lock
Falko Schindler 1 жил өмнө
parent
commit
e17be83079

+ 3 - 3
fly.toml

@@ -38,8 +38,8 @@ kill_timeout = "5s"
     handlers = ["tls", "http"]
   [services.concurrency]
     type = "requests"
-    hard_limit = 60
-    soft_limit = 30
+    hard_limit = 50
+    soft_limit = 20
 
   [[services.tcp_checks]]
     interval = "10s"
@@ -56,5 +56,5 @@ kill_timeout = "5s"
     tls_skip_verify = false
 
 [[metrics]]
+  path = "/"
   port = 9062
-  path = "/metrics"

+ 36 - 22
nicegui/nicegui.py

@@ -174,7 +174,7 @@ async def handle_disconnect(client: Client) -> None:
     delay = client.page.reconnect_timeout if client.page.reconnect_timeout is not None else globals.reconnect_timeout
     await asyncio.sleep(delay)
     if not client.shared:
-        _delete_client(client.id)
+        _delete_client(client)
     for t in client.disconnect_handlers:
         safe_invoke(t, client)
     for t in globals.disconnect_handlers:
@@ -216,33 +216,47 @@ def handle_javascript_response(client: Client, msg: Dict) -> None:
 async def prune_clients() -> None:
     """Prune stale clients in an endless loop."""
     while True:
-        stale_clients = [
-            id
-            for id, client in globals.clients.items()
-            if not client.shared and not client.has_socket_connection and client.created < time.time() - 60.0
-        ]
-        for client_id in stale_clients:
-            _delete_client(client_id)
+        try:
+            stale_clients = [
+                client
+                for client in globals.clients.values()
+                if not client.shared and not client.has_socket_connection and client.created < time.time() - 60.0
+            ]
+            for client in stale_clients:
+                _delete_client(client)
+        except Exception:
+            # NOTE: make sure the loop doesn't crash
+            globals.log.exception('Error while pruning clients')
         await asyncio.sleep(10)
 
 
 async def prune_slot_stacks() -> None:
     """Prune stale slot stacks in an endless loop."""
     while True:
-        running = [
-            id(task)
-            for task in asyncio.tasks.all_tasks()
-            if not task.done() and not task.cancelled()
-        ]
-        stale = [
-            id_
-            for id_ in globals.slot_stacks
-            if id_ not in running
-        ]
-        for id_ in stale:
-            del globals.slot_stacks[id_]
+        try:
+            running = [
+                id(task)
+                for task in asyncio.tasks.all_tasks()
+                if not task.done() and not task.cancelled()
+            ]
+            stale = [
+                id_
+                for id_ in globals.slot_stacks
+                if id_ not in running
+            ]
+            for id_ in stale:
+                del globals.slot_stacks[id_]
+        except Exception:
+            # NOTE: make sure the loop doesn't crash
+            globals.log.exception('Error while pruning slot stacks')
         await asyncio.sleep(10)
 
 
-def _delete_client(client_id: str) -> None:
-    globals.clients.pop(client_id).remove_all_elements()
+def _delete_client(client: Client) -> None:
+    """Delete a client and all its elements.
+
+    If the global clients dictionary does not contain the client, its elements are still removed and a KeyError is raised.
+    Normally this should never happen, but has been observed (see #1826).
+    """
+    client.remove_all_elements()
+    del globals.clients[client.id]

+ 1 - 1
poetry.lock

@@ -3051,4 +3051,4 @@ plotly = ["plotly"]
 [metadata]
 lock-version = "2.0"
 python-versions = "^3.8"
-content-hash = "f0a0ab5d0551c62190399771521b47c79dc54c8e8ddc310d3e6b0a1117072d73"
+content-hash = "1525b3eb18d862e499d4380191406bc5413917be191d9ce5fba5cd2c10677d15"

+ 1 - 1
pyproject.toml

@@ -16,7 +16,7 @@ Pygments = ">=2.15.1,<3.0.0"
 uvicorn = {extras = ["standard"], version = "^0.22.0"}
 fastapi = ">=0.92,<1.0.0"
 fastapi-socketio = "^0.0.10"
-python-socketio = ">=5.9.0" # https://github.com/zauberzeug/nicegui/issues/1809
+python-socketio = ">=5.10.0" # https://github.com/zauberzeug/nicegui/issues/1809
 vbuild = ">=0.8.2"
 watchfiles = ">=0.18.1,<1.0.0"
 jinja2 = "^3.1.2"

+ 2 - 2
set_scale.sh

@@ -1,10 +1,10 @@
 #!/usr/bin/env bash
 
-fly scale count app=3  --region fra -y
+fly scale count app=4  --region fra -y
 fly scale count app=3  --region iad -y
 fly scale count app=1  --region jnb -y
 fly scale count app=3  --region lax -y
-fly scale count app=3  --region lhr -y
+fly scale count app=4  --region lhr -y
 fly scale count app=2  --region bom -y
 fly scale count app=2  --region mad -y
 fly scale count app=3  --region mia -y

+ 2 - 1
tests/conftest.py

@@ -89,7 +89,8 @@ def screen(driver: webdriver.Chrome, request: pytest.FixtureRequest, caplog: pyt
     if screen_.is_open:
         screen_.shot(request.node.name)
     logs = screen_.caplog.get_records('call')
-    assert not logs, f'There were unexpected logs:\n-------\n{logs}\n-------'
     screen_.stop_server()
     if DOWNLOAD_DIR.exists():
         shutil.rmtree(DOWNLOAD_DIR)
+    if logs:
+        pytest.fail('There were unexpected logs. See "Captured log call" below.', pytrace=False)

+ 1 - 1
website/static/search_index.json

@@ -1271,7 +1271,7 @@
   },
   {
     "title": "Context Menu",
-    "content": "Creates a context menu based on Quasar's QMenu <https://quasar.dev/vue-components/menu>_ component. The context menu should be placed inside the element where it should be shown. It is automatically opened when the user right-clicks on the element and appears at the mouse position.",
+    "content": "Creates a context menu based on Quasar's QMenu <https://quasar.dev/vue-components/menu>_ component. The context menu should be placed inside the element where it should be shown. It is automatically opened when the user right-clicks on the element and appears at the mouse position. open Open the context menu.close Close the context menu.",
     "url": "/documentation/context_menu"
   },
   {