PDA

View Full Version : Store's models get corrupted at sync? I'm doing it wrong?



ManuelP
15 Sep 2011, 2:54 AM
I don't know if this is a bug or not, so I post my question here in the bugreport format.

REQUIRED INFORMATION

Ext version tested:


Ext 4.0.2a

Browser versions tested against:


FF7 (firebug 1.9.0a2 installed)

Description:
Here is the context:


A store containing a set of models (each one have some fields to describe a date, like dayOfMonth, month and year)
A panel with several buttons, each one opens a window containing a grid to see and edit the models in a given date.


The listener associated with every button filters the store and opens the details window in which I can edit and save the models. Every time the windows is closed, the store's filter is cleared.

Problem is: when I sync the store (regardless there are modified/dirty models or not), the filtered models get corrupted. If I don't filter the store EVERY model gets corrupted. I've written some log statements before and after the window create/close events to iterate through the store's models in a test environment, and this is the result:



Models:
- 10 / 3 / 2011
-> Object { phantom=true, internalId="ext-record-88", raw={...}, other elements...} Dirty? false
- 10 / 4 / 2011
-> Object { phantom=true, internalId="ext-record-89", raw={...}, other elements...} Dirty? false

POST http://localhost:9000/plan?_dc=1316080711590
200 OK

Models:
- 0 / 0 / 0
-> Object { phantom=false, internalId="ext-record-97", raw={...}, other elements...} Dirty? false
- 10 / 4 / 2011
-> Object { phantom=true, internalId="ext-record-89", raw={...}, other elements...} Dirty? false


