Are you able to test this without all the NH dependency cruft? I want to keep hacking on this but can't figure out how to write a lighter test for it to stick in RSB code base. Just throwing TransactionExceptions doesn't work
On Mon, Jun 1, 2009 at 8:12 AM, Ayende Rahien <[email protected]> wrote: > Sigh, > I reproduced the issue, not fun. > > > On Mon, Jun 1, 2009 at 1:29 PM, Mike Nichols <[email protected]>wrote: > >> >> I think I have narrowed the problem to transaction commit failures >> that take place AFTER the 'Consume' invocation is made (ie in >> MessageCompleted). These exceptions are outside the scope of the >> try...catch wrapping the ProcessMessage call. >> In the code I have above the transaction tries to commit (in ATM) and >> then rolls back since SQL Server throws, aborting the transaction. >> When the TransactionScope attempts to Dispose in RQTransport >> ReceiveMessage method, the InternalTransaction throws since it was >> aborted, making the whole app crash since it is unhandled. >> >> Any ideas on this? My attempts to handle TransactionException have so >> far just thrown RSB into a loop. >> >> On May 30, 11:41 pm, Mike Nichols <[email protected]> wrote: >> > I have a test case here that demonstrates the problem. I changed >> > RQTransport on ReceiveMessage to catch TransactionAbortedException and >> > Debugger.Launch inside the catch statement. >> > Note this test is 'heavy' intentionally . RSB tries 5 times to handle >> > the message but when the Session flushes the transaction aborts and >> > since the transaction reference is outside the try...catch in >> > ReceiveMessage it goes unhandled. >> > >> > First here is output from NHProf Error logging: >> > It seems like since the exception is thrown inside the >> > TransactionScope (tx) instead the inner try..catch is ignored and >> > hence the TransactionAbortedException goes unhandled in the app, >> > stopping it altogether. >> > >> > ERROR: >> > DTC transaction prepre phase failed >> > System.Data.SqlTypes.SqlTypeException: SqlDateTime overflow. Must be >> > between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM. >> > at System.Data.SqlTypes.SqlDateTime.FromTimeSpan(TimeSpan value) >> > at System.Data.SqlTypes.SqlDateTime.FromDateTime(DateTime value) >> > at System.Data.SqlClient.MetaType.FromDateTime(DateTime dateTime, >> > Byte cb) >> > at System.Data.SqlClient.TdsParser.WriteValue(Object value, >> > MetaType type, Byte scale, Int32 actualLength, Int32 encodingByteSize, >> > Int32 offset, TdsParserStateObject stateObj) >> > at System.Data.SqlClient.TdsParser.TdsExecuteRPC(_SqlRPC[] >> > rpcArray, Int32 timeout, Boolean inSchema, SqlNotificationRequest >> > notificationRequest, TdsParserStateObject stateObj, Boolean >> > isCommandProc) >> > at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds >> > (CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean >> > returnStream, Boolean async) >> > at System.Data.SqlClient.SqlCommand.RunExecuteReader >> > (CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean >> > returnStream, String method, DbAsyncResult result) >> > at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery >> > (DbAsyncResult result, String methodName, Boolean sendToPipe) >> > at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() >> > at NHibernate.AdoNet.AbstractBatcher.ExecuteNonQuery(IDbCommand >> > cmd) >> > at NHibernate.AdoNet.NonBatchingBatcher.AddToBatch(IExpectation >> > expectation) >> > at NHibernate.Persister.Entity.AbstractEntityPersister.Insert >> > (Object id, Object[] fields, Boolean[] notNull, Int32 j, >> > SqlCommandInfo sql, Object obj, ISessionImplementor session) >> > at NHibernate.Persister.Entity.AbstractEntityPersister.Insert >> > (Object id, Object[] fields, Object obj, ISessionImplementor session) >> > at NHibernate.Action.EntityInsertAction.Execute() >> > at NHibernate.Engine.ActionQueue.Execute(IExecutable executable) >> > at NHibernate.Engine.ActionQueue.ExecuteActions(IList list) >> > at NHibernate.Engine.ActionQueue.ExecuteActions() >> > at >> > NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions >> > (IEventSource session) >> > at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush >> > (FlushEvent event) >> > at NHibernate.Impl.SessionImpl.Flush() >> > at >> > >> NHibernate.Impl.AbstractSessionImpl.System.Transactions.IEnlistmentNotification.Prepare >> > (PreparingEnlistment preparingEnlistment) >> > >> > TEST >> > >> ============================================================================== >> > I am attaching it here in the Files section to make it easier to read, >> > too: >> > >> > namespace Cei.MaterialsTesting.Bugs >> > { >> > public class RSBBugs : >> > OccasionalConsumerOf<RSBBugs.ConsumerCompleteMessage> >> > { >> > private WindsorContainer container; >> > private ManualResetEvent wait; >> > >> > public RSBBugs() >> > { >> > container = new WindsorContainer(new >> XmlInterpreter("Bugs/ >> > RSBBugs.config")); >> > container.AddFacility("rhino.esb", new >> RhinoServiceBusFacility >> > ().AddMessageModule<UnitOfWorkMessageModule>()); >> > container.AddFacility("trx", new >> RhinoTransactionFacility()); >> > container.AddFacility("nh_uow", new >> NHibernateUnitOfWorkFacility( >> > new >> > NHibernateUnitOfWorkFacilityConfig( >> > >> Assembly.GetAssembly(typeof >> > (BadDateEntity))))); >> > container.AddComponent<SQLMessageConsumer>(); >> > >> > var cfg = new Configuration() >> > >> .SetProperty(Environment.ReleaseConnections, "on_close") >> > .SetProperty(Environment.Dialect, >> > "NHibernate.Dialect.MsSql2005Dialect") >> > >> .SetProperty(Environment.ConnectionDriver, >> > "NHibernate.Driver.SqlClientDriver") >> > >> .SetProperty(Environment.ConnectionString, string.Format("Server= >> > (local);initial catalog={0};Integrated Security=SSPI", >> > "MaterialsTesting_Test")) >> > >> .SetProperty(Environment.ProxyFactoryFactoryClass, typeof >> > (ProxyFactoryFactory).AssemblyQualifiedName) >> > .SetProperty(Environment.ShowSql, >> "true") >> > .SetProperty(Environment.BatchSize, >> "10") >> > >> .SetProperty(Environment.GenerateStatistics, "true"); >> > >> > cfg.AddXmlFile("Bugs/BadDateEntity.hbm.xml"); >> > >> > SessionFactory = cfg.BuildSessionFactory(); >> > using (var session = >> SessionFactory.OpenSession()) >> > { >> > new SchemaExport(cfg).Execute(false, >> true, false, >> > session.Connection, null); >> > } >> > IoC.Initialize(container); >> > } >> > >> > protected ISessionFactory SessionFactory { get; set; } >> > >> > [Observation] >> > public void should_throw() >> > { >> > using(var bus = >> container.Resolve<IStartableServiceBus>()) >> > { >> > bus.Start(); >> > using(bus.AddInstanceSubscription(this)) >> > { >> > wait = new >> ManualResetEvent(false); >> > bus.Send(new SQLMessage()); >> > >> Assert.True(wait.WaitOne(TimeSpan.FromSeconds(60),false)); >> > } >> > } >> > } >> > public class SQLMessage >> > { >> > >> > } >> > >> > [Transactional] >> > public class SQLMessageConsumer : ConsumerOf<SQLMessage> >> > { >> > private IServiceBus bus; >> > >> > public SQLMessageConsumer(IServiceBus bus) >> > { >> > this.bus = bus; >> > } >> > >> > [Transaction] >> > public void Consume(SQLMessage message) >> > { >> > >> > var bad = new BadDateEntity {CreatedOn = >> DateTime.MinValue}; >> > UnitOfWork.CurrentSession.Save(bad); >> > bus.Publish(new >> ConsumerCompleteMessage()); >> > } >> > } >> > public class ConsumerCompleteMessage >> > { >> > } >> > >> > public void Consume(ConsumerCompleteMessage message) >> > { >> > wait.Set(); >> > } >> > } >> > >> > } >> >> > > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Rhino Tools Dev" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/rhino-tools-dev?hl=en -~----------~----~----~----~------~----~------~--~---
