SignalR and one browser window for a session at a time - concurrency

I have a situation where a user can modify an Excel like grid schedule online. I would like to be able to show a message stating that the schedule is being modified in another window. However, how can I do this with a window open, and if the previous window was closed with SignalR. For other sessions I just want to state another user is modifying the schedule.

It might be easiest to use localStorage to communicate between multiple tabs/windows a single user has open: http://www.codediesel.com/javascript/sharing-messages-and-data-across-windows-using-localstorage/
You can listen for the storage event which is triggered on every window a user has open on your site when you call localStorage.setItem or localStorage.removeItem.
Of course, it would still make sense to use SignalR to notify other users.
If you cannot use the localStorage API for some reason, you can still use SignalR to send a message to every window the user has open by using Clients.User(userName).... inside your Hub. By default, userName should match your user's IPrincipal.Identity.Name, but you can register your own IUserIdProvider to customize this: http://www.asp.net/signalr/overview/signalr-20/hubs-api/mapping-users-to-connections#IUserIdProvider

Related

How to send a "you haven't used your app in a while " push notification in React Native using AWS?

Just wanted to know from a high level how I would accomplish this.
I thought that when a user opens the application, I will keep track of the last opened time in a Dynamo DB table.
Then I could have a background worker constantly check and see if anybody hasn't used their app in 3 or 4 days and then send a push notification, ie, "you haven't used your app in a while, why don't you open it up and do XYZ."
From a very high level, there are two possible ways:
1.) Local notifications (you don't need AWS for this):
You can schedule a local notification, every time the user opens up the app (or better - every time the user brings the app to foreground). It works like: User opens app -> cancel old scheduled notification if existing -> schedule new notification for "in 3 or 4 days" -> ready :-)
You can use something like this: https://github.com/zo0r/react-native-push-notification (see section Sheduled Notifications).
2.) You could do it with remote notifications (https://aws.amazon.com/sns/):
You can go the way you proposed. Then you have to store an entry in your db with the push notification token of the device and the last time the app was opened. Your worker then has to check and send the push message to the device using a service like SNS.
I would recommend 1.) over 2.) because you are independent from the users internet connection when getting the app opening info. In 2.) you can miss the opening info, when the user opens the app without internet connection. Also 2.) is more expensive then 1.) when you scale your app.
An advantage of 2.) would be, that you are more flexible when and what you send in your notification, since you can edit it on server side. 1.) would mean that it is coded in your app (at least until you build a synchronization mechanism for the variables) :-)

Google Admin SDK user push notifications and renaming of users

I want to ask about the situation that is related to the renaming of a user by an administrator. It can take up to 10 minutes (from the disclaimer) to get user's name changed, but the notification about update event is sent immediately. There is no way to understand whether user's data is changed or not at the moment when notification is received. The only way to process it correctly is to delay processing by 10 minutes which is not good for me.
Is there something that I've missed to handle this? Otherwise it is quite useless API.

Block GUI when waiting for QTcpSocket data

I am writing a program to interact with a network-based API using Qt.
The interaction with the API is made with XML messages (both queries and results)
I implemented the communication and data processing in a class in a shared library project and I have a QMainWindow in which the user can enter the connection details. When clicking on the connect button, the following should happen:
1. An instance of the connecting class is created.
2. A connection message is sent to the API to get the session ID. The answer is parsed and a session ID is stored in the class instance.
3. A message is sent to the API the get some field information. The XML is then parsed to extract the required field information to get data from the API.
4. Another message is sent to get the data matching the fields. The XML answer is then parsed and stored in a data structure for processing.
5. The data is then processed and finally displayed to the user.
I made a simple console program to test the library and it is working fine - no message is sent before all the data from the previous message has been processed. However, when I implement the same process in a QMainWindow instance, no wait occurs and messages are sent one after another without waiting.
How can I block the GUI thread to wait for full processing before sending the next message?
Thanks
Blocking the UI isn't achieved by blocking the event loop. It's done by disabling the widgets that you don't want to allow interaction with - either by literally calling disable() method on them, or by guarding the interaction based on some state variable, e.g.:
connect(button, &QPushButton::clicked, button, [this]{
if (! hasAllData) return;
// react to a button press
});
All you need is to define a set of states your application can be in, and disable relevant widgets in appropriate states. I presume that once the session is established, it'd be fastest to issue all queries in parallel anyway, and asynchronously update the UI as the replies come back in real time.

