Saving data instantly, onClose, save button? Which is better in this situation - google-app-engine

In my GWT application, I have been saving everything that the user does instantly to the datastore in the background whenever they make changes. So far this has been fine because the things that the user can change aren't being changed a whole lot.
But now I have added a series of check boxes that the user can check & uncheck:
Would it be proper to save everything instantly to the database everytime the user checks/unchecks a box? The thing that's on my mind is reducing the amount of times my web application has to go to the server to save data. Facebook, Google, (and many many others) use a "Save" button whenever a user makes changes to a large amount of fields (say, to their user information).
I am trying to stay away from having a Save button, and so the thought came to mind about saving these values whenever the user closed or refreshed the page. I don't know if that's proper either (what if there is a loss of power, and their system shuts down!), but I know that I could use it like this:
public void onClose(CloseEvent<Window> event) {
//save changes to the datastore
}
I'm torn between the three methods and don't know which path to take! Any information will be helpful
Thank you!

Your current system follows a really excellent design pattern which a lot of apps (web- and otherwise) are picking up lately: Eliminate the manual operation of 'saving'. I think you should stick with it.
That said, if you want to reduce the number of round-trips and server load, you can do a couple of things: You could restrict the number of saves-in-progress to one, so that if the user makes a change while you're waiting for a 'save' request to complete, you wait until that request completes before sending a new one. Or, you could start a timer when the user makes a change, and commit any changes when the timer expires - this is pretty much how GMail's auto-save of draft messages works.
Either way, don't rely on a close event to trigger sending state to the server: If the user's browser crashes, the close event won't fire and they'll lose all their changes.

Related

Dealing with server stranded file uploads

I have an Angular SPA app running on Azure and I'd like to implement a rich text editor similar to Medium.com. I'll be using some existing editor for this, but I have a problem with image files.
The problem
I would like my editor to have the ability to also add images inside content. The problem I'm having is when should I be uploading images to the server?
Possible solution 1: Immediate upload after they're selected
The good
saving content is quicker because all images are likely already uploaded
files get displayed right after they're uploaded from the server URL
The bad
files may have to be deleted on the server if users selects to cancel editing
files may get stranded on the server if user simply closes their browser window
Possible solution 2: Upload after save
The good
files get displayed immediately using FileAPI capabilities
no stranded server side files if editing is discarded in whatever way
The bad
saving of content may take longer as all images need to be uploaded at the moment of saving content
additional client-side to display images from local files
Question
I would like to implement Solution 1 because it provides more transparent user interface process and reacts quicker to edit saves => better UX. But how should I be managing stranded files? I could use a worker process that would delete stranded files from time to time, but I wonder whether that's the best approach for this scenario.
What and how would you suggest I implement this?
This is highly subjective (opinion based), but I will give it a shot.
You are actually having bigger problem than you think. In your abstracted approaches, you only describe a situation when user started something as new. Whereas I see much harder to solve issues if user is editing existing item. What will happen if he/she deletes images, adds new images and at the end hits CANCEL. And also, if Internet connection drops while creating / editing?
I would also go for Solution one. And, of course minimize the "bad" things, as they aren't really that much or hard to handle. Here is how I would solve all the "bad"s in Approach 1:
All my articles (or whatever user is editing with editor) will have a boolean flag "IsDraft" or something like this. Then all my business logic for front end will only look for items where IsDraft == False.
Whenever a user starts a new article (the easiest to solve problem) I immediately create new item in my DB with IsDraft=True
Have a link table to keep link between ID of item being created and Image Files being used (blobs). The point here is, that, if you do not keep links between used and unused blobs, you will have a lot headaches deciding which blob to delete and which one to leave on the storage.
Have a worker process (either as worker process in Web Role if I use Cloud Services, or as a Web Job (+ nice and short explanation here) is I use Web Sites) that checks for articles that are Draft and older than XXX days. If found - delete files + article itself.
Handling Editing of existing item is more challenging - for this, I might take the approach of:
Create a new copy of the entire article when user hits Edit and mark it as draft
If user hits save - switch the content of the new article (new version) with the existing one, leaving the new article marked as IsDraft - the worker process will clean it up.
If user doesn't hit save for some reason (hit cancel, or internet drops, or computer restarts, or browser crashes, or or or ..) - the new article will be cleaned later by the worker process
And if you want to go deeper and crazier, you can have a section in your admin panel where you show the Drafts to your users, so they can either continue work, or leave it to be auto cleaned.

Multi-user support with nhibernate winforms application

I’m working on a multi-user winforms application (MDI). Our application uses NHibernate and one session per instance.
The problem is if an user makes modification, for example a user adds an item to a list, another user doesn’t see this modification immediately. How do I get around this, what is the recommended approach? Should I be using One-session-per-form or something else?
Every application needs to define it's own unit of work. For your use case, if you are wanting the database to update every time a user adds an item to a list, then that should be your unit of work.
So to answer your question for your unique use case, I would create a new NHibernate session, persist the users changes, and dispose of the session every time a user adds an item to the list.
FYI: You should not feel that there is anything wrong with creating a session per user action if that is indeed the behavior your application desires. Typically in a WinForms application, most people do use a Session-per-Form pattern but then again, that is because most WinForms applications fall into the model of having a form that the user needs to complete before proceeding to the next form. In those cases, you would only want to persist/save the user's changes when they submit the form. But if you application does not fall into that model, then your definition of a unit of work ( session life-cycle ) could be completely different.

