Intermittent Problems With cfthread - coldfusion

I found this bug report. The question is, "Is that what's happening to me?".
I have a few situations where I do this sort of thing.
<cfthread name="thread1" action="run">
code for thread1
</cfthread>
<cfthread name="thread2" action="run">
code for thread2
</cfthread>
The next one will have an actual name.
<cfthread name="CIMSThread" action="run">
code for CIMSThread
</cfthread>
<cfthread name="thread1,thread2,CIMSThread" action="join"></cfthread>
Every so often, I will get these sorts of exceptions.
"Error","cfthread-638","04/10/13","15:14:14",,"CIMSTHREAD: null"
"Error","jrpp-1215","04/10/13","15:14:22","DWQueries","Error Executing Database
Query.<br><b>Query Of Queries runtime error.</b><br>
Table named CIMSThread.CIMSData was not found in memory. etc"
When it first happened, I ran the applicable report again and got the same type of error on a different thead and eventually got it to run successfully without changing any code or data.
When it first happened, I also thought something bad might be happening in the thread which would cause it to crash, so I did something to force that to happen. However, when I checked the exception log, the error in that thread showed up. In these cases, the exception log shows what's in this post.
We are running Version 9,0,1,274733 and have monitoring turned on.
Am I being affected by the reported bug, or might this be something else?
Reply to Comments
I am not able to reproduce the problem at will. After consulting with my administrator we have turned off monitoring, but the pages are not being run very often. If the errors don't appear for awhile, it won't necessarily prove anything.
The problematic threads contain long running queries. Something I just thought of is that there is a very frequently used page that has never caused an issue. There are two differences between the good page and the problem pages. The good page has runs just two threads and joins them. The problem pages run more than two. Also, the queries on the good page don't take as long to exectute.
For Those Who Suggest A Timeout, It's Not
Here is some code. The query takes about 4 seconds to run.
<cfthread name="ThreadWithTimeOut" action="run">
<cfquery name="thread.x" datasource="dw" timeout="1">
sql deleted
</cfquery>
</cfthread>
<cfthread action="join" name="ThreadWithTimeOut"></cfthread>
<cfdump var="#ThreadWithTimeOut.x#" metainfo="no">
The exception log shows this:
"Error","cfthread-6","04/16/13","14:19:15",,"THREADWITHTIMEOUT:
Error Executing Database Query. **
Error ** (11319) [Red Brick Warehouse JDBC Driver] :
Query timeout (1 seconds) has expired."
coldfusion.tagext.sql.QueryTag$DatabaseQueryException: Error Executing Database Query.
and this:
"Error","jrpp-238","04/16/13","14:19:15","Dan",
"Element X is undefined in THREADWITHTIMEOUT.
That's a different set of exceptions. The previous ones said the thread was null.

