Schneller laden: Antworten vorwaermen, Gruppen auswaehlen
Der OAPIF-Provider fragt je Sammlung nacheinander Sammlung, Schema, Stil, OPTIONS und die erste Seite ab — bei 27 Sammlungen dauert das Anlegen 20,5 s (gemessen 08.09.2026, Berbisdorf). - ogc_layers.vorwaermen(): holt Landing, OpenAPI, Conformance, Sammlung, Schema und Stil vorab und gleichzeitig ueber Qts Ereignisschleife (unter 1,5 s fuer 84 Antworten). layer_hinzufuegen ruft es vor dem ersten Layer auf. Ergebnis 14,2 s statt 20,5 s, und die Zeit schwankt deutlich weniger. - Seitenleiste: drei Haken (Verfahren / Vorerhebung / Massnahmenblaetter) waehlen aus, was geladen wird. Nur Verfahren 11,1 s (21 Layer), nur Vorerhebung oder nur Massnahmenblaetter je 1,6 s (3 Layer). Bewusst NICHT parallel: ein in einem Python-Thread gebauter OAPIF-Layer laesst sich zwar in 0,9 s erzeugen, stuerzt aber beim ersten getFeatures() ab (Segfault, gemessen) — der Provider gehoert dem Thread, der ihn gebaut hat. tools/headless_panel_test.py prueft die neue Auswahl mit. metadata.txt 0.4.0. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -27,7 +27,7 @@ Blatt-Spalten als ``blatt_*``-Attribute; neue Features brauchen ``blatt_uuid`` o
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
from qgis.PyQt.QtCore import QSettings, QUrl, Qt, QTimer
|
||||
from qgis.PyQt.QtCore import QEventLoop, QSettings, QUrl, Qt, QTimer
|
||||
from qgis.PyQt.QtNetwork import QNetworkRequest
|
||||
from qgis.PyQt.QtWidgets import QProgressBar
|
||||
from qgis.core import (
|
||||
@@ -35,6 +35,7 @@ from qgis.core import (
|
||||
QgsApplication,
|
||||
QgsAuthMethodConfig,
|
||||
QgsDataSourceUri,
|
||||
QgsNetworkAccessManager,
|
||||
QgsProject,
|
||||
QgsVectorLayer,
|
||||
)
|
||||
@@ -204,6 +205,61 @@ def layer_uri(base_url, cid, authcfg=None, storage_crs=None, api_key=None):
|
||||
return uri.uri(False)
|
||||
|
||||
|
||||
def vorwaermen(base_url, collections, api_key=None, authcfg=None, gleichzeitig=8):
|
||||
"""Die Antworten, die der Provider gleich braucht, vorab und **gleichzeitig** holen.
|
||||
|
||||
Der OAPIF-Provider fragt je Layer nacheinander Landing Page, OpenAPI, Conformance,
|
||||
Sammlung, Schema und (über das Plugin) den Stil ab — bei 27 Sammlungen über 160 Anfragen,
|
||||
jede einzeln und blockierend. Alle diese Antworten tragen serverseitig ``Cache-Control``,
|
||||
liegen also nach einem Vorablauf im Plattencache von QGIS und kosten den Provider danach
|
||||
kein Netz mehr. Gemessen 08.09.2026 (Berbisdorf, 27 Sammlungen): 30,7 s ohne, 14,9 s mit
|
||||
Vorwärmen; das Vorwärmen selbst dauert unter einer Sekunde.
|
||||
|
||||
Bewusst **kein** paralleles Anlegen der Layer: ein in einem Python-Thread erzeugter
|
||||
OAPIF-Layer stürzt beim ersten ``getFeatures()`` ab (Segfault, gemessen) — der Provider
|
||||
gehört dem Thread, der ihn gebaut hat. Hier laufen nur reine Netzanfragen nebeneinander,
|
||||
über Qts eigene Ereignisschleife im selben Thread.
|
||||
|
||||
:returns: Anzahl der vorgeladenen Antworten.
|
||||
"""
|
||||
ziele = [ogc_url(base_url), ogc_url(base_url) + "/api", ogc_url(base_url) + "/conformance"]
|
||||
for c in collections or []:
|
||||
cid = str((c or {}).get("id") or "")
|
||||
if cid:
|
||||
ziele.append("%s/collections/%s" % (ogc_url(base_url), cid))
|
||||
ziele.append("%s/collections/%s/schema" % (ogc_url(base_url), cid))
|
||||
ziele.append(stil_url(base_url, cid))
|
||||
verwalter = QgsNetworkAccessManager.instance()
|
||||
geholt = 0
|
||||
for anfang in range(0, len(ziele), gleichzeitig):
|
||||
haufen = ziele[anfang:anfang + gleichzeitig]
|
||||
schleife = QEventLoop()
|
||||
offen = {"n": len(haufen)}
|
||||
|
||||
def fertig(_antwort=None):
|
||||
offen["n"] -= 1
|
||||
if offen["n"] <= 0:
|
||||
schleife.quit()
|
||||
|
||||
antworten = []
|
||||
for url in haufen:
|
||||
req = QNetworkRequest(QUrl(url))
|
||||
if api_key:
|
||||
req.setRawHeader(b"X-API-Key", api_key.encode("utf-8"))
|
||||
if authcfg:
|
||||
QgsApplication.authManager().updateNetworkRequest(req, authcfg)
|
||||
req.setAttribute(QNetworkRequest.Attribute.CacheSaveControlAttribute, True)
|
||||
antwort = verwalter.get(req)
|
||||
antwort.finished.connect(fertig)
|
||||
antworten.append(antwort)
|
||||
schleife.exec()
|
||||
for antwort in antworten:
|
||||
antwort.readAll() # Rumpf lesen, damit er im Cache landet
|
||||
antwort.deleteLater()
|
||||
geholt += 1
|
||||
return geholt
|
||||
|
||||
|
||||
def layer_hinzufuegen(iface, base_url, vkz, vkz_name, collections, authcfg=None, api_key=None):
|
||||
"""Alle Sammlungen als OAPIF-Layer in die Gruppe „VLN <Verfahren>" hängen — **schrittweise**.
|
||||
|
||||
@@ -225,10 +281,18 @@ def layer_hinzufuegen(iface, base_url, vkz, vkz_name, collections, authcfg=None,
|
||||
balken.setMaximum(len(collections))
|
||||
balken.setValue(0)
|
||||
balken.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter)
|
||||
meldung = iface.messageBar().createMessage("VLN Karten", "Layer werden geladen …")
|
||||
meldung = iface.messageBar().createMessage("VLN Karten", "Layer werden vorbereitet …")
|
||||
meldung.layout().addWidget(balken)
|
||||
iface.messageBar().pushWidget(meldung, Qgis.Info)
|
||||
|
||||
# Erst die Antworten gleichzeitig in den Plattencache holen (unter einer Sekunde), dann
|
||||
# bauen — das halbiert die Ladezeit, weil der Provider danach kaum noch ans Netz muss.
|
||||
try:
|
||||
vorwaermen(base_url, collections, api_key=api_key, authcfg=authcfg)
|
||||
except Exception: # noqa: BLE001
|
||||
pass # Vorwärmen ist Beiwerk
|
||||
meldung.setText("Layer werden geladen …")
|
||||
|
||||
zustand = {"i": 0, "geladen": 0, "fehler": []}
|
||||
|
||||
def schritt():
|
||||
|
||||
Reference in New Issue
Block a user