在自定义 html 应用程序中处理并发集会会话



我有一个自定义html的拉力扑克应用程序,其中有一个团队成员屏幕和一个Scrum Master屏幕。我需要的是如何在团队成员使用此自定义 html 应用程序时控制他们的并发更新。截至今天,该应用程序仅从并发会话中最后提交的用户那里获取最新更新。它会覆盖其他所有数据。如果有人可以发布如何检查并发会话并停止覆盖并发会话中的用户输入的示例代码,那将非常有帮助。感谢您的帮助。

单击此处查看 Scrum 母版视图屏幕截图

@kyle - 我尝试添加您提到的版本 ID

谢谢凯尔。我确实尝试了一种繁琐的方法,通过重复提取代码来检查版本ID,但是在我的测试中,它证明版本ID没有为并发会话正确设置。我已经粘贴了具有版本ID检查的代码片段。您能否查看并让我知道是否需要添加任何内容。感谢您的帮助

Ext.create('Ext.window.Window', {
												                title: 'Planning Poker-Team Member view         UserStoryNumber : '+userstorynumber, height: 200, width: 400, layout: 'fit',
												                items: [
																	//*************** START PANEL FORM 1 *******************
																	Ext.create('Ext.form.Panel', {
																	    bodyPadding: 5, width: 350, url: 'save-form.php',
																		layout: { type: 'vbox', align: 'stretch', pack: 'start' },
																	    defaults: { anchor: '100%' },
																	    //Fields
																	    defaultType: 'textfield',
																	    
																	    items: [
																			{ fieldLabel: 'Estimate', name: 'Estimate', allowBlank: false, id: 'estimate' },
																			{ fieldLabel: 'Justification', name: 'Justification', allowBlank: false, id: 'justification' }
																	    ],
																	    // Reset and Submit buttons
																	    buttons: [
																			//{ text: 'Reset', handler: function () { this.up('form').getForm().reset(); } },
																			{
																			    text: 'Submit', formBind: true, disabled: true,
																			    handler: function () {
																			        //alert(f_newEstimate('name','points','role','justification'));
																			        var EstimateObject = getExistingEstimates(result);
																			        if (EstimateObject)
																			            console.log('Notes ************ ' + result.get('Notes'));
																			        console.log('Stringfy ************ ' + JSON.stringify(EstimateObject));
																			        //rec.set('PlanEstimate', estFinal);
																			        var jsonobj = f_newEstimate(name, Ext.getCmp('estimate').getValue(), role, Ext.getCmp('justification').getValue());
																			        console.log("json raw is", jsonobj);
																			        //console.log("json justi is", jsonobj.justification);
																			        console.log("PO note is", result.get('c_PONote'));
																			        //var existingPONote = result.get('c_PONote');
																			        //var newponote = existingPONote + ',' + jsonobj;
																		        var CurrentVersionID;
																			        var newVersionID;
																			        //Exp Karthik Starts
																			        var myStore = Ext.create('Rally.data.wsapi.Store', {
																			            model: 'User Story',
																			            autoLoad: true,                         // <----- Don't forget to set this to true! heh
																			            filters: [
                          {
                              property: 'ObjectID',
                              operator: '=',
                              value: objectId
                          }
																			            ],
																			            listeners: {
																			                load: function (myStore, myData, success) {
																			                    CurrentVersionID = myStore.data.items["0"].data.VersionId;
																			                    console.log("Version ID is", myStore.data.items["0"].data.VersionId);
																			                },
																			                scope: this                         // This tells the wsapi data store to forward pass along the app-level context into ALL listener functions
																			            },
																			            fetch: ['ObjectID', 'c_PONote', 'VersionId']   // Look in the WSAPI docs online to see all fields available!
																			        });
                               
																			        var existingPONote = result.get('c_PONote');
																			        var newponote = '';
																			        if (existingPONote.length == 0) {
																			            newponote = '[' + jsonobj + ']';
																			        }
																			        else {
																			            replacestr = ',' + jsonobj + ']';
																			            newponote = existingPONote.replace(']', replacestr);
																			        }
																			        rec.set('c_PONote', newponote);
																			          var myStore = Ext.create('Rally.data.wsapi.Store', {
																			            model: 'User Story',
																			            autoLoad: true,                         // <----- Don't forget to set this to true! heh
																			            filters: [
                          {
                              property: 'ObjectID',
                              operator: '=',
                              value: objectId
                          }
																			            ],
																			            listeners: {
																			                load: function (myStore, myData, success) {
																			                    newVersionID = myStore.data.items["0"].data.VersionId;
																			                    console.log("Version ID is", myStore.data.items["0"].data.VersionId);
																			                },
																			                scope: this                         // This tells the wsapi data store to forward pass along the app-level context into ALL listener functions
																			            },
																			            fetch: ['ObjectID', 'c_PONote', 'VersionId']   // Look in the WSAPI docs online to see all fields available!
																			        });
																		        if (CurrentVersionID == newVersionID) {
																			            rec.save();
																			        }
																			        else
																			        {
																			           
																			            var myStore = Ext.create('Rally.data.wsapi.Store', {
																			                model: 'User Story',
																			                autoLoad: true,                         // <----- Don't forget to set this to true! heh
																			                filters: [
                              {
                                  property: 'ObjectID',
                                  operator: '=',
                                  value: objectId
                              }
																			                ],
																			                listeners: {
																			                    load: function (myStore, myData, success) {
																			                        newVersionID = myStore.data.items["0"].data.VersionId;
																			                        console.log("Version ID is", myStore.data.items["0"].data.VersionId);
																			                    },
																			                    scope: this                         // This tells the wsapi data store to forward pass along the app-level context into ALL listener functions
																			                },
																			                fetch: ['ObjectID', 'c_PONote', 'VersionId']   // Look in the WSAPI docs online to see all fields available!
																			            });
																			           
																			            var existingPONote = myStore.data.items["0"].data.c_PONote;
																			            var newponote = '';
																			            if (existingPONote.length == 0) {
																			                newponote = '[' + jsonobj + ']';
																			            }
																			            else {
																			                replacestr = ',' + jsonobj + ']';
																			                newponote = existingPONote.replace(']', replacestr);
																			            }
																			            rec.set('c_PONote', newponote);
																			            console.log("Concurrent versions saved", newponote);
																			            rec.save();
																			        }
																			       
																			        console.log('Submit Success1');
																			        this.up('window').close();
																			    }
																			}]

WSAPI 中的所有对象都包含一个 VersionId 字段,每次更新对象时,该字段都会在服务器上自动递增。 产品处理并发问题的方式是始终获取此 VersionId 字段。 然后,用户可以在本地进行更新。 当用户保存时,首先会再次阅读故事。 如果 VersionId 与首次读取时相同,则可以安全地发送更新。 但是,如果该版本ID更高,则意味着其他用户在此期间更新了故事。

如果发生冲突,您可以将本地更改合并到新读取的对象中,然后再次尝试保存。 您可以根据需要重复此操作,直到用户能够执行干净保存。

最新更新