I have a problem with my current implementation of real time with Angular and Socket.io.
I have a model in Angular and I watch it for modification with $scope.$watch().
When I detect a modification I send a message with socket to my server.
When my server detect a call on this update, I save the modification and I send to other user the modification
Other users are notified about someone modification.
But, I have a problem with this implementation :
User A update a field
Send message to server
Save to the server
Update notification send to users
User B is notified
User B model is updated
The watch detect a modification in model of User B and send notification
Send message to server
Save to the server
etc...
So, my question is, how to avoid this infinite loop and infinite update ?
You could define on the client side a variable named changed_elsewhere. The default value of changed_elsewhere it's false.
When you receive on your socket a new value from the server, then set changed_elsewhere to true. Then, on the watcher, send the new changed value to the server only if changed_elsewhere is false. If changed_elsewhere is true, then you know that the value has already been on the server and you don't need to send it again.
Finally, your watcher should look this way: if changed_elsewhere is true, then turn changed_elsewhere to false and don't do nothing; if changed_elsewhere is false, then send the new value to the server.
Sorry if the changed_elsewhere name is not very suggestive, but i hope that you get my idea.
Why not create two models? one that is synced from the server and one that is watched for changes. Instead of adding them directly to the controller's scope you create a service which presents it to the controller as one model but behind the scenes it manages the differences?
Related
I use QSqlRelationalTableModel to extract data from database, and use tableView to show it. Now, when I update my database, how to update tableView automatically to show it? I know i need to use function dataChanged() to make this automatically, but i do not know how to use it? Any suggestion will be appreciated.
The main code is as follows:
QSqlRelationalTableModel *model = new QSqlRelationalTableModel(NULL, db);
model->setTable(tableName);
model->select();
tableView->setModel(model);
tableView->show();
No, there is no need to use dataChanged().
You just need to call QSqlRelationalTableModel::select() whenever the database gets updated. This will re-populate the model from the database, and update the views that are using it automatically.
If the database is updated from within you application, you can just call model->select() after the update queries get executed in your application.
If the database is updated from another application, you'll have to use something like PostgreSQL's event notification system, subscribe to the notification from your application using QSqlDriver::subscribeToNotification() and call model->select() in a slot connected to the notification() signal.
You can use QSqlDriver::hasFeature(QSqlDriver::EventNotifications) to check if notifications from your database are supported.
I have instance of operation entity. I'd like to execute it after some row was successfully deleted from store (ui has been gotten OK response from server).
1st Issue. How determine that row was deleted on server and execute some logic after it.
There are no callbacks for store.remove/removeAt. And it seams (from debugging) that listening 'remove' event on store is not option.
2nd Issue. It's possible just to call execute() on operation instance. But how to get know view and even store about this operation. Because simple operation.execute() does not give any effect except request to back-end.
Solution to 1st issue:
store.suspendAutoSync();
store.removeAt(this.rowIndex);
this.getView().getStore().sync({
success:function(){
...
},
failure:function(){
...
}
});
i working with angularjs, and my web receive data from websocket each second, and now i using a $scope.$apply for refresh every time I get a fact, the problem is when my server send More information than usual the web page is very slow, and if i comment the $scope.$apply the web run fine.
I have something like this
$scope.ChangeData=function(str){
//process.... take around 1ms
//here i change a variable, with new info
$scope.$apply();
//here the process print 60-100ms
}
then i want to do it,
$scope.ChangeData=function(str){
//process.... take around 1ms
//here i change a variable, with new info
angular.element(document.getElementById(str.ID)).scope().$apply
//I do this, I hope the process will only take a few ms
//beacuse i change only the changed element
}
but i have a error in this part
Cannot read property '$apply' of undefined
please help me..
UPDATE
Example in plnkr
Without fully understanding the context of your application, I can only guess that this is a messaging type application. This assumption is based on the fact that a) you're using a socket server to push updates to existing data on the UI and b) you're attempting to maintain existing UI already present.
I took your plunkr and forked it with how I would approach this problem. There are 2 things to realize:
the ItemsController is dumbed down so that it only consumes a model coming from a service and the simulated push to update to said model
the itemsService facilitates
storing the messages data
handles the push update
Because the ng-repeat is already charged with watching any changes in its target collection, you shouldn't have to do any of the $scope.$apply or angular.element stuff you were doing. Each item in the ng-repeat will update the DOM for you. That's its purpose.
https://plnkr.co/edit/qLeDuP0iaTUE16rY2KTl?p=preview
I want to listen change in my legacy system whenever there is any change in SF object (add/update/delete). So I have created outbound message and workflow. But in workflow I don't see any way to fire if object is deleted.
Is there anyway I can trigger outbound message on record delete? I know have heard that it can be done by trigger. But I don't want to write apex code for this.
To the best of my knowledge it cannot be done, the workflow actions are decoupled from the workflow rule (you can even reuse them) so they probably do not receive the transaction scope and when they execute the record is already gone and any reference inside action would point to a non-existing data. Thus the only way I know how to do it is via trigger.
Here is a workaround. However this will only be able to capture deletion made via std. Salesforce UI.
1.Create a custom checkbox field "Is Deleted"
2.Override the Del link with a custom VF page, that first updates the record status to "Is Deleted", and deletes the record.
3.Write workflow rule using the "Is Deleted" field.
Perhaps a compromise architecture would be to write an extremely small and simple after delete trigger that simply copies the deleted records in question to some new custom object. That new custom object fires your workflow rule and thus sends the outbound message you're looking for. The only issue with this would be to periodically clean up your custom object data that would grow in size as you deleted records from your other object. In other words, your "scratch" object would just need periodic cleaning - which could be done on a nightly schedule with batch Apex.
Here's a delete trigger that would do the trick using Opportunity as an example:
trigger AfterDelete on Opportunity (after delete)
{
List<CustObj__c> co = new List<CustObj__c>();
for(Opportunity o : Trigger.old)
{
CustObj__c c = new CustObj__c();
c.Name = o.Name;
c.Amount__c = o.Amount;
c.CloseDate__c = o.CloseDate;
c.Description__c = o.Description;
// etc.
co.add(c);
}
insert co;
}
It's not ideal but at least this would save you from having to code your own trigger-based outbound messages. These can only be done using the #Future annotation, btw, since callouts directly from triggers are forbidden. Hope that helps.
write a single email send in the trigger delete event. You have it in less than 1 hour.
this is probably only some conceptual problem, but I cannot seem to find the ideal solution.
I'd like to create a Silverlight client application that uses WCF to control a third party application via some self written webservice. If there is more than one Silverlight client, all clients should be synchronized, i.e. parameter changes from one client should be propagated to all clients.
I set up a very simple Silverlight GUI that manipulates parameters which are passed to the server (class inherits INotifyPropertyChanged):
public double Height
{
get { return frameworkElement.Height; }
set
{
if (frameworkElement.Height != value)
{
frameworkElement.Height = value;
OnPropertyChanged("Height", value);
}
}
}
OnPropertyChanged is responsible for transferring data. The WCF service (duplex net.tcp) maintains a list of all clients and as soon as it receives a data packet (XElement with parameter change description) it forwards this very packet to all clients but the one the packet was received from.
The client receives the package, but now I'm not sure, what's the best way to set the property internally. If I use "Height" (see above) a new change message would be generated and sent to all other clients a.s.o.
Maybe I could use the data field (frameworkElement.Height) itself or a function - but I'm not sure whether there would arise problems with data binding later on. Also I don't want to simply copy parts of the code properties, to prevent bugs with redundant code.
So what would you recommend?
Thanks!
One common solution here is to use a boolean to track your current state within OnPropertyChanged. It can be set to true when a WCF packet is received, and if it's true, you don't rebroadcast. You then set it to false after setting the property.
When you set the property normally, you'd just leave it false. This will cause it to broadcast normally when set internally, but not when set via the WCF call.
This option works, but it does require care to get right. Since you're putting this logic into a single point, it should be fairly straightforward to get correct.