David Nicol wrote:

After reading http://www.presicient.com/dbixthrd

I don't like all the explicit waiting, although I suppose it fits the explicit
nature of DBI better than something more abstract.  It would be
possible to create a wrapper around DBIx::Threaded that would provide
self-promoting result objects (see asynchronous::universal::ready) instead
of necessitating all the checking.  Also a way to stack up calls against
an unfinished call for background completion (see
asynchronous::universal::set_callback)
would be good in my book.

Note that the various wait()'s are only relevant for start()'ed calls;
the usual DBI suspects behave as before (ie, blocking).

As for self-promoting objects, I'm not certain how DBIx::Threaded
can enforce that; the things going into and coming out of DBIx::Threaded
are data elements, rather than objects (w/ the exception of connections 
manufacturing
statement objects), ie, DBIx::Threaded is a resource,
the users of DBIx::Threaded are consumers. Any promotion they need
should be their own implementation...at which point they call
DBIx::Threaded->wait() or TQD->wait() or whatever.

As for callbacks, keep in mind that you can't pass CODErefs between
threads; the DBIx::Threaded apt. thread has no knowledge of the
appl. thread (tho I spose one could pass entire code nuggets as scalar strings
and eval on the server side...but I'm not inclined to do that).
So the only way to enforce that would be an extension
to Thread::Queue::Duplex to register a private callback association
w/ the enqueue'd $id...but that means someone somewhere has to call into
TQD to catch the cond_signal/cond_broadcast event...which kinda defeats
the purpose of registered callbacks. The only other solution is some sort of
MainLoop implicit event catcher/dispatcher, and I don't see DBI/DBIx::Threaded
as the proper place to provide that.


But it looks good.

Another thing is the fallback when invoked in a non-threaded perl.  Have
you considered using the forks module instead of threads instead of falling
back to fully synchronous operation?

Not quite that simple. TQD would also need to be updated to use
sockets, and then there's the whole mess of translating
locks/cond_wait/cond_signal to signal events.

I guess my reaction is, if you don't have threads, don't use DBIx::Threaded.
If Perl's thread model is heavyweight, and DBIx::Threaded is a
middleweight solution, then using forks and sockets is neutron star class
heavyweight, and the application probably needs a new architecture.


concerning the doubts about last_insert_id(), I think a
last_insert_id() statement
in a callback block would have to use the same connection and would execute
immediately after a threaded insert, in the same thread ---
connections each have
their own threads, do they not?  A callback queue could guarantee that an action
would happen immediately after the blocking event completed, thus solving the
stale last_insert_id problem.

So, I'd like to see something like

     $id = $dbh->dbix_threaded_start($InsertStatement,{});
     DBIx::Threaded->dbix_threaded_set_callback($id, sub{
          $LastInsertedID = $dbh->last_inserted_id()
     });

as a way to be sure that the code will run immediately after outstanding
request $id completes, in the same thread, with the same connection.


See my note wrt callbacks above. In order for that sequence to be safe, a whole
new set of locking sequences would be needed. Maybe TQD will provide async
notification in future, and/or "grouped" operations, but for now I'll leave it
to applications to sequence such things themselves.

- Dean

Reply via email to