Inaccessible database

I'm working on an rather small application (C#, winform) that is kind of front-end to MS Access database file stored on shared drive. While it is possible that drive could be down I am checking connection while loading Main Form.
I would like to know your opinions on how to deal with this problem.
I came up with ideas like:
Application shows only MessageBox
with an error message and close
itself (before actually showing up),
as it won't be useful at all.
Application load itself and then
display an error-message to not make
users confused (if they click warning
before reading the explanation).
What are yours best practices?
I think it's rather irrelevant whether the application is shown or not because in the end, you display the message box with the error anyway. The user clicks OK and you close your Application.
However, to me it's a bit nicer without the application showing in background, mainly because it makes no sense to fire it up when the database isn't available. Save yourself (and the pc) the time it takes to show it ;)

Silverlight stop page closing before being saved

In the old days for WinForms, if your user was creating/editing some information in a DialogBox, it was easy to detect the Window closing and if the data was dirty, ask if they wanted to save.
My question is, how do you approach this scenario in Silverlight where everything seems to be done in UserControls, which have no obvious way of knowing when the page is closing, ie switching to another page within the Silverlight app would simply open a different UserControl without checking the previous UserControl needed saving.
There must be some standard way of achieving this?
If you need to ask the user a question about whether to save or not then you will need to handle this in the browser the onbeforeunload (whilst not a standard event it is supported by those browsers on which Silverlight is officially supported). It may be possible to set up a little javascript to call back into your application when onbeforeunload fires.
That said I'm not a fan of the "Are you sure, you want to lose all that work you've just done" type of question. "Of course I don't want lose it, save it already, as long as I can undo it later if necessary I'm happy".
You can handle the Application.Exit event to execute code on application shut down. Be warned that at this time the networking stack has already shut down so you can't send any messages from the Application.Exit. You cannot cancel the event.
+1 Michael. It is a current limitation of SL. You can however persist to isolated storage from the app exit event, would it be feasible in your app to check if dirty, and if so save to iso storage. Then next time your app loads you could load the dirty data from iso storage ready to carry on editing..?

Best practice for updating silverlight deployment that is actively being used

I am currently running a SL3 project where we are in a highly iterative development mode with about 25 active test customers. I am making small changes at a clip of about 4 new builds per day. It is important to know this application is mission critical line of business for these 25 people, it is the tool they use all day to do their work so they are using it constantly and often launch their browser and the app in the morning and never close it until the end of the day.
The challenge is that when I make an update to the application I have no clean way to notify the users, in most cases this is ok as it is rare that I introduce a data contract change or something that would be a classic 'breaking' change to the app/service. Users keep plugging along and will get the change next time they refresh.
Right now we have resorted to emailing everyone and telling them to force refresh or close the browser and log back in.
Surely there is a better way...
Right now my train of thought is to have a method on the server that compares client xap versions and determines if the client being used is the most up to date, if so I will notify the user and make them update.
What have you done to solve this problem?
One way of doing it is to use a push mechanism (I used Kaazing Websoocket Gateway but any would do). When a new version of the XAP is released a message (either manually entered into the system by admin or automated triggered by XAP file change event) would be sent to all the clients. In the simplest scenario some notification would be shown to a user (telling him that a new version is released and the application needs to refresh) and then the app would refresh (by simply reloading the page) saving user's state if necessary.
If I would do this I would just keep it simple. A configuration value in web.config and a corresponding service method that simply returns that value (the value itself could be anything, but a counter is probably wise). Then you could have your Silverlight app poll that service method at regular intervals. Whenever the value changes (which you would do manually when you deploy a new version), just pop up a dialog telling the user to refresh the browser or log in/out. This way you don't have to force them to refresh every time. If you go with the idea of comparing xap file versions they will always be required to refresh, even for non-breaking changes.
If you want to take it further you could come up with some sort of mechanism to distinguish between different severity levels. For instance, if the new config value would contain the string "update_forced", you could force the users to reload the app by logging them out automatically (a little harsh, perhaps). If it contains the string "update_recommended", just show a little icon at the top right corner saying that there is a new version and that they should upgrade in their own time.
Granted, this was targeted at Silverlight 3, but with the PollingDuplex client and such in the newer versions of Silverlight, you could publish an "Update Now" bit to the clients, and build a mechanism in the client to alert the user that there is an update that is now out... that they should update it shortly, etc. You may even be able, through serialization and such, to save the state that they are in when they close the app to reload it.
We've done stuff similar with a LOB app that we built, so that as users are changing things, the rest of the userbase sees those changes immediately. Next up will be putting the flags in to change authorization and upgrades "on the fly" if you will.

Resources