Periodic tasks in Django/Celery - How to notify the user on screen?

I have now succesfully setup Django-celery to check after my existing tasks to remind the user by email when the task is due:
#periodic_task(run_every=datetime.timedelta(minutes=1))
def check_for_tasks():
tasks = mdls.Task.objects.all()
now = datetime.datetime.utcnow().replace(tzinfo=utc,second=00, microsecond=00)
for task in tasks:
if task.reminder_date_time == now:
sendmail(...)
So far so good, however what if I wanted to also display a popup to the user as a reminder?
Twitter bootstrap allows creating popups and displaying them from javascript:
$(this).modal('show');
The problem is though, how can a celery worker daemon run this javascript on the user's browser? Maybe I am going a complete wrong way and this is not possible at all. Therefore the question remains can a cronjob on celery ever be used to achieve a ui notification on the browser?
Well, you can't use the Django messages framework, because the task has no way to access the user's request, and you can't pass request objects to the workers neither, because they're unpickable.
But you could definitely use something like django-notifications. You could create notifications in your task and attach them to the user in question. Then, you could retrieve those messages from your view and handle them in your templates to your liking. The user would see the notification on their next request (or you could use AJAX polling for real-time-ish notifications or HTML5 websockets for real real-time [see django-websocket]).
Yes it is possible but it is not easy. Ways to do/emulate server to client communication:
polling
The most trivial approach would be polling the server from javascript. Your celery task could create rows in your database that can be fetched by a url like /updates which checks for new updates, marks the rows as read and returns them.
long polling
Often referred to as comet. The client does a request to the server which pends until the server decides to return something. See django-comet for example.
websocket
To enable true server to client communication you need an open connection from the client to the server. django-socketio and django-websocket are examples of reusable apps that make this possible.
My advice judging by your question's context: either do some basic polling or stick with the emails.

Gracefully terminate a request based service on server

In our web application, for each http-request there is a lot of computation that happens on back end. Output can vary from 10 sec - 1 Hour. In the mean time when it is computed, "Waiting.." is shown on the website for the respective user.
But it so happens, that a user might cut down the service in between. So what all can be done on the back end so that the computation can be stopped in between to save resources? What different tactics can be applied here?
And if better (instead of killing the thread directly), then a graceful termination policy should make wonders.
I'm not sure if this fits your scenario but here is how I have tackled this issue in the past. We were generating pdf reports for a web-app. Most reports could be generated in under 5 seconds but some would take up to an hour.
When the User clicks on generate button we redirect them to a "Generating..." dialog screen which has a sort of progress bar and a Cancel button. This also launches the generate process on the server in a separate thread (we have a worker pool). The browser then polls the server regularly via ajax to check on the progress (either update the progress bar or redirect to the display page when finished).
The synchronization at the server between the generating process and the ajax process was done via a process synchronization object. The sync-obj was a very simple class instance which could be retrieved quickly from any thread at any time via some unique string.
Both processes could update this shared sync-obj. As the report generated the repgen thread would update the sync-obj which the ajax thread would inform the browser. If the User clicked the Cancel button then the ajax thread would set the "cancel" flag in the sync-ob and the repgen thread would pick that up and break out of the generate loop.
Clearly the responsiveness of the whole process depends a lot on how frequently the repgen thread checks the sync-obj and that often comes down to how the individual report was coded.
Finally, to answer your question, if the User gets bored and goes "back" and clicks the generate button again we do not cancel the first report and start a second but rather realise that it is the same report (and the same sync-obj id) and so just let the report continue. However if that does not suit your scenario then starting a generate process could cancel the first in the same manner that the User could via the Cancel button.