Man thanks Ayende
On Mon, Jun 1, 2009 at 10:13 AM, Ayende Rahien <[email protected]> wrote: > Yes, I can.You need to use IEnlistmentNotification impl and register that > on the TX. > I'll have a fix shortly > > > On Mon, Jun 1, 2009 at 1:01 PM, Mike Nichols <[email protected]>wrote: > >> 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 -~----------~----~----~----~------~----~------~--~---
