So, the service engine has this way cool feature, the ability to call
a service when the current transaction is rolled back, or committed.
However, in reality, it actually is completely and uterly broken.

Both of these methods allow for persisting the job to the JobSandbox.
 That in itself is not a problem.

What is a problem, is that GenericAbstractDispatcher will *always*
make any such registered service an async service.  There is no way to
run a sync service.  Remember this point, I'll come back to it in a bit.

Once the ServiceXaWrapper is registered with the transaction, and the
actual commit/rollback phase happens, it'll end up calling an internal
runService helper method.  However, this helper method is run inside a
brand new, temporary thread.  This effectively makes *all* registered
services async.  That's just broken.

One thing I'm not familiar with, is if a thread that spawns a new one
automatically inherits the parent thread's transaction.  However, no
matter what that scenario actually is, when runService is running in
its own separate thread, it suspends the parent transaction.  This
means it's in its very own separate transaction.  So that the service
actually being run will *not* see anything that was in the original
transaction upon which it was registered.

Now comes the time to actually run the real service.  Since the
service is always an async service, it'll be serialized to JobSandbox,
and run a very short time later.  Not immediately.

Back in the original, parent thread, service, and transaction, the
transaction is committed or rolled back.

The aforementioned async service(s) are now run.  If the transaction
was rolled back, and they try to manipulate data, the original data
will no longer exist.  So, the service will fail, and the JobPoller
will schedule a retry of the service.  But, the service never has a
chance of succeeding, so this will repeating ad infinitum.

I was able to track all this down, because we had
placeOrder/processPayment run inside a transaction, that was then
aborted if the payment was declined.  We then started getting spammed
in the log with failed sandbox entries.

Does anyone else agree with my reading of the code?  Just looking at
the source I was able to discover these very poorly implemented designs.


Does anyone else agree with my reading here?

Reply via email to