Open dlaplexurenet opened 3 years ago
You raise an important issue actually; how to make sure a locally cached list could be trusted to be current; as things stand I don't have an answer (your proposal to check the Etag does make sense but it is not supported by the API).
The advantage of adding a HEAD method to the API won't break any backward compatibility as we do not touch anything existing. Additionally, yet I think it's not too relevant in a local network, is the ability of adding gzip compression. In your requests you allow gzipped responses, but the API unfortunately doesn't reply with a compressed response. Another way for fine tuning is basically allowing http/2 in jetty (supported as of 9.3, OH3 is using 9.4 - so I guess it's just a matter of configuration). Well, actually on the UI side, there's not too much you can actually do. A complete async architecture where the backend informs you through SSE about any changes on the objects such as Items, Things, Links could trigger on the UI side a partial of full update of the local cache. This would be even more proactive than doing a HEAD before the GET.
A complete async architecture where the backend informs you through SSE about any changes on the objects such as Items, Things, Links could trigger on the UI side a partial of full update of the local cache. This would be even more proactive than doing a HEAD before the GET.
That's basically how other UIs operate - HABPanel, HABot, the former Paper UI - the problem being that some folks have very busy event buses and it would lead to problems such as increased CPU usage, reduced battery lives... So for this UI I made the choice of keeping the SSE traffic/simultaneous connections as low as possible (SSE even has strict limitations in the latter when not using HTTP/2), and close/reopen them with topic filters relevant to the current page to avoid these problems as much as possible. This as the cost of having more regular requests to ensure the data is always current (this could possibly be improved in some areas like the item picker).
The HEAD requests/ETag approach can work, but I suspect your bottleneck is in the processing rather than the downloading of the data, so if you hit the same bottleneck during the HEAD request, it's not going to help much (it'll even be worse as you'll have to wait for it to end before requesting the actual data).
6 seconds to get items is really too much, even with 1400 items, so I think bringing that number down would be the most pressing problem.
some folks have very busy event buses
Sure, I do understand, but here we are rather talking about things, items and links and I thought rather about a notification to tell the frontend to gather new full list of items (which is useful when you have maybe more than 10 items to load after a file reload or bulk addition through text definition in the frontend) or just a notification to gather a specific item.
I do not really know where the bottleneck comes from in my case. In the browser I only see the dowloading part, and I have not sufficient knowledge of Java and its components to see/understand in Jetty/Pax, what is taking so much time to download 1MB from LAN - at least from what I can read about jsondb, it's actually loading the content into memory, so I doubt it's related to system level or I/Os (running Buster on an RPi with SSD and 4GB of memory). Here is at least some information I can provide by opening the Items list in Main UI:
20:48:53.279 [DEBUG] [pax.web.service.spi.model.ServerModel] - Matching [/rest/items]...
20:48:53.284 [DEBUG] [pax.web.service.spi.model.ServerModel] - Path [/rest/items] matched to {pattern=/rest/.*,model=ServletModel{id=org.ops4j.pax.web.service.spi.model.ServletModel-11,name=cxf-servlet,urlPatterns=[/*],alias=null,servlet=org.apache.aries.jax.rs.whiteboard.internal.Whiteboard$1@1c991d2,initParams={hide-service-list-page=true},context=ContextModel{id=org.ops4j.pax.web.service.spi.model.ContextModel-10,name=rest,httpContext=org.ops4j.pax.web.extender.whiteboard.internal.WebApplication$1@103f320,contextParams={httpContext.shared=true, webapp.context=rest},virtualHosts={},connectors={}}}}
20:48:53.293 [DEBUG] [ice.jetty.internal.HttpServiceContext] - Handling request for [/items] using http context [org.ops4j.pax.web.extender.whiteboard.internal.WebApplication$1@103f320]
20:48:53.297 [DEBUG] [ty.internal.HttpServiceServletHandler] - handling request org.ops4j.pax.web.service.jetty.internal.HttpServiceRequestWrapper@1b2f3bc, org.ops4j.pax.web.service.jetty.internal.HttpServiceResponseWrapper@136fe13
20:48:58.772 [DEBUG] [pax.web.service.spi.model.ServerModel] - Matching [/rest/events]...
20:48:58.778 [DEBUG] [pax.web.service.spi.model.ServerModel] - Path [/rest/events] matched to {pattern=/rest/.*,model=ServletModel{id=org.ops4j.pax.web.service.spi.model.ServletModel-11,name=cxf-servlet,urlPatterns=[/*],alias=null,servlet=org.apache.aries.jax.rs.whiteboard.internal.Whiteboard$1@1c991d2,initParams={hide-service-list-page=true},context=ContextModel{id=org.ops4j.pax.web.service.spi.model.ContextModel-10,name=rest,httpContext=org.ops4j.pax.web.extender.whiteboard.internal.WebApplication$1@103f320,contextParams={httpContext.shared=true, webapp.context=rest},virtualHosts={},connectors={}}}}
20:48:58.788 [DEBUG] [ice.jetty.internal.HttpServiceContext] - Handling request for [/events] using http context [org.ops4j.pax.web.extender.whiteboard.internal.WebApplication$1@103f320]
20:48:58.794 [DEBUG] [ty.internal.HttpServiceServletHandler] - handling request org.ops4j.pax.web.service.jetty.internal.HttpServiceRequestWrapper@1a62ac5, org.ops4j.pax.web.service.jetty.internal.HttpServiceResponseWrapper@4162ef
I'll see what I can provide more ...
I'm coming from #573: I'm thinking of following another approach (REST cache), but that approach needs two requirements to be met:
The problem
Personally I use pretty often the "Add Items from Textual Definition". When you open this page, it's basically doing 3 XHR calls to load things, items and links. I have roughly 220 things and over 1400 items. After a restart of OpenHAB, this takes roughly 2s from things endpoint and 6s for items. After a couple of days, these waiting times go down hill (I opened 2109 in openhab-core for this).
Regardless from the root cause of this issue, I believe that the things, items and links endpoints are probably reloaded very often even if there's no need to load them from the server. Example: searching the items or display the badge with items count.
Your suggestion
Would it be possible to load things, items and links and check the last modification of these objects on the server side? So before initiating a GET, you could do a HEAD, verify last modification or etag and compare with information in localStorage of the browser. As long as no changes have been made, all operations could be done on the data in the localStorage.
Your environment
Additional information