Stopping multiple database access when user refreshes browser - java

Say we have a database query that takes 20seconds to run (the user runs it by clicking a button on HTML page in a browser).
The user gets impatient and only after 10seconds he refreshes his browser, only to run a new query.
How do I stop the first running database query (or prevent the second one from running)?
Thanks

First step would be to optimize that query, 20 seconds is way too long for most queries. Users won't generally tolerate that kind of poor performance.

If this is using Ajax, disable the
button that starts the query until
after the query is finished.
When the use makes the request, set a
flag in the user session, and then
start the query on a separate thread.
If they try to submit it again, check
the flag, and simply ignore the
request. When the query finishes,
reset the flag. While the query is
running, the browser can poll the
server waiting for the results.

I am not an expert, but you can store the time he last filed the query in his session. If the same user file another query with 20 secs, just ignore it.
It's not really a brute force way though.

Related

Android AsyncTask/Service killed before task complete

Synopsis: I need a way to start a task and have it persist through onDestroy() of app until it completes, or ability to pick up where it left off.
In my app, I have a ListView containing some items from a database. Hopefully only about 10-30 items, but potentially thousands (if the user never clears it, although I have prompts to clear it from time to time).
I have set up an AsyncTask to perform clearing the selected items from the list when the user wants to. However, I've noticed that the AsyncTask is killed when onDestroy() is called, for example if the user selects all items to delete, presses delete, then swipes app out of Recents while task is still performing.
I remember learning somewhere that a Service persists longer than an AsyncTask, so when the task gets killed I hand off the data to delete to a Service that I created. It does this by
intent.putIntegerArrayListExtra(list);
and get data from it in the Service. The Service persists far longer than the AsyncTask (only about 4-6 seconds), but still not all the way to completion. I know a little about START_XXXX flags, but that would be bad practice for this task, since they'd either send the whole list back to itself, or never really stop.
What is the preferred method to delete selected items from a database without it stopping when the app is killed, or at least to pick up where it leaves off?
Thanks all!
Your problem is very much like this: You have an application open in your favorite OS which is doing things in the background and then in the middle of it, the user force closes it. Logically, it will stop everything it's doing and stop executing and there's not much you can do to interrupt it.
There's no ideal solution to stop this from happening so what most people end up doing is to warn users that stopping the app when this operation is in process can have unwanted consequences.
In Android however, you have another option which is slightly more robust: you can write a persistent background service what continues running even if your app isn't running, but that still wouldn't solve the problem of what happens if the user switches off the phone when you're deleting from the DB? which would be the next logical question given your context. (personally, I would not recommend this approach for your task).
Best you can do is to maybe write a shared preference for every row you've not yet deleted (this will be the full list of rows you want to delete when you start deleting). For every row (or bunch of rows) you delete, change this preference to remove those rows from the preference and then if the app is interrupted, when you restart your app, read this preference and continue where you left off.
Alternatively, do what others do and warn users (by use of dialogs for instance) that they shouldn't stop the app until the delete is done otherwise bad things happen, etc.
I would strongly discourage you from using a service simply because it lasts longer than an AsyncTask. That's way too hacky and not at all reliable.

Is it possible to abort a long running query using iBATIS?

I have a GUI which allows users to run long running queries. Sometimes, the users regret running the queries and would like to cancel them. The queries are running using iBATIS against an Oracle database, and I know that the java.sql.Statement interface defines a cancel method that might or might not be implemented by the driver. So my question is, is it possible to use iBATIS to invoke this method to cancel the query (given the right driver), or is there any other way of aborting an ongoing long running query.
Well,
I guess that once the got to the DB server, cancelling it is really a "DB vendor specific" issue.
If your requirement is to cancel the query, when it comes to your application
(i.e - if it reaches the Oracle DB server, and is run there, you are fine, as long as you will not get the result), consider using the Future interface which has a cancel method.
You can submit a "Callable" to run your query, and it will return a proper object of type which is an implementation.
If you need to abort - just use the "cancel" method of the future object.
You can also check using "isCanceled" to see if submission was cancelled, and make proper treatment at your code.

locking DB records for concurrency between threads

