Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Robustness with cacheAllData & cacheMaxAge

    Hi,

    We have some data sources which we've configured to cache the data for 30 seconds to avoid too many server roundtrips. The data sources are basically configured as

    setCacheAllData(true);
    setCacheMaxAge(30);

    We've aiming here for 30 seconds of caching in the client and periodical refresh of the data from the server and this works. Occasionally, quite rarely - but sometimes, some editors in the grids of our application get stuck as "Loading data ..." with these data sources and they seem not to be able to recover from the situation. We have trouble repeating the issue and we suspect that it has something to do with some network errors or such. For example, it can sometimes be seen when a user changes a wifi network (or something similar) and the browser's network has a hiccup of some kind.

    My question is that does the protocol which fires the update for an expired cache (in our case every 30 seconds or longer) have a robust timeout handling or something else that should prevent this problem? My experience is that the controls relying on these data sources get stuck and it at least seems that the editors don't automatically recover when the initial cachealldata-fetch has failed. Also, this never happens for us with any control which has a data source defined to not cache the data for some seconds.

    Thanks!

    #2
    Many many things could be going wrong. We need client and, if relevant, server diagnostics for one of the failures. See the FAQ for the other rqeuired information you've also omitted.

    Comment


      #3
      We are using SmartGWT 6.0 LGPL nightly build 2017-04-09. We have trouble repeating the issue so providing a client is close to impossible. Also, server diagnostics are probably no use as there are numerous different scenarios where this could happen (an error status sent by the server, socket opened by no response, socket closed, timeout, network change, ...). What I am trying to say the server diagnostics are irrelevant in a sense, that the client should, in any case, have a logic in place to handle failed requests.

      A simple question: What does the auto loading component (a component configured to cache all data) do if the request for cache data fails?

      Comment


        #4
        There are lots of different kinds of failure - timeouts, failure to return any data, error responses, garbled responses, etc. The framework code looks to handle these failures correctly, but with any of these bad responses, callbacks or overrides from your code could crash even if the framework code is handling the error correctly. So, sorry, but there is no shortcut to either gathering some kind of diagnostic about the crash that's actually happening, or trying to put together a test case showing a specific issue with handling error responses.

        Comment


          #5
          Hi again,

          I am resurrecting this old thread with an additional question. This is a thing that still happens to us randomly.

          As far as we've investigated this, our findings are that there really is no error handling in the cacheAllData requests. What seems to happen is that if the cacheAllData-request fails, the data source goes into a stale state and does not work anymore. What seems to happen is that in DataSource.firstCacheAllDataRequest, you find

          Code:
                
          // defer all other operations against this datasource until this fetch      
          // completes, starting with this one        
          this._deferredRequests = [dsRequest];

          Then, if the fetch fails with an error (lets say the server side rest-endpoint fails for some reason, returns response status -1 or something), this is left in place.

          If the data source tries to recover later, let's say you call fetchData(null) for it, no requests are sent any more as the DataSource.fetchingClientOnlyData has


          Code:
                  
          // if we're deferring requests, add request to queue and return      
          if (this._deferredRequests) {            
          this._deferredRequests.add(dsRequest);            
          return true; // request has been deferred, return true to halt further processing        
          }

          When looking at a debugger, you can see that all requests just queue up to the _deferredRequests but nothing is ever sent. The end result is a 'stuck' data source that never recovers if an error happens while refreshing the (cacheAllData) cache. The deferred requests are cleared in the setCacheData function, but it never gets called if an error occurs.

          There seems to be another thread about this at https://forums.smartclient.com/forum...andling-errors without any advice.

          1) Are we doing something wrong or should there be somekind of strategy to deal with the above situation?

          2) This issue realizes to us in our application in a way that the cached data sources are used as optionDataSources in ListGridFields. If the cached datasource fails and therefore fails to provide data to the field in ListGrid, it also seems that the valueMap for the field is left unset. This results in primary keys of our option data source records to be shown in the grid. Should the ListGrids (or fields of them) also recover automatically? Is there something we can do to force the option data source bound fields in the grid to re-initialize (or somehow recover) their valueMaps if they have failed to fetch them once?


          Thanks!
          Marko


          "originally posted by markok "

          Comment


            #6
            A cacheAllData DataSource won't recover from a bad server response, and it's not really clear what correct handling would be.

            If you're unable to correct your server, one approach would be to destroy and re-create the DataSource if an error occurs. Another would be to do the fetch yourself and then create a clientOnly DataSource from the results.

            Comment


              #7
              Hi,

              Ok. A sensible approach might be to at least retry after the maxAge-setting has expired again. For us to handle errors is a bit hard - we have no way of knowing then the cacheAllData fetch has failed as everything happens automatically under the hood?

              Also, there is really nothing we can do on our server. The issue is most likely some kind of rare occurrence such as some kind of transport error (for example wifi problem).

              The current approach to make this work seems to be to implement the cacheAllData/maxAge -thing from the scratch with a clientOnly data source, as you suggest.


              "originally posted by markok "

              Comment


                #8
                If we were to retry once the cache reached maxAge then presumably the end user would see this aspect of the app return to functionality after several minutes? That wouldn't be something we'd consider an acceptable solution for our public apps..

                Also, is it somehow possible for just the cacheAllData fetch to somehow fail while the rest of the app is still viable? That doesn't sound like a wifi connectivity error, rather it sounds like an intermittent error in one server subsystem, which again, should most likely be addressed on the server if you can.

                So again, if you have an intermittent error for one particular fetch, which leaves the rest of the app functional, but just this cacheAllData DataSource is broken, then we would recommend doing a fetch (w/error handling) and creating a clientOnly DataSource, which requires very little code.

                If you need some inspiration for how simple this is, then you might look at DataSource.getClientOnlyDataSource() - just the else clause - it's about 10 lines. Add a timer to that to expire the cache if you need to, and you should be done quite quickly.

                Comment


                  #9
                  Ok thanks, we will try to find a workaround for this. We will most likely migrate away from using the cacheAllData+maxAge.

                  You are correct that we _do not know_ the actual problem causing this. We are 100% sure it is not a server problem though - it is something in the transport layer or in the application itself. We are not seeing any errors anywhere and the only data sources in our app with this problem are the ones with cacheAllData + maxAge set. There is nothing else different with these data sources in our app. It might be some kind of obscure timing problem in the component <-> optiondatasource (with cacheAllData/maxAge fetch) as it seems to happen very rarely.


                  "originally posted by markok "

                  Comment


                    #10
                    OK, let us know if we can help with isolating the error. We, for one, have set up automatic storage of JS errors and transport errors in a DB for our live sites - you might try that, or just train some users in how to gather diagnostics.

                    One thing that's different about cacheAllData requests is that they might be larger, since it's a full download of the dataset. Maybe that trips an error.

                    Comment

                    Working...
                    X