Interesting is the fact that if a place the same log statements directly after the sync (in the save button's handler in the details window), the models seems fine.

Steps to reproduce the problem:


Load the store
Filter the store (or not, it doesn't matter)
Create an Ext.window.Window that contains a grid associated with the same store (the link to the store is managed by ExtJS's MVC mechanism)
Modify (or not) the records (autoSync in the store is false), and sync the store.

Doing this will corrupt the store's records.

The result that was expected:


Models are correctly synced through the store.

The result that occurs instead:


Models are correctly POSTed through the store's AJAX proxy, but after the sync they are corrupted.


Controller's code:

Pay no attention to possible inconsistencies of names, they are edited.



Ext.define(
'PL.controller.Plan',
{
extend: 'Ext.app.Controller',

stores: ['Hours'],
models: ['Hour'],
views: [
'planner.FooPanel', 'planner.DetailsWindow'
],

refs: [
// ...
],

init: function () {
this.control({
// [...]
'mainPanel #details': {
click: this.openDetailsWindow
},
'detailsWindow': {
destroy: function (win) {
this.getHoursStore().clearFilter();
win.editorGiorno.refresh();
}
},
'detailsWindow #save': {
click: function (button) {
// problem is here:
this.getHoursStore().sync();
button.up('window').close();
}
},
'detailsWindow #cancel': {
click: function (button) {
button.up('window').close();
}
}
});
},
// [...]

openDetailsWindow: function (button, event) {
// --- XXX
console.log('Hours: ');
var i = 0, store = this.getHoursStore(), hour = undefined;
for (i = 0; i < store.count(); i = i + 1) {
hour = store.getAt(i);
console.log(' - ', hour.get('month'), '/', hour
.get('dayOfMonth'), '/', hour.get('year'));
console.log(' -> ', hour, ' Dirty? ', hour.dirty);
}
// ----

this.getOrariFactStore().filter([
// [...]
]);
Ext.create('TS.view.planner.DetailsWindow', {
// ...
}).show();
},


Operating System:


Ubuntu Linux 11.04

mberrie
15 Sep 2011, 5:05 AM
You say that the corruption happens even when there is no write action triggered by the sync call (no modified records, no newly created records), and when there is *no* communication with the server resulting from the sync operation?

What happens if you don't trigger sync and only close the window?

I see that there are two stores involved (hours and OrariFactStore). Do they share data? Do you feed data from one store into the other? (Could you be affected by a problem similar to this one (http://www.sencha.com/forum/showthread.php?143612-Store-loadData-modifes-data-array-passed-into-the-method)?)


If it happens only when there is a write action to the server, it could be a problem with the data sent back from the server (Ext will update the model with data from the server to allow for server generated values (e.g. ID's)).

ManuelP
15 Sep 2011, 6:27 AM
You say that the corruption happens even when there is no write action triggered by the sync call (no modified records, no newly created records), and when there is *no* communication with the server resulting from the sync operation?

Actually, there is a POST even when I don't modify any filtered record. I don't know why. I simply filter the store, open a windows, show a grid binded to that store, and immediately close the window, syncing the store. More specifically: if the filtered store has n models, the sync will cause n POSTs, one for every model.


What happens if you don't trigger sync and only close the window?

If I only close the window all the records are fine.

Probably this is not important, but when there are corrupted records and I close and reopen the main panel (effectively reloading the incrimined store from the server) then it's all good.


I see that there are two stores involved (hours and OrariFactStore). Do they share data? Do you feed data from one store into the other? (Could you be affected by a problem similar to this one (http://www.sencha.com/forum/showthread.php?143612-Store-loadData-modifes-data-array-passed-into-the-method)?)

The two stores are in fact the same. Sorry about that, I've edited the source to make it more readable (I hope) but it seems I've missed some substitutions.

As for the problem you kindly suggested, I don't think this is the case. I don't use Store.loadData() in this controller.


If it happens only when there is a write action to the server, it could be a problem with the data sent back from the server (Ext will update the model with data from the server to allow for server generated values (e.g. ID's)).

Well, I have other areas of the application when I sync the same exact store and don't return anything from the server and they work just fine, no corrupted models. Just checked with firebug.

There are further details that may be relevant: basically every record of the store is passed and memorized in some array to permit some other elaborations. Since in JS objects are passed by reference, I thought this won't be a problem. Other interesting fact: inspecting stuff around, I see that after the sync new "corrupted" records are created (they have a different internalId than the original ones), but the originals are still present in the other array and correctly modified. But the total number of records in the store (as from Store.count()) is the same as before, so I assume in some way the original record is "disconnected" from its store (I see from firebug that this record has a reference to the store, but the store doesn't have that record in its items property).

mberrie
15 Sep 2011, 7:38 AM
There are further details that may be relevant: basically every record of the store is passed and memorized in some array to permit some other elaborations. Since in JS objects are passed by reference, I thought this won't be a problem.

Hm. Well as long as you don't modify properties of the model objects, that shouldn't affect anything.



Other interesting fact: inspecting stuff around, I see that after the sync new "corrupted" records are created (they have a different internalId than the original ones), but the originals are still present in the other array and correctly modified. But the total number of records in the store (as from Store.count()) is the same as before, so I assume in some way the original record is "disconnected" from its store (I see from firebug that this record has a reference to the store, but the store doesn't have that record in its items property).

I would try to isolate the problem and remove as much code as possible to make sure that nothing interferes.

Otherwise I can only advise to get out your debugger tools...

When debugging sync() consider that this will run asynchronously! That is most likely why your data is still fine immediately after the sync() method returns.


I would set breakpoints in:

AbstractStore#sync() - check what records have been modified/created/deleted.
Server#processResponse()

And to understand batch processing add


Batch#runOperation - set a breakpoint at the beginning and inside onProxyReturn (!)
Ext.data.proxy.Ajax#doRequest()

Also, monitor your network traffic closely and check what gets sent to the server and what will be returned.

Good luck! :D

ManuelP
16 Sep 2011, 12:50 AM
Thank you very much for your help, I'll try to figure it out (I'll post updates in this thread).

One last question before I dive into it: in the documentation I haven't found nothing about this (probably my fault):



[...] (Ext will update the model with data from the server to allow for server generated values (e.g. ID's)).

mberrie
16 Sep 2011, 1:23 AM
There are some things that you just pick up along the way. Maybe it is mentioned *somewhere* in the docs, maybe not ;)

Checkout Server.js#processResponse. The record is updated no matter if it was a read or write operation.



processResponse: function(success, operation, request, response, callback, scope){
var me = this,
reader,
result,
records,
length,
mc,
record,
i;

if (success === true) {
reader = me.getReader();
result = reader.read(me.extractResponseData(response));
records = result.records;
length = records.length;

if (result.success !== false) {
mc = Ext.create('Ext.util.MixedCollection', true, function(r) {return r.getId();});
mc.addAll(operation.records);
for (i = 0; i < length; i++) {
record = mc.get(records[i].getId());

if (record) {
record.beginEdit();
record.set(record.data);
record.endEdit(true);
}
}




If you can post a working example of the erroneous behavior I will have a look at it.

mberrie
20 Sep 2011, 9:00 PM
You might want to check out this thread (http://www.sencha.com/forum/showthread.php?147614-Grid-RowEditor-not-refreshing-after-Update&p=651173#post651173).

ManuelP
21 Sep 2011, 1:14 AM
You might want to check out this thread (http://www.sencha.com/forum/showthread.php?147614-Grid-RowEditor-not-refreshing-after-Update&p=651173#post651173).

Wow, this could certainly be the root cause. I'll investigate further the issue, thank you very much for the link!