This kind of thing has been done a million times I'm sure, but my search foo appears weak today, and I'd like to get opinions on what is generally considered the best way to accomplish this goal.
My application keeps track of sessions for online users in a system. Each session corresponds to a single record in a database. A session can be ended in one of two ways. Either a "stop" message is received, or the session can timeout. The former case is easy, it is handled in the message processing thread and everything is fine. The latter case is where the concern comes from.
In order to process timeouts, each record has an ending time column that is updated each time a message is received for that session. To make timeouts work, I have a thread that returns all records from the database whose endtime < NOW() (has an end time in the past), and goes through the processing to close those sessions. The problem here is that it's possible that I might receive a message for a session while the timeout thread is going through processing for the same session. I end up with a race between the timeout thread and message processing thread.
I could use a semaphore or the like and just prevent the message thread from processing while timeout is taking place as it only needs to run every 30 seconds or a minute. However, as the user table gets large this is going to run into some serious performance issues. What I think I would like is a way to know in the message thread that this record is currently being processed by the timeout thread. If I could achieve that I could either discard the message or wait for timeout thread to end but only in the case of conflicts now instead of always.
Currently my application uses JDBC directly. Would there be an easier/standard method for solving this issue if I used a framework such as Hibernate?
This is a great opportunity for all kinds of crazy bugs to occur, and some of the cures can cause performance issues.
The classic solution would be to use transactions (http://dev.mysql.com/doc/refman/5.0/en/commit.html). This allows you to guarantee the consistency of your data - but a long-running transaction on the database turns it into a huge bottleneck; if your "find timed-out sessions" code runs for a minute, the transaction may run for that entire period, effectively locking write access to the affected table(s). Most systems would not deal well with this.
My favoured solution for this kind of situation is to have a "state machine" for status; I like to implement this as a history table, but that does tend to lead to a rapidly growing database.
You define the states of a session as "initiated", "running", "timed-out - closing", "timed-out - closed", and "stopped by user" (for example).
You implement code which honours the state transition logic in whatever data access logic you've got. The pseudo code for your "clean-up" script might then be:
update all records whose endtime < now() and whose status is "running, set status = "timed-out - closing"
for each record whose status is "timed-out - closing"
do whatever other stuff you need to do
update that record to set status "timed-out - closed" where status = "timed-out - closing"
next record
All other attempts to modify the current state of the session record must check that the current status is valid for the attempted change.
For instance, the "manual" stop code should be something like this:
update sessions
set status = "stopped by user"
where session_id = xxxxx
and status = 'running'
If the auto-close routine has kicked off in the time between showing the user interface and the database code, the where clause won't match any records, so the rest of the code simply doesn't run.
For this to work, all code that modifies the session status must check its pre-conditions; the most maintainable way is to encode status and allowed transitions into a separate database table.
You could also write triggers to enforce this logic, though I'm normally not a fan of triggers - only do this if you have to.
I don't think this adds significant performance worries - but test and optimize. The majority of the extra work on the database is by adding extra "where" clauses to your update statements; assuming you have an index on status, it's unlikely to have a measurable impact.

How to implement a lock on data currently being viewed by a user

Morning gurus,
I am trying to implement a solution for allowing only one user of our web app be able to see the data they are interested in until they move away from the page.
So when a user clicks on the page they are presented with all the routes they have permission to see and no one else who has permission to see them is currently looking at.
I have partially implemented this by making an Application Scoped bean which stores a map of the routes being viewed by users keyed on their session id.
The Application Scoped bean is updated when the page's backing bean gets the routes from the database.
I have written a Filter which removes the viewed routes from the Application Scoped bean when the user leaves the page.
This all works fine :-)
But if the user leaves the page by either closing the browser tab / closing the browser or the session expiring my clean up code is bypassed.
Does anyone have suggestions how
I can get my clean up code to run before the tab/browser closes/session expires.
I can access the sessions for all users in my application scope bean (so I can iterate over them and build the watched routes map every time it is requested)
An idea of a better solution.
I'm working with JSF / Icefaces 2.
Thanks for your time.
First, and most importantly, you need to decide on the acceptable delay between a user closing the browser and releasing the locks on the held objects.
If you can handle having locks persist until the session is destroyed, add an HttpSessionListener and perform cleanup when the session is destroyed.
If you can handle delays in the 10s of seconds, add a periodic request on the web page (either via AJAX/JS, or via an invisible IFRAME that reloads a specific page from your server), and have a Filter that timestamps the last access from the browser in the users session or the Application Scpoed bean you already have. A separate thread wakes up every N seconds, scans for sessions with locked objects that are older than M seconds and unlocks them.
If you need immediate notification, install an onbeforeunload event handler that notifies the server. Also, you could do it with a persistent connection or WebSocket.
In any case, you will need at least one of the first two, because the third may be unreliable.
Use a cronjob or something which runs periodically and indentifies closed connections etc.; you can save the last action from each user and remove the lock if this times is greater than some time.
You could add a periodic (once a minute for example) AJAX call on your page, which keeps the lock alive.

java (jdbc, ms sql server) how to get an indication that my query was executed?

My application does queries to database (non-queries too).
I show to the user indeterminate progressbar while transaction.
The problem is that I don't know when to close the progressbar, because I have no indication or signal object of query completion.
If your queries are taking so long that you need a progress bar, I'd recommend taking a hard look at your database to see how you can speed them up.
Since a database operation blocks, you know it's done when you return.
The progress bar suggests that you need some kind of polling mechanism to check a metric that indicates how much you have to do and how many have been done. Since you don't give any details, I can only guess what those might be.
But an AJAX call in your JSP to poll and update the progress bar is most likely what you need.

Categories

Resources