Jeroen T. Vermeulen wrote:
> On Sun, August 12, 2007 14:39, Bart Samwel wrote:
> 
>> ...but generally intended to be a precise one if the user doesn't
>> manually cancel what he's waiting for. So timeouts are generally not the
>> thing. Think of loading web pages: there's a network timeout of several
>> minutes, but there's also a "stop" button. I would be very annoyed if I
>> would replace this with only a timeout, but not with only a stop button.
> 
> But if there's an application running behind the web page, and a query
> inside that application is taking too long, then at some point the
> application must conclude that:
> 
> 1. The user isn't going to get an answer in reasonable time, and it may be
> better to tell him "no can do" than to keep him waiting.
> 
> 2. There may be something seriously wrong with the query, or with system
> load, and the application had better abort the query to protect itself.
> 
> The user is likely at some point to move on to something else anyway, and
> it doesn't make much sense to continue processing.  Worst case, the user
> has already tried to reload the page a few times and you may have several
> instances of the problem query running at the same time.

Ahhh, I wasn't considering the web application case. I was only 
considering the desktop application case, in which case there's no 
reloading and TCP timeouts to consider.

>> And consider "real-time monitoring" software, e.g. something displaying
>> a graph. If the data doesn't get there on time for a once-a-second graph
>> update, should the query be cancelled? No: otherwise it probably won't
>> get there on time *every* second.
> 
> Yes, if the job can't make its real-time constraint, it should be
> canceled.  If the application consistently can't make its time goals, then
> it must cope or die.  Otherwise you're talking about "fast enough," not
> realtime.

True. "Real-time monitoring" is a misnomer, I should have said something 
like "live monitoring".

>>> And of course there's the matter of transactions.  Do you abort the
>>> transaction (if any)?
>> Treat it the same as a statement failure. I don't know how pqxx behaves
>> in this respect: if statement failure only rolls back the statement
>> itself, then it should do that. If statement failure aborts an entire
>> transaction, then it should do that.
> 
> That is determined in the back-end, not in the client library: a failed
> statement aborts the transaction if one was ongoing.

Then that's what it should do!

>>> What if you're not currently executing any queries
>>> so that the cancel is a no-op from the database's perspective?  Do you
>>> abort, throw, ignore?
>> I can give you a definite answer to that one. You ignore. Quite simply
>> put: as a programmer you can never make sure that the database is busy
>> and then cancel in the safe knowledge that the database will not *just*
>> have finished what it was doing. So if you throw/abort, you basically
>> force all users of cancel() to try/catch around it. Worse: if they only
>> cancel long-running queries, they may not ever find out you're throwing
>> on this condition until production time (because they didn't encounter
>> the race condition in testing, it being unlikely when long queries are
>> involved).
> 
> I'm inclined to agree, but I appreciate the opportunity to discuss it. 
> Any multi-transaction database application should be prepared to catch and
> handle errors while executing database statements.  The cancel is not very
> different from, say, a resource error or deadlock there.

Well, yeah. But it's the *scope* of the try/catch that differs from 
normal exceptions. For instance, there's something like:

try
{
   // ... whole chunk of code ...
   foo();
   // ... whole chunk of code ...
}
catch (std::exception const&)
{
   // ...
}

This is the normal thing -- do error reporting, aborting an entire chunk 
of work and doing some cleanup. But if foo() is a cancel statement, and 
I want the behaviour "I want this canceled if it is running", I might 
need to add another try/catch *just around the call to foo()*.

Another reason not to throw an exception: it's not an exceptional 
situation. It's to be expected that the statement may have just finished 
when the cancellation is requested.

> It's also similar in that, if we ignore cancels that don't come during
> database statements, the exception typically won't show up during testing
> and exploration.

Yes. But I'd hate to add exceptions for expectable situations just to 
make people aware that they should add exception handlers. At least find 
a proper excuse to throw an exception once in a while. :-)

> In fact I wonder whether it may make sense to have two versions of cancel:
> a "cancel current statement" that only aborts a statement if one is
> ongoing, and a "cancel and die."  The latter would guarantee that the
> ongoing transaction would abort and accept no further statements,
> regardless of what it was doing at the time.  That could be a useful way
> for a multithreaded application to "reach out and touch" a thread that was
> doing stuff that's no longer appreciated.  The application could implement
> that as well, of course, but if it means many programmers re-writing the
> same code, we might as well have it in the library.

A very interesting concept, and very useful, I think! Definitely worth 
considering.

> One problem is, all this asynchronous stuff requires locking.  We don't do
> that right now, and it's a pretty big step to take.

True, that may take up a lot more work...

Cheers,
Bart
_______________________________________________
Libpqxx-general mailing list
[email protected]
http://gborg.postgresql.org/mailman/listinfo/libpqxx-general

Reply via email to