look at the error you're getting more closely:
"Error","cfthread-638","04/10/13","15:14:14",,"CIMSTHREAD: null"
"Error","jrpp-1215","04/10/13","15:14:22","DWQueries","Error Executing Database
Query.<br><b>Query Of Queries runtime error.</b><br>
Table named CIMSThread.CIMSData was not found in memory. etc"
From that error I can only assume (because you didn't provide any actual code in your question) that the code in the CIMSTHREAD is raising an error causing the thread to crash and not return any data.
Also from the error (and your question), I can deduct that your thread is querying the database and passing it back.
Now personally I don't know why in the world you're using a thread to query your database. If you need to resort to that because the queries take awhile to execute, then you have bigger problems my friend. I would put the queries being run against the database in a ide attached to the database itself. See if you need to add an index or play with the query somehow so that it returns faster.
Bottom line... I think your problem isn't a cfthread issue, its a timeout issue with your query.

Related

How should I handle an error in libpq for postgresql

I'm creating a few simple helper classes and methods for working with libpq, and am wondering if I receive an error from the database - (e.g. SQL error), how should I handle it?
At the moment, each method returns a bool depending on whether the operation was a success, and so is up to the user to check before continuing with new operations.
However, after reading the libpq docs, if an error occurs the best I can come up with is that I should log the error message / status and otherwise ignore. For example, if the application is in the middle of a transaction, then I believe it can still continue (Postgresql won't cancel the transaction as far as I know).
Is there something I can do with PostgreSQL / libpq to make the consequences of such errors safe regarding the database server, or is ignorance the better policy?
You should examine the SQLSTATE in the error and make handling decisions based on that and that alone. Never try to make decisions in code based on the error message text.
An application should simply retry transactions for certain kinds of errors:
Serialization failures
Deadlock detection transaction aborts
For connection errors, you should reconnect then re-try the transaction.
Of course you want to set a limit on the number of retries, so you don't loop forever if the issue doesn't clear up.
Other kinds of errors aren't going to be resolved by trying again, so the app should report an error to the client. Syntax error? Unique violation? Check constraint violation? Running the statement again won't help.
There is a list of error codes in the documentation but the docs don't explain much about each error, but the preamble is quite informative.
On a side note: One trap to avoid falling into is "testing" connections with a trivial query before using them, and assuming that means the real query can't fail. That's a race condition. Don't bother testing connections; simply run the real query and handle any error.
The details of what exactly to do depend on the error and on the application. If there was a single always-right answer, libpq would already do it for you.
My suggestions:
Always keep a record of the transaction until you've got a confirmed commit from the DB, in case you have to re-run. Don't just fire-and-forget SQL statements.
Retry the transaction without a disconnect and reconnect for SQLSTATEs 40001 (serialization_failure) and 40P01 (deadlock_detected), as these are transient conditions generally resolved by re-trying. You should log them, as they're opportunities to improve how the app interacts with the DB and if they happen a lot they're a performance problem.
Disconnect, reconnect, and retry the transaction at least once for error class 08 (connection exceptions).
Handle 53300 (too_many_connections) and 53400 (connection limit exceeded) with specific and informative errors to the user. Same with the other 53 class entries.
Handle class 57's entries with specific and informative errors to the user. Do not retry if you get a query_cancelled (57014), it'll make sysadmins very angry.
Handle 25006 (read_only_sql_transaction) by reporting a different error, telling the user you tried to write to a read-only database or using a read-only transaction.
Report a different error for 23505 (UNIQUE violation), indicating that there's a conflict in a unique constraint or primary key constraint. There's no point retrying.
Error class 01 should never produce an exception.
Treat other cases as errors and report them to the caller, with details from the problem - most importantly SQLSTATE. Log all the details if you return a simplified error.
Hope that's useful.

Saving the same UIManagedDocument on two different devices generates error

Should the same UIManagedDocument be open on both of my devices, and I save (using the following code):
[self.documentDatabase.managedObjectContext performBlockAndWait:^{
STNoteLabelCell *cell = (STNoteLabelCell *)[self.noteTableView cellForRowAtIndexPath:indexPath];
[cell setNote:newNote animated:YES];
}];
I am told that the UIManagedDocuments documentState is changed to UIDocumentStateSavingError then I get this error:
CoreData: error: (1) I/O error for database at /var/mobile/Applications/some-long-id/Documents/Read.dox/StoreContent.nosync/persistentStore. SQLite error code:1, 'cannot rollback - no transaction is active'
2013-05-14 16:30:09.062 myApp[11711:4d23] -[_PFUbiquityRecordImportOperation main](312): CoreData: Ubiquity: Threw trying to get the knowledge vector from the store: <NSSQLCore: 0x1e9e2680> (URL: file://localhost/var/mobile/Applications/some-long-id/Documents/Read.dox/StoreContent.nosync/persistentStore)
Does anybody know why this error happens?
A couple of things...
I think the saving the same document on two different devices is a red herring, as it will actually be working on a local copy of your database on each device - only the transaction logs get uploaded to iCloud.
Secondly, I may be confused, but I don't see anything in the above code snippet that indicates you are performing a save (unless it is triggered by one of those calls, or autosave happens).
What that code snippet does seem to be doing is:
On your database document's child MOC thread, run the following block
of code
And that block of code is doing purely UI related stuff,
nothing to actually do with the database? The only thing that might
be going out to the DB is cellForRowAtIndexPath - and this usually
would be expected to only be doing read operations, not something
that needs to save.
The only other thing.... if the above code does trigger a save - you might have an issue with performing that as a performBlockAndWait. The UIManagedDocument save routines do stuff asynchronously - but they need the run loop to execute before they actually get a chance to run the async part... So by blocking before continuing you may actually be preventing the actual save from being executed or something.
I'm guessing wildly here, but have seen enough with saving managed documents to know to be really careful with which thread things are actually being called from, and that after a save request has been made, to allow the run loop to have a chance to actually do it. To be fair, this has only ever been an issue with calling saveToURL: repeatedly within one method, or in a loop, in which case all the async parts of the saves get queued up and executed at the end, usually to great comical effect.

CFStoredProc Timing Out

I have a very basic app that plugs data into a stored procedure which in turn returns a recordset. I've been experiencing what I thought were 'timeouts'. However, I'm now no longer convinced that this is what is really happening. The reason why is that the DBA and I watched sql server spotlight to see when the stored procedure was finished processing. As soon as the procedure finished processing and returned a recordset, the ColdFusion page returned a 'timeout' error. I'm finding this to be consistent whenever the procedure takes longer than a minute. To prove this, I created a stored procedure with nothing more than this:
BEGIN
WAITFOR DELAY '00:00:45';
SELECT TOP 1000 *
FROM AnyTableName
END
If I run it for 59 seconds I get a result back in ColdFusion. If I change it to one minute:
WAITFOR DELAY '00:01';
I get a cfstoredproc timeout error. I've tried running this in different instances of ColdFusion on the same server, different databases/datasources. Now, what is strange, is that I have other procedures that run longer than a minute and return a result. I've even tried this locally on my desktop with ColdFusion 10 and get the same result. At this point, I'm out of places to look so I'm reaching out for other things to try. I've also increased the timeout in the datasource connections and that didn't help. I even tried ColdFusion 10 with the timeout attribute but no luck there either. What is consistent is that the timeout error is displayed when the query completes.
Also, I tried adding the WAITFOR in cfquery and the same result happened. It worked when set for 59 seconds, but timed out when changed to a minute. I can change the sql to select top 1 and there is no difference in the result.
Per the comments, it looks like your request timeout is set to sixty seconds.
Use cfsetting to extend your timeout to whatever you need.
<cfsetting requesttimeout = "{numberOfSeconds}">
The default timeout for all pages is 60s, you need to change this in the cfadmin if it is not enough, but most pages should not run this long.
Take some time to familiarise yourself with the cfadmin and all its settings to avoid such head scratching.
As stated use cfsetting tag to override for specific pages.

ColdFusion performance and locking optimisation

I have a link that will allow users to click it and it fetches a zip file of photos. If the zip file doesn't exist, it then starts a thread to create the zip and displays a message back to the user that the photos are currently being processed.
What I'm trying to avoid is a user clicking the link repeatedly and setting off a whole mass of threads that will try create/update the zip file. The zip file processing is quite system resource intensive so I only want to allow the application to generate one zip at a time. If one is busy being compiled, it should just do nothing and queue the requests.
Currently how I am handling it is with a cflock around the thread:
<cflock name="createAlbumZip" type="exclusive" timeout="30" throwontimeout="no">
<cfthread action="run" albumId="#arguments.albumId#" name="#CreateUUID()#">
....
What I am hoping occurs here (it seems to be working if I test it) is that it will check if there is currently a thread running using a lock called 'createAlbumZip'. If there is, it will queue the request for 30 seconds after which it should timeout without any error. If it wasn't able to create it within the 30 seconds that is fine.
So - this seems to be working, but my question is: Is this the best way to handle a scenario like this? Is locking the right approach? Are there any shortcomings that could arise from this approach that I don't see?
There are a million ways to skin this cat. Locking is a good start, and as per your comment on #Pat Branley's answer, I think your locking outside the thread creation might be a little more efficient for just the reason you propose: the potential would exist to create dozens of threads whose whole lifespan will consist of waiting for a lock to open or timeout.
The other thing you need to do is double up on the IF statement:
<cfif not (zip file exists)>
<cflock ...>
<cfif not (zip file exists)>
<cfthread>
...create zip...
</cfthread>
</cfif>
</cflock>
</cfif>
This will prevent the case where thread B is waiting while thread A creates the zip, and then thread A finishes, and thread B proceeds to recreate/overwrite it.
In addition, you could consider something like using JavaScript to prevent extra clicks by disabling the button/link after it's been clicked.
I think you have that code around the wrong way. What you are saying is 'only one thread is allowed to spawn this new thread'. Now that may work in your case because you have the timeouts set such that nobody can create another thread so there is no chance two threads are executing at once.
what you want to say is 'only one thread is allowed to make a zip'. So I would do this
<cfthread .... >
<cflock>
...zip....

Avoiding sqlite3 database locked

I have a multithreaded application that uses sqlite (3.7.3)
I'm hitting the database locked error that seems to be quite prevalent.
I'm wondering how to avoid it in my case.
Let me describe what I'm building. Sorry, no code it's too large and complex.
I have around 8 threads that simultaneously access the database. Any one of those threads can either read or write at the same time.
Each row in a table in the database has a file path that points to a resource + other attributes related to that resource.
3 fields of note are readers, status and del.
Readers is incremented each time a thread reads from the resource, but only if status > 0 and del = 0.
So I have some SQL that does
UPDATE resource set readers=readers+1 where id=? AND del=0 AND status>0
After that, I check the number of rows updated. It should only be 1.
After that I try to read the row back with a select. I do that even if it failed
to update because I need to know the reason that it failed.
I tried wrapping both the update and the select in in a transaction but that didn't help.
I've checked that I'm calling finalize on my statements too.
Now, I thought that sqlite serializes by default. I've tried a couple of open modes but I still get the same error.
And before you ask, no I'm not intending to go to mysql. I absolutely need zero config.
Can someone provide some pointers on how to avoid this type of problem? should I move the readers lock out of the DB? If I do that what mechanism should I replace it with? I'm using Linux under C++ and with the boost library available.
EDIT:
Interestingly, adding COMMIT after my updated call improved things dramatically.
When you open the db, you should configure the 'busy timeout'
int sqlite3_busy_timeout(sqlite3*, int ms);
http://www.sqlite.org/c3ref/busy_timeout.html
First question: are you trying to use one connection with all eight threads? If so, make sure each thread has their own connection. I don't know of any database that likes that.
Also check out the FAQ: http://www.sqlite.org/faq.html
Apparently SQLite has to be compiled with a SQLITE_THREADSAFE preprocessor option set to 1. They do have a method to determine if that's your problem.
Another issue is that writes can only happen from one process safely.