1. #1
    Ext User
    Join Date
    Feb 2009
    Location
    Japan
    Posts
    10
    Vote Rating
    0
    r3ap3r is on a distinguished road

      0  

    Exclamation Undo store.remove() on server error

    Undo store.remove() on server error


    I have a DirectStore that fires off a destroy request to the server when I call store.remove(record); What I can't figure out (and I'm sure I'm not the only one who needs this) and haven't found a solution to in these forums is:

    If the server fails to delete the record, how can I prevent the record from actually being deleted from the Store?

    Basically I have a DataView that is displaying the contents of the store. If I delete the element from the DataView by removing it from the store (store.remove(record)), and the store fires off a crud destroy request to my server, but that request fails (maybe there is a connection issue to the database, permissions issue, etc) and returns a {'success':false}, then I need the item to remain in the store and the DataView to be refreshed to return the item that wasn't actually deleted on the server back into the DataView.

    I can think of a million ways to achieve the end result, but not in a way that seems logical. I would think the store (with a DataWriter) shouldn't actually delete the record until it gets a success response from the server. Maybe that is what it's doing and it's actually still in the store and I just can't find it, who knows.

    If anyone knows the CORRECT way of dealing with this situation please let me know.

    Examples of NON-correct ways of handling the problem (at least in my mind).

    1) Set the destroy handler in the DirectProxy api to be an empty function that actually doesn't do anything. Then have a status parameter for each record, and instead of remove()ing the record I set the status to 'deleted' and do an Update. Then in the callback function if the record wasn't actually deleted on the server I just remove the 'deleted' status and everything is fine. If it was successfully removed from the server then I just call store.remove(record) and it goes away (with the destroy request going to an empty function instead of a Direct function.

    Obviously this would work, but it isn't logical. What is the point of a destroy request if there is no way to deal with errors on the server.

    2) Use the destroy handler as normal. If the destroy fails on the server, then return the full data for the record (from the server) in the response so that it can be 're-added' to the DataStore. This would work, and is probably cleaner than option #1, but it requires that I create an additional database call on the server to pull the record information to return to the client (since the destroy request only sends the ID, not the whole record to the server). In my case the database call to create that record involves multiple joins and is expensive, and the only reason for doing it is because the DirectStore doesn't properly handle server failures on destroy (at least as far as I can tell). Again, not really a good solution.

    3) Extend DirectStore to work as it should and just use my own extension instead that properly handles the errors. This works, but just adds to the amount of code my users need to download all to fix a problem that should be addressed in the core DataStore.

    4) Stop using Ext.Direct and go back to manually creating the ajax calls and dealing with the server responses which was working fine to begin with. (Wondering why I decided to try and convert it to use Direct anyway. ).

    Thanks in advance,
    -Chris

  2. #2
    Sencha - Ext JS Dev Team evant's Avatar
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    16,833
    Vote Rating
    609
    evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute

      0  

    Default


    I believe this is already in the 3.0 download:

    Code:
        onDestroyRecords : function(success, rs, data) {
            // splice each rec out of this.removed
            rs = (rs instanceof Ext.data.Record) ? [rs] : [].concat(rs);
            for (var i=0,len=rs.length;i<len;i++) {
                this.removed.splice(this.removed.indexOf(rs[i]), 1);
            }
            if (success === false) {
                // put records back into store if remote destroy fails.
                // @TODO: Might want to let developer decide.
                for (i=rs.length-1;i>=0;i--) {
                    this.insert(rs[i].lastIndex, rs[i]);    // <-- lastIndex set in Store#destroyRecord
                }
            }
        }
    Might give you a point to start debugging at least.
    Evan Trimboli
    Sencha Developer
    Twitter - @evantrimboli
    Don't be afraid of the source code!

  3. #3
    Ext User
    Join Date
    Feb 2009
    Location
    Japan
    Posts
    10
    Vote Rating
    0
    r3ap3r is on a distinguished road

      0  

    Default


    Evan,
    Thanks for posting. I'm not sure how I missed that one. I figured I must just be missing something because it didn't make sense not to handle the errors. That should be enough of a hint to figure out what I'm doing wrong.

    Thanks again,
    -Chris

  4. #4
    Ext User
    Join Date
    Feb 2009
    Location
    Japan
    Posts
    10
    Vote Rating
    0
    r3ap3r is on a distinguished road

      0  

    Default


    Evan,
    OK, I'm still banging my head against the wall here. I have played with the code and still can't get this to work.

    In the method you posted is the code:
    Code:
    alert("Success:" + success + ":");
    if (success === false) {
      alert("WTF");
      // put records back into store if remote destroy fails.
      // @TODO: Might want to let developer decide.
      for (i=rs.length-1;i>=0;i--) {
        this.insert(rs[i].lastIndex, rs[i]);    // <-- lastIndex set in Store#destroyRecord
      }
    }
    Minus the alert statements (obviously I put those in). No matter what I try success is always true (and my WTF alert never gets called).

    My server is returning this:
    Code:
    {"type":"rpc","tid":4,"action":"Gallery","method":"DeleteImage","result":{"success":false}}
    although I have also tried returning:
    Code:
    {"type":"rpc","tid":5,"action":"Gallery","method":"DeleteImage","result":false}
    
    and
    
    {"type":"rpc","tid":7,"action":"Gallery","method":"DeleteImage","result":false,"success":false}
    each time the 'success' variable in the onDestroyRecords method is true.

    So what am I doing wrong and not seeing here?

    Thanks,
    -Chris

  5. #5
    Ext User
    Join Date
    Oct 2009
    Posts
    4
    Vote Rating
    0
    UltraDM is on a distinguished road

      0  

    Default


    Quote Originally Posted by r3ap3r View Post
    If I delete the element from the DataView by removing it from the store (store.remove(record)), and the store fires off a crud destroy request to my server, but that request fails (maybe there is a connection issue to the database, permissions issue, etc) and returns a {'success':false}, then I need the item to remain in the store and the DataView to be refreshed to return the item that wasn't actually deleted on the server back into the DataView.
    In this case the server should reply with an appropriate status code of 4xx, 5xx and I think in your case it returns 200.

    Having the server return the correct status code fixed the problem for me

  6. #6
    Ext User
    Join Date
    Aug 2009
    Posts
    3
    Vote Rating
    0
    mikovali is on a distinguished road

      0  

    Default


    I have the same problem.
    But when I send a header with a 500 response, then the request is done twice. Exactly the same request. After the second request is made, the records are added to the store like I wanted.
    But why the two identical requests?

  7. #7
    Sencha User pieturp's Avatar
    Join Date
    Oct 2007
    Location
    The Netherlands
    Posts
    36
    Vote Rating
    0
    pieturp is on a distinguished road

      0  

    Default


    @mikovali See Ext.direct.RemotingProvider (maxRetries)

Turkiyenin en sevilen filmlerinin yer aldigi xnxx internet sitemiz olan ve porn sex tarzi bir site olan mobil porno izle sitemiz gercekten dillere destan bir durumda herkesin sevdigi bir site olarak tarihe gececege benziyor. Sitenin en belirgin ozelliklerinden birisi de Turkiyede gercekten kaliteli ve muntazam, duzenli porno izle siteleri olmamasidir. Bu yuzden iste. Ayrica en net goruntu kalitesine sahip adresinde yayinlanmaktadir. Mesela diğer sitelerimizden bahsedecek olursak, en iyi hd porno video arşivine sahip bir siteyiz. "The Best anal porn videos and slut anus, big asses movies set..." hd porno faketaxi