support icon indicating copy to clipboard operation
support copied to clipboard

CRUD manager loses changes when applying sync response

Open bmblb opened this issue 2 years ago • 7 comments

Reproducible on scheduler pro using this source:

import '../_shared/shared.js'; // not required, our example styling etc.
import '../../lib/Scheduler/column/ResourceInfoColumn.js';
import SchedulerPro from '../../lib/SchedulerPro/view/SchedulerPro.js';

import AjaxHelper from '../../lib/Core/helper/AjaxHelper.js';

const resources = [
    { id : 'r6', name : 'Gloria', company : 'Small rocket co' }
];

AjaxHelper.mockUrl('load', {
    responseText : JSON.stringify({
        success   : true,
        resources : { rows : resources }
    })
});

let count = 1000;

AjaxHelper.mockUrl('sync', function(url, params, options) {
    const body = JSON.parse(options.body);

    console.log(body);

    if (body.events.added) {
        body.events.added.forEach(added => {
            added.id = count++;
        });
    }

    return {
        responseText : JSON.stringify({
            success : true,
            events  : {
                rows : [
                    ...(body.events?.added || []),
                    ...(body.events?.updated || [])
                ],
                removed : [...(body.events?.removed || [])]
            }
        }),
        delay : 200
    };
});

const schedulerPro = new SchedulerPro({
    appendTo          : 'container',
    resourceImagePath : '../_shared/images/users/',

    features : {
        eventTooltip : true
    },

    columns : [
        { type : 'resourceInfo', text : 'L{Name}', width : 150 },
        { text : 'L{Company}', field : 'company', width : 150 }
    ],

    project : {
        loadUrl  : 'load',
        syncUrl  : 'sync',
        autoLoad : true,
        autoSync : true
    },

    startDate  : new Date(2017, 0, 1, 6),
    endDate    : new Date(2017, 0, 1, 20),
    viewPreset : 'hourAndDay'
});

window.run = function() {
    let counter = 1;

    const interval = setInterval(() => {
        schedulerPro.eventStore.add({ name : `Child ${counter++}`, duration : 1, startDate : '2017-01-01', resourceId : 'r6' });

        console.log('added event ' + counter);

        if (counter > 10) {
            clearInterval(interval);
        }
    }, 100);
};

Open the demo and launch run() method. You will see sync requests logged to the console and you could notice they only contain 6 changes combined. There should be 10 records.

image

Changes are likely lost when applying sync response to a modified project. We should either postponse sync until there are none made within an autoSyncTimeout interval, or preserve changes when applying a changeset,

bmblb avatar Jan 15 '24 14:01 bmblb

Client reverted to 5.5.4 because apparently problem is not reproducible there. Or, more likely, less noticeable

bmblb avatar Jan 16 '24 12:01 bmblb

Apparently this is still an issue:

One of the case we have encountered where changes are not synched is this: User attempts to update a task record name field which initiated a sync call from bryntum. While the sync call of task record name update is still in progress.... user attempts to update the description field of the task record. Once the task name field update network call is resolved the description update call is never be made hence the description remained unsaved. We have test this issue by applying the network throttling to slow 3G in the browser network tab. There is also a similar issue which is resolved as well https://github.com/bryntum/support/issues/8263 but still facing the similar issue on the task record update. I have tested the behaviour in bryntum version 6.0.3 (edited)

bmblb avatar Aug 05 '24 13:08 bmblb

Record's creation is in progress however when updating record's address that network request is not being initiated.

import { Store, Model, AjaxHelper, ProjectModel, } from '../../build/schedulerpro.module.js?478494';

class Client extends Model {
    static get $name() {
        return "Client"
    }

    static get fields() {
        return [
            "name",
            "address"
        ]
    }
}

AjaxHelper.mockUrl('load', {
    responseText : JSON.stringify({
        success   : true,
        resources : { rows : [] }
    })
});

let count = 1000;

AjaxHelper.mockUrl('sync', function(url, params, options) {
    const body = JSON.parse(options.body);
    console.log(body);
     if (body.clients.added) {
        body.clients.added.forEach(added => {
            added.id = count++;
        });
    }

    const response = {
            success : true,
            clients  : {
                rows : [
                    ...(body.clients?.added || []),
                    ...(body.clients?.updated || [])
                ],
                removed : [...(body.clients?.removed || [])]
            }
        }
    console.log("response", response)
    return {
        responseText : JSON.stringify(response),
        delay : 2000
    };
});

const clientStore = new Store({
    id: "clients",
    modelClass: Client
})

const project = new ProjectModel({
    autoLoad: true,
    loadUrl: "load",
    syncUrl: "sync",
    autoSync: true,
    crudStores: [
        clientStore
    ]
})
window.project= project;
console.log("project", project);

bmblb avatar Aug 05 '24 14:08 bmblb

image

canonic-epicure avatar Aug 06 '24 06:08 canonic-epicure

Hi @matsbryntse and @canonic-epicure,

We are still encountering issues with crudManager in version 6.0.5. We've identified the following two scenarios where crudManager loses changes:

  1. When a record is added to the store and then updated, the update network call is never triggered. image
  2. When a project is loaded and a record is already in the store, the initial update to that record triggers a network request. However, any further updates to the same record do not trigger additional network requests. image

Code Snippet:

import { Store, Model, AjaxHelper, ProjectModel } from '../../build/schedulerpro.module.js?479193';
import shared from '../_shared/shared.module.js?479193';


class Client extends Model {
    static get $name() {
        return "Client"
    }

    static get fields() {
        return [
            "name",
            "address"
        ]
    }
}

AjaxHelper.mockUrl('load', {
    responseText : JSON.stringify({
        success   : true,
        clients : { rows : [{ id: 1, name: "Faisal", address: "" }] }
    }) 
});

let count = 1000;

AjaxHelper.mockUrl('sync', function(url, params, options) {
    const body = JSON.parse(options.body);
    console.log(body);
     if (body.clients.added) {
        body.clients.added.forEach(added => {
            added.id = count++;
        });  
    }

    const response = { 
            success : true,
            clients  : {
                rows : [
                    ...(body.clients?.added || []),
                    ...(body.clients?.updated || [])
                ],
                removed : [...(body.clients?.removed || [])]
            }
        }
    console.log("response", response)
    return {
        responseText : JSON.stringify(response),
        delay : 2000
    };
});

const clientStore = new Store({
    id: "clients",
    modelClass: Client
})

const project = new ProjectModel({
    autoLoad: true,
    loadUrl: "load",
    syncUrl: "sync",
    autoSync: true,
    crudStores: [
        clientStore
    ]
})
window.project= project;

Note: Data must be loaded into the store(clientStore) in the load network request.

muhammad-faisal101 avatar Sep 04 '24 15:09 muhammad-faisal101

Confirmed, problem still exists

bmblb avatar Sep 09 '24 13:09 bmblb

+1

atremel avatar Sep 17 '24 09:09 atremel