public void Runs()
        {
            var random = new Random();
            var max = (byte)random.Next(byte.MinValue, byte.MaxValue);
            var min = (byte)random.Next(byte.MinValue, max);
            var count = Substitute.For<IQueueCount>();
            var setup = new QueueSetup<object>
            {
                Name = "test",
                Priority = QueuePriority.Low,
                Processor = () => { return Substitute.For<IProcessor<object>>(); },
            };

            var connection = new QueueConnection<object>()
            {
                ConnectionString = ConnectionString,
                Setup = setup,
            };

            var throughput = Substitute.For<IQueueThroughput>();
            throughput.Frequency(setup.Priority).Returns(new Range<byte>(min, max));

            var s = new BusQueueAutoScaler<object>(count, connection, throughput);
            var runs = s.Runs(connection);

            Assert.IsNotNull(runs);
            Assert.AreEqual(min, runs.MinimumPeriodInSeconds);
            Assert.AreEqual(max, runs.MaximumPeriodInSeconds);

            throughput.Received().Frequency(setup.Priority);
        }
        public void Runs()
        {
            var random = new Random();
            var frequency = new Range<byte>();
            frequency.Maximum = (byte)random.Next(byte.MinValue, byte.MaxValue);
            frequency.Minimum = (byte)random.Next(byte.MinValue, frequency.Maximum);
            var count = Substitute.For<IQueueCount>();
            var setup = new QueueSetup<object>()
            {
                Priority = QueuePriority.High,
                Name = Guid.NewGuid().ToString(),
                Processor = () => { return Substitute.For<IProcessor<object>>(); },
            };
            var connection = new QueueConnection<object>()
            {
                Setup = setup,
                ConnectionString = ConnectionString,
            };
            var throughput = Substitute.For<IQueueThroughput>();
            throughput.Frequency(setup.Priority).Returns(frequency);

            var s = new StorageQueueAutoScaler<object>(count, connection, throughput);
            var runs = s.Runs(connection);

            Assert.IsNotNull(runs);
            Assert.AreEqual(frequency.Minimum, runs.MinimumPeriodInSeconds);
            Assert.AreEqual(frequency.Maximum, runs.MaximumPeriodInSeconds);

            throughput.Received().Frequency(setup.Priority);
        }
        public void ConnectionString()
        {
            var expected = Guid.NewGuid().ToString();
            var qc = new QueueConnection<object>()
            {
                ConnectionString = expected,
            };

            Assert.AreEqual(expected, qc.ConnectionString);
        }
        public void Setup()
        {
            var expected = new QueueSetup<object>();
            var qc = new QueueConnection<object>()
            {
                Setup = expected,
            };

            Assert.AreEqual(expected, qc.Setup);
        }
 public static void NoVerification(QueueConnection queueConnection, QueueProducerConfiguration queueProducerConfiguration, long messageCount, ICreationScope scope)
 {
 }
 public static void Verify(QueueConnection queueConnection, QueueProducerConfiguration queueProducerConfiguration, long messageCount, int orderId, ICreationScope scope)
 {
     new VerifyQueueData(queueConnection, queueProducerConfiguration.Options()).Verify(messageCount, null, orderId);
 }
        static void Main(string[] args)
        {
            //we are using serilog for sample purposes
            var log = new LoggerConfiguration()
                      .WriteTo.Console()
                      .MinimumLevel.Debug()
                      .CreateLogger();

            Log.Logger = log;
            log.Information("Startup");
            log.Information(SharedConfiguration.AllSettings);

            //verify that the queue exists
            var fileLocation     = Path.Combine(Environment.ExpandEnvironmentVariables("%userprofile%"), "Documents");
            var queueName        = ConfigurationManager.AppSettings.ReadSetting("QueueName");
            var connectionString = $"Filename={fileLocation}{ConfigurationManager.AppSettings.ReadSetting("Database")};Connection=shared;";
            var queueConnection  = new QueueConnection(queueName, connectionString);

            using (var createQueueContainer = new QueueCreationContainer <LiteDbMessageQueueInit>(serviceRegister =>
                                                                                                  Injectors.AddInjectors(new SerilogAdapter(log), SharedConfiguration.EnableTrace, SharedConfiguration.EnableMetrics,
                                                                                                                         SharedConfiguration.EnableCompression, SharedConfiguration.EnableEncryption, "LiteDbConsumerLinq",
                                                                                                                         serviceRegister), options => Injectors.SetOptions(options, SharedConfiguration.EnableChaos)))
            {
                using (var createQueue =
                           createQueueContainer.GetQueueCreation <LiteDbMessageQueueCreation>(queueConnection))
                {
                    if (!createQueue.QueueExists)
                    {
                        //the consumer can't do anything if the queue hasn't been created
                        Log.Error(
                            $"Could not find {connectionString}. Verify that you have run the producer, which will create the queue");
                        return;
                    }
                }
            }

            using (var schedulerContainer = new SchedulerContainer(serviceRegister =>
                                                                   Injectors.AddInjectors(new SerilogAdapter(log), SharedConfiguration.EnableTrace, SharedConfiguration.EnableMetrics,
                                                                                          SharedConfiguration.EnableCompression, SharedConfiguration.EnableEncryption, "LiteDbConsumerLinq",
                                                                                          serviceRegister), options => Injectors.SetOptions(options, SharedConfiguration.EnableChaos)))
            {
                using (var scheduler = schedulerContainer.CreateTaskScheduler())
                {
                    var factory = schedulerContainer.CreateTaskFactory(scheduler);
                    factory.Scheduler.Configuration.MaximumThreads = 8; //8 background threads
                    factory.Scheduler.Configuration.MaxQueueSize   =
                        1;                                              //allow work to be de-queued but held in memory until a thread is free

                    //note - the same factory can be passed to multiple queue instances - don't dispose the scheduler container until all queues have finished
                    factory.Scheduler.Start(); //the scheduler must be started before passing it to a queue

                    using (var queueContainer = new QueueContainer <LiteDbMessageQueueInit>(serviceRegister =>
                                                                                            Injectors.AddInjectors(new SerilogAdapter(log), SharedConfiguration.EnableTrace, SharedConfiguration.EnableMetrics,
                                                                                                                   SharedConfiguration.EnableCompression, SharedConfiguration.EnableEncryption,
                                                                                                                   "LiteDbConsumerLinq", serviceRegister), options => Injectors.SetOptions(options, SharedConfiguration.EnableChaos)))
                    {
                        using (var queue =
                                   queueContainer.CreateConsumerMethodQueueScheduler(queueConnection, factory))
                        {
                            //set some processing options and start looking for work
                            //in the async model, the worker count is how many threads are querying the queue - the scheduler runs the work
                            queue.Configuration.Worker.WorkerCount =
                                1;                                                   //lets just run 1 thread that queries the database

                            queue.Configuration.HeartBeat.UpdateTime  = "sec(*%10)"; //set a heartbeat every 10 seconds
                            queue.Configuration.HeartBeat.MonitorTime =
                                TimeSpan.FromSeconds(15);                            //check for dead records every 15 seconds
                            queue.Configuration.HeartBeat.Time =
                                TimeSpan.FromSeconds(
                                    35); //records with no heartbeat after 35 seconds are considered dead

                            //an invalid data exception will be re-tried 3 times, with delays of 3, 6 and then finally 9 seconds
                            queue.Configuration.TransportConfiguration.RetryDelayBehavior.Add(
                                typeof(InvalidDataException),
                                new List <TimeSpan>
                            {
                                TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(6), TimeSpan.FromSeconds(9)
                            });

                            queue.Configuration.MessageExpiration.Enabled     = true;
                            queue.Configuration.MessageExpiration.MonitorTime =
                                TimeSpan.FromSeconds(20); //check for expired messages every 20 seconds
                            queue.Start();
                            Console.WriteLine("Processing messages - press any key to stop");
                            Console.ReadKey((true));

                            //if jaeger is using udp, sometimes the messages get lost; there doesn't seem to be a flush() call ?
                            if (SharedConfiguration.EnableTrace)
                            {
                                System.Threading.Thread.Sleep(2000);
                            }
                        }
                    }
                }
            }
        }
 private void Verify(QueueConnection arg1, QueueProducerConfiguration arg2, long arg3, ICreationScope arg4)
 {
     //only verify count in redis
 }
Beispiel #9
0
        public void Run <TTransportInit, TTransportCreate>(
            QueueConnection queueConnection,
            int messageCount, int runtime, int timeOut, int workerCount, int readerCount, int queueSize,
            int messageType,
            LinqMethodTypes linqMethodTypes,
            bool enableChaos,
            Action <TTransportCreate> setOptions,
            Func <QueueProducerConfiguration, AdditionalMessageData> generateData,
            Action <QueueConnection, QueueProducerConfiguration, long, ICreationScope> verify,
            Action <QueueConnection, IBaseTransportOptions, ICreationScope, int, bool, bool> verifyQueueCount)
            where TTransportInit : ITransportInit, new()
            where TTransportCreate : class, IQueueCreation
        {
            if (Factory == null)
            {
                Factory = CreateFactory(workerCount, queueSize);
            }

            var logProvider = LoggerShared.Create(queueConnection.Queue, GetType().Name);

            using (var queueCreator =
                       new QueueCreationContainer <TTransportInit>(
                           serviceRegister => serviceRegister.Register(() => logProvider, LifeStyles.Singleton)))
            {
                ICreationScope scope     = null;
                var            oCreation = queueCreator.GetQueueCreation <TTransportCreate>(queueConnection);
                try
                {
                    setOptions(oCreation);
                    var result = oCreation.CreateQueue();
                    Assert.True(result.Success, result.ErrorMessage);
                    scope = oCreation.Scope;

                    if (messageType == 1)
                    {
                        var id       = Guid.NewGuid();
                        var producer = new ProducerMethodAsyncShared();
                        producer.RunTestAsync <TTransportInit>(queueConnection, false, messageCount, logProvider,
                                                               generateData,
                                                               verify, false, runtime, id, linqMethodTypes, oCreation.Scope, false).Wait(timeOut);

                        var consumer = new ConsumerMethodAsyncShared {
                            Factory = Factory
                        };
                        consumer.RunConsumer <TTransportInit>(queueConnection,
                                                              false, logProvider,
                                                              runtime, messageCount,
                                                              timeOut, readerCount, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(35), id,
                                                              "second(*%10)", enableChaos, scope);
                    }
                    else if (messageType == 2)
                    {
                        var id       = Guid.NewGuid();
                        var producer = new ProducerMethodAsyncShared();
                        producer.RunTestAsync <TTransportInit>(queueConnection, false, messageCount, logProvider,
                                                               generateData,
                                                               verify, false, runtime, id, linqMethodTypes, oCreation.Scope, false).Wait(timeOut);

                        var consumer = new ConsumerMethodAsyncShared {
                            Factory = Factory
                        };
                        consumer.RunConsumer <TTransportInit>(queueConnection,
                                                              false, logProvider,
                                                              runtime, messageCount,
                                                              timeOut, readerCount, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(35), id,
                                                              "second(*%10)", enableChaos, scope);
                    }
                    else if (messageType == 3)
                    {
                        var id       = Guid.NewGuid();
                        var producer = new ProducerMethodAsyncShared();
                        producer.RunTestAsync <TTransportInit>(queueConnection, false, messageCount, logProvider,
                                                               generateData,
                                                               verify, false, runtime, id, linqMethodTypes, oCreation.Scope, false).Wait(timeOut);

                        var consumer = new ConsumerMethodAsyncShared {
                            Factory = Factory
                        };
                        consumer.RunConsumer <TTransportInit>(queueConnection,
                                                              false, logProvider,
                                                              runtime, messageCount,
                                                              timeOut, readerCount, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(35), id,
                                                              "second(*%10)", enableChaos, scope);
                    }

                    verifyQueueCount(queueConnection, oCreation.BaseTransportOptions, scope, 0, false, false);
                }
                finally
                {
                    oCreation.RemoveQueue();
                    oCreation.Dispose();
                    scope?.Dispose();
                }
            }
        }
Beispiel #10
0
 public VerifyQueueRecordCount(QueueConnection queueConnection, SqlServerMessageQueueTransportOptions options)
 {
     _options         = options;
     _connection      = new SqlConnectionInformation(queueConnection);
     _tableNameHelper = new SqlServerTableNameHelper(_connection);
 }
Beispiel #11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="RedisConnectionInfo"/> class.
 /// </summary>
 /// <param name="queueConnection">Queue and connection information.</param>
 public RedisConnectionInfo(QueueConnection queueConnection) : base(queueConnection)
 {
     ValidateConnection(queueConnection.Connection);
 }
Beispiel #12
0
        public void RunConsumer <TTransportInit>(QueueConnection queueConnection, bool addInterceptors,
                                                 ILogger logProvider,
                                                 int messageCount, int workerCount, int timeOut,
                                                 int queueSize, int readerCount,
                                                 TimeSpan heartBeatTime, TimeSpan heartBeatMonitorTime,
                                                 string updateTime,
                                                 string route,
                                                 bool enableChaos,
                                                 ICreationScope scope)
            where TTransportInit : ITransportInit, new()
        {
            if (enableChaos)
            {
                timeOut *= 2;
            }

            using (var metrics = new Metrics.Metrics(queueConnection.Queue))
            {
                var addInterceptorConsumer = InterceptorAdding.No;
                if (addInterceptors)
                {
                    addInterceptorConsumer = InterceptorAdding.ConfigurationOnly;
                }

                var processedCount = new IncrementWrapper();
                using (
                    var creator = SharedSetup.CreateCreator <TTransportInit>(addInterceptorConsumer, logProvider, metrics, false, enableChaos, scope)
                    )
                {
                    using (var schedulerCreator =
                               new SchedulerContainer(
                                   // ReSharper disable once AccessToDisposedClosure
                                   serviceRegister => serviceRegister.Register(() => metrics, LifeStyles.Singleton), options => SharedSetup.SetOptions(options, enableChaos)))
                    {
                        bool rollBacks;
                        using (var taskScheduler = schedulerCreator.CreateTaskScheduler())
                        {
                            taskScheduler.Configuration.MaximumThreads = workerCount;
                            taskScheduler.Configuration.MaxQueueSize   = queueSize;

                            taskScheduler.Start();
                            var taskFactory = schedulerCreator.CreateTaskFactory(taskScheduler);

                            using (
                                var queue =
                                    creator
                                    .CreateConsumerQueueScheduler(
                                        queueConnection, taskFactory))
                            {
                                rollBacks = queue.Configuration.TransportConfiguration.MessageRollbackSupported;
                                SharedSetup.SetupDefaultConsumerQueue(queue.Configuration, readerCount, heartBeatTime,
                                                                      heartBeatMonitorTime, updateTime, route);
                                SharedSetup.SetupDefaultErrorRetry(queue.Configuration);

                                var waitForFinish = new ManualResetEventSlim(false);
                                waitForFinish.Reset();

                                //start looking for work
                                queue.Start <TMessage>((message, notifications) =>
                                {
                                    MessageHandlingShared.HandleFakeMessagesError(processedCount, waitForFinish,
                                                                                  messageCount, message);
                                });

                                waitForFinish.Wait(timeOut * 1000);

                                //wait for last error to be saved if needed.
                                Thread.Sleep(3000);
                            }
                        }

                        if (rollBacks)
                        {
                            VerifyMetrics.VerifyRollBackCount(queueConnection.Queue, metrics.GetCurrentMetrics(), messageCount, 2, 2);
                        }
                    }
                }
            }
        }
 /// <summary>
 /// Allows a transport to register its dependencies in the IoC container.
 /// </summary>
 /// <param name="container">The container.</param>
 /// <param name="registrationType">Type of the registration.</param>
 /// <param name="queueConnection">Queue and connection information.</param>
 public override void RegisterImplementations(IContainer container, RegistrationTypes registrationType, QueueConnection queueConnection)
 {
     RegisterConnectionImplementation.RegisterImplementations(container, queueConnection);
 }
        public void ScaleUnit()
        {
            var count = Substitute.For<IQueueCount>();
            var setup = Substitute.For<IQueueSetup<object>>();
            setup.Name.Returns(Guid.NewGuid().ToString());
            
            var connection = new QueueConnection<object>()
            {
                Setup = setup,
                ConnectionString = ConnectionString,
            };

            var s = new BusQueueAutoScaler<object>(count, connection);
            var unit = s.ScaleUnit(connection);

            Assert.IsNotNull(unit);
            Assert.AreEqual(1, unit.Count());
        }
        public void ScaleUnitSetupNull()
        {
            var count = Substitute.For<IQueueCount>();
            var setup = new QueueConnection<object>();

            var s = new StorageQueueAutoScaler<object>(count, setup);
            var unit = s.ScaleUnit(null);

            Assert.IsNotNull(unit);
            Assert.AreEqual(1, unit.Count());
        }
        /// <summary>
        /// Creates an async consumer queue that uses a task scheduler
        /// </summary>
        /// <param name="queueConnection">Queue and connection information.</param>
        /// <param name="factory">The task factory.</param>
        /// <returns></returns>
        public IConsumerMethodQueueScheduler CreateConsumerMethodQueueScheduler(QueueConnection queueConnection, ITaskFactory factory)
        {
            Guard.NotNull(() => queueConnection, queueConnection);

            return(CreateConsumerMethodQueueSchedulerInternal(queueConnection, factory, null, false));
        }
        /// <summary>
        /// Creates the consumer method queue scheduler.
        /// </summary>
        /// <param name="queueConnection">Queue and connection information.</param>
        /// <param name="factory">The factory.</param>
        /// <param name="workGroup">The work group.</param>
        /// <param name="internalFactory">if set to <c>true</c> [internal factory].</param>
        /// <returns></returns>
        private IConsumerMethodQueueScheduler CreateConsumerMethodQueueSchedulerInternal(QueueConnection queueConnection, ITaskFactory factory, IWorkGroup workGroup, bool internalFactory)
        {
            Guard.NotNull(() => queueConnection, queueConnection);

            IContainer container;

            if (internalFactory) //we own factory
            {
                if (workGroup == null)
                {
                    container = _createContainerInternal()
                                .Create(QueueContexts.ConsumerMethodQueueScheduler, _registerService, queueConnection,
                                        _transportInit, ConnectionTypes.Receive,
                                        serviceRegister =>
                                        serviceRegister.Register(() => factory, LifeStyles.Singleton)
                                        .Register <IWorkGroup>(() => new WorkGroupNoOp(), LifeStyles.Singleton)
                                        .Register(() => factory.Scheduler, LifeStyles.Singleton), _setOptions);
                }
                else
                {
                    container = _createContainerInternal()
                                .Create(QueueContexts.ConsumerMethodQueueScheduler, _registerService, queueConnection,
                                        _transportInit, ConnectionTypes.Receive,
                                        serviceRegister =>
                                        serviceRegister.Register(() => factory, LifeStyles.Singleton)
                                        .Register(() => workGroup, LifeStyles.Singleton)
                                        .Register(() => factory.Scheduler, LifeStyles.Singleton), _setOptions);
                }
            }
            else  //someone else owns factory
            {
                if (workGroup == null)
                {
                    container = _createContainerInternal()
                                .Create(QueueContexts.ConsumerMethodQueueScheduler, _registerService, queueConnection,
                                        _transportInit, ConnectionTypes.Receive,
                                        serviceRegister =>
                                        serviceRegister.RegisterNonScopedSingleton(factory)
                                        .Register <IWorkGroup>(() => new WorkGroupNoOp(), LifeStyles.Singleton)
                                        .RegisterNonScopedSingleton(factory.Scheduler), _setOptions);
                }
                else
                {
                    container = _createContainerInternal()
                                .Create(QueueContexts.ConsumerMethodQueueScheduler, _registerService, queueConnection,
                                        _transportInit, ConnectionTypes.Receive,
                                        serviceRegister =>
                                        serviceRegister.RegisterNonScopedSingleton(factory)
                                        .Register(() => workGroup, LifeStyles.Singleton)
                                        .RegisterNonScopedSingleton(factory.Scheduler), _setOptions);
                }
            }
            Containers.Add(container);
            return(container.GetInstance <IConsumerMethodQueueScheduler>());
        }
        /// <inheritdoc />
        public override void RegisterImplementations(IContainer container, RegistrationTypes registrationType,
                                                     QueueConnection queueConnection)
        {
            Guard.NotNull(() => container, container);
            base.RegisterImplementations(container, registrationType, queueConnection);

            var init = new RelationalDatabaseMessageQueueInit <long, Guid>();

            init.RegisterStandardImplementations(container, Assembly.GetAssembly(GetType()));

            //**all
            container.Register <IDbConnectionFactory, DbConnectionFactory>(LifeStyles.Singleton);
            container.Register <PostgreSqlMessageQueueSchema>(LifeStyles.Singleton);
            container.Register <IQueueCreation, PostgreSqlMessageQueueCreation>(LifeStyles.Singleton);
            container.Register <IJobSchedulerLastKnownEvent, PostgreSqlJobSchedulerLastKnownEvent>(LifeStyles.Singleton);
            container.Register <IOptionsSerialization, OptionsSerialization>(LifeStyles.Singleton);
            container.Register <PostgreSqlJobSchema>(LifeStyles.Singleton);
            container.Register <ISendJobToQueue, PostgreSqlSendJobToQueue>(LifeStyles.Singleton);
            container.Register <CommandStringCache, PostgreSqlCommandStringCache>(LifeStyles.Singleton);
            container.Register <IJobSchema, PostgreSqlJobSchema>(LifeStyles.Singleton);
            container.Register <IReadColumn, ReadColumn>(LifeStyles.Singleton);
            container.Register <ITransportOptionsFactory, TransportOptionsFactory>(LifeStyles.Singleton);
            container.Register <IGetPreviousMessageErrors, GetPreviousMessageErrors <long> >(LifeStyles.Singleton);

            container.Register <IRemoveMessage, RemoveMessage>(LifeStyles.Singleton);

            container.Register <IGetTime, PostgreSqlTime>(LifeStyles.Singleton);
            container.Register <IGetFirstMessageDeliveryTime, GetFirstMessageDeliveryTime>(LifeStyles.Singleton);
            container
            .Register
            <IPostgreSqlMessageQueueTransportOptionsFactory, PostgreSqlMessageQueueTransportOptionsFactory>(
                LifeStyles.Singleton);

            container.Register <PostgreSqlCommandStringCache>(LifeStyles.Singleton);
            container.Register <IConnectionInformation>(() => new SqlConnectionInformation(queueConnection),
                                                        LifeStyles.Singleton);

            container.Register <PostgreSqlMessageQueueTransportOptions>(LifeStyles.Singleton);
            container.Register <IConnectionHeader <NpgsqlConnection, NpgsqlTransaction, NpgsqlCommand>, ConnectionHeader <NpgsqlConnection, NpgsqlTransaction, NpgsqlCommand> >(LifeStyles.Singleton);
            //**all

            //**receive
            container.Register <IReceiveMessages, PostgreSqlMessageQueueReceive>(LifeStyles.Transient);
            container.Register <IConnectionHolderFactory <NpgsqlConnection, NpgsqlTransaction, NpgsqlCommand>, ConnectionHolderFactory>(LifeStyles.Singleton);
            container.Register <ITransportRollbackMessage, RollbackMessage>(LifeStyles.Singleton);
            container.Register <ReceiveMessage>(LifeStyles.Transient);
            container.Register <IBuildMoveToErrorQueueSql, BuildMoveToErrorQueueSql>(LifeStyles.Singleton);
            //**receive

            //reset heart beat
            container
            .Register <IPrepareCommandHandler <ResetHeartBeatCommand <long> >,
                       ResetHeartBeatCommandPrepareHandler>(LifeStyles.Singleton);

            //delete table - need lower case
            container
            .Register <IPrepareCommandHandler <DeleteTableCommand>,
                       DeleteTableCommandPrepareHandler>(LifeStyles.Singleton);

            //explicit registration of our job exists query
            container
            .Register <IQueryHandler <DoesJobExistQuery <NpgsqlConnection, NpgsqlTransaction>,
                                      QueueStatuses>,
                       DoesJobExistQueryHandler <NpgsqlConnection, NpgsqlTransaction> >(LifeStyles.Singleton);

            //because we have an explicit registration for job exists, we need to explicitly register the prepare statement
            container
            .Register <IPrepareQueryHandler <DoesJobExistQuery <NpgsqlConnection, NpgsqlTransaction>,
                                             QueueStatuses>,
                       DoesJobExistQueryPrepareHandler <NpgsqlConnection, NpgsqlTransaction> >(LifeStyles.Singleton);

            //expired messages
            container
            .Register <IPrepareQueryHandler <FindExpiredMessagesToDeleteQuery <long>, IEnumerable <long> >,
                       FindExpiredRecordsToDeleteQueryPrepareHandler>(LifeStyles.Singleton);

            //error messages
            container
            .Register <IPrepareQueryHandler <FindErrorMessagesToDeleteQuery <long>, IEnumerable <long> >,
                       FindErrorRecordsToDeleteQueryPrepareHandler>(LifeStyles.Singleton);

            //heartbeat
            container
            .Register <IPrepareQueryHandler <FindMessagesToResetByHeartBeatQuery <long>, IEnumerable <MessageToReset <long> > >,
                       FindRecordsToResetByHeartBeatQueryPrepareHandler>(LifeStyles.Singleton);

            container
            .Register <ICommandHandlerWithOutput <DeleteTransactionalMessageCommand, long>,
                       DeleteTransactionalMessageCommandHandler <NpgsqlConnection, NpgsqlTransaction, NpgsqlCommand> >(LifeStyles.Singleton);

            container
            .Register <ICommandHandler <MoveRecordToErrorQueueCommand <long> >,
                       MoveRecordToErrorQueueCommandHandler <NpgsqlConnection, NpgsqlTransaction, NpgsqlCommand> >(LifeStyles.Singleton);

            //explicit registration of options
            container
            .Register <IQueryHandler <GetQueueOptionsQuery <PostgreSqlMessageQueueTransportOptions>,
                                      PostgreSqlMessageQueueTransportOptions>,
                       GetQueueOptionsQueryHandler <PostgreSqlMessageQueueTransportOptions> >(LifeStyles.Singleton);

            container
            .Register <IPrepareQueryHandler <GetQueueOptionsQuery <PostgreSqlMessageQueueTransportOptions>,
                                             PostgreSqlMessageQueueTransportOptions>,
                       GetQueueOptionsQueryPrepareHandler <PostgreSqlMessageQueueTransportOptions> >(LifeStyles.Singleton);

            container.RegisterDecorator(typeof(IPrepareQueryHandler <GetColumnNamesFromTableQuery, List <string> >),
                                        typeof(GetColumnNamesFromTableQueryPrepareDecorator), LifeStyles.Singleton);

            container.RegisterDecorator(typeof(IPrepareQueryHandler <GetTableExistsQuery, bool>),
                                        typeof(GetTableExistsQueryPrepareDecorator), LifeStyles.Singleton);

            container.RegisterDecorator(typeof(IPrepareQueryHandler <GetTableExistsTransactionQuery, bool>),
                                        typeof(GetTableExistsTransactionQueryPrepareDecorator), LifeStyles.Singleton);

            container.RegisterDecorator(typeof(ICommandHandlerWithOutput <,>),
                                        typeof(RetryCommandHandlerOutputDecorator <,>), LifeStyles.Singleton);

            container.RegisterDecorator(typeof(ICommandHandler <>),
                                        typeof(RetryCommandHandlerDecorator <>), LifeStyles.Singleton);

            container.RegisterDecorator(typeof(ICommandHandlerWithOutputAsync <,>),
                                        typeof(RetryCommandHandlerOutputDecoratorAsync <,>), LifeStyles.Singleton);

            container.RegisterDecorator(typeof(IQueryHandler <,>),
                                        typeof(RetryQueryHandlerDecorator <,>), LifeStyles.Singleton);

            //register our decorator that handles table creation errors
            container.RegisterDecorator(
                typeof(ICommandHandlerWithOutput <CreateJobTablesCommand <ITable>, QueueCreationResult>),
                typeof(CreateJobTablesCommandDecorator), LifeStyles.Singleton);

            //register our decorator that handles table creation errors
            container.RegisterDecorator(
                typeof(ICommandHandlerWithOutput <CreateQueueTablesAndSaveConfigurationCommand <ITable>,
                                                  QueueCreationResult>),
                typeof(CreateQueueTablesAndSaveConfigurationDecorator), LifeStyles.Singleton);

            //trace fallback command
            container.RegisterDecorator(
                typeof(ICommandHandler <RollbackMessageCommand <long> >),
                typeof(DotNetWorkQueue.Transport.PostgreSQL.Trace.Decorator.RollbackMessageCommandHandlerDecorator), LifeStyles.Singleton);

            //trace sending a message so that we can add specific tags
            container.RegisterDecorator(
                typeof(ICommandHandlerWithOutput <SendMessageCommand, long>),
                typeof(DotNetWorkQueue.Transport.PostgreSQL.Trace.Decorator.SendMessageCommandHandlerDecorator), LifeStyles.Singleton);

            container.RegisterDecorator(
                typeof(ICommandHandlerWithOutputAsync <SendMessageCommand, long>),
                typeof(DotNetWorkQueue.Transport.PostgreSQL.Trace.Decorator.SendMessageCommandHandlerAsyncDecorator), LifeStyles.Singleton);
        }
 public void IsQueueAutoScaler()
 {
     var count = Substitute.For<IQueueCount>();
     var setup = new QueueConnection<object>();
     Assert.IsNotNull(new StorageQueueAutoScaler<object>(count, setup) as QueueAutoScaler<IQueueConnection<object>>);
 }
Beispiel #20
0
 /// <inheritdoc />
 public SqliteConnectionInformation(QueueConnection queueConnection, IDbDataSource dataSource) : base(queueConnection)
 {
     _dataSource = dataSource;
     ValidateConnection(queueConnection.Connection);
 }
Beispiel #21
0
 public VerifyErrorCounts(QueueConnection queueConnection)
 {
     _connection      = new SqlConnectionInformation(queueConnection);
     _tableNameHelper = new SqlServerTableNameHelper(_connection);
 }
Beispiel #22
0
        static void Main(string[] args)
        {
            //we are using serilog for sample purposes
            var log = new LoggerConfiguration()
                      .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] [{SourceContext}] {Message:lj}{NewLine}{Exception}")
                      .MinimumLevel.Debug()
                      .CreateLogger();

            Log.Logger = log;
            log.Information("Startup");
            log.Information(SharedConfiguration.AllSettings);

            var queueName        = ConfigurationManager.AppSettings.ReadSetting("QueueName");
            var connectionString = ConfigurationManager.AppSettings.ReadSetting("Database");
            var queueConnection  = new QueueConnection(queueName, connectionString);

            //create the container for creating a new queue
            using (var createQueueContainer = new QueueCreationContainer <SqlServerMessageQueueInit>(serviceRegister =>
                                                                                                     Injectors.AddInjectors(Helpers.CreateForSerilog(), SharedConfiguration.EnableTrace, SharedConfiguration.EnableMetrics, SharedConfiguration.EnableCompression, SharedConfiguration.EnableEncryption, "SQLServerProducer", serviceRegister),
                                                                                                     options => Injectors.SetOptions(options, SharedConfiguration.EnableChaos)))
            {
                using (var createQueue =
                           createQueueContainer.GetQueueCreation <SqlServerMessageQueueCreation>(queueConnection))
                {
                    var enabledUserColumns = ConfigurationManager.AppSettings.ReadSetting("UseUserDequeue");
                    if (bool.Parse(enabledUserColumns))
                    {
                        _userData = true;
                    }
                    //Create the queue if it doesn't exist
                    if (!createQueue.QueueExists)
                    {
                        //queue options
                        createQueue.Options.EnableDelayedProcessing = true;
                        createQueue.Options.EnableHeartBeat         = true;
                        createQueue.Options.EnableMessageExpiration = true;
                        createQueue.Options.EnableStatus            = true;
                        createQueue.Options.EnableStatusTable       = true;

                        if (!string.IsNullOrEmpty(enabledUserColumns) && bool.Parse(enabledUserColumns))
                        {
                            createQueue.Options.AdditionalColumnsOnMetaData = true;
                            createQueue.Options.AdditionalColumns.Add(new Column("DayOfWeek", ColumnTypes.Int, true, null));
                        }

                        var result = createQueue.CreateQueue();
                        log.Information(result.Status.ToString());
                    }
                    else
                    {
                        log.Warning("Queue already exists; not creating; note that any setting changes won't be applied");
                    }
                }
            }

            //create the producer
            using (var queueContainer = new QueueContainer <SqlServerMessageQueueInit>(serviceRegister =>
                                                                                       Injectors.AddInjectors(Helpers.CreateForSerilog(), SharedConfiguration.EnableTrace, SharedConfiguration.EnableMetrics, SharedConfiguration.EnableCompression, SharedConfiguration.EnableEncryption, "SQLServerProducer", serviceRegister)
                                                                                       , options => Injectors.SetOptions(options, SharedConfiguration.EnableChaos)))
            {
                using (var queue = queueContainer.CreateProducer <SimpleMessage>(queueConnection))
                {
                    RunProducer.RunLoop(queue, ExpiredData, ExpiredDataFuture, DelayedProcessing);
                }
            }

            //if jaeger is using udp, sometimes the messages get lost; there doesn't seem to be a flush() call ?
            if (SharedConfiguration.EnableTrace)
            {
                System.Threading.Thread.Sleep(2000);
            }
        }
Beispiel #23
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SqlConnectionInformation"/> class.
 /// </summary>
 /// <param name="queueConnection">Queue and connection information.</param>
 public SqlConnectionInformation(QueueConnection queueConnection) : base(queueConnection)
 {
     ValidateConnection(queueConnection.Connection);
 }
        /// <summary>
        /// Registers the implementations.
        /// </summary>
        /// <param name="container">The container.</param>
        /// <param name="registrationType">Type of the registration.</param>
        /// <param name="queueConnection">Queue and connection information.</param>
        public override void RegisterImplementations(IContainer container, RegistrationTypes registrationType, QueueConnection queueConnection)
        {
            Guard.NotNull(() => container, container);
            base.RegisterImplementations(container, registrationType, queueConnection);

            var init = new RelationalDatabaseMessageQueueInit <long, Guid>();

            init.RegisterStandardImplementations(container, Assembly.GetAssembly(GetType()));

            //override so that we can use schema as needed
            container.Register <ITableNameHelper, SqlServerTableNameHelper>(LifeStyles.Singleton);

            //**all
            container.Register <IDbConnectionFactory, DbConnectionFactory>(LifeStyles.Singleton);
            container.Register <SqlServerMessageQueueSchema>(LifeStyles.Singleton);
            container.Register <IQueueCreation, SqlServerMessageQueueCreation>(LifeStyles.Singleton);
            container.Register <IJobSchedulerLastKnownEvent, SqlServerJobSchedulerLastKnownEvent>(LifeStyles.Singleton);
            container.Register <SqlServerJobSchema>(LifeStyles.Singleton);
            container.Register <ISendJobToQueue, SqlServerSendJobToQueue>(LifeStyles.Singleton);
            container.Register <CommandStringCache, SqlServerCommandStringCache>(LifeStyles.Singleton);
            container.Register <IOptionsSerialization, OptionsSerialization>(LifeStyles.Singleton);
            container.Register <IJobSchema, SqlServerJobSchema>(LifeStyles.Singleton);
            container.Register <IReadColumn, ReadColumn>(LifeStyles.Singleton);
            container.Register <IBuildMoveToErrorQueueSql, BuildMoveToErrorQueueSql>(LifeStyles.Singleton);
            container.Register <ITransportOptionsFactory, TransportOptionsFactory>(LifeStyles.Singleton);
            container.Register <IRemoveMessage, RemoveMessage>(LifeStyles.Singleton);
            container.Register <IGetPreviousMessageErrors, GetPreviousMessageErrors <long> >(LifeStyles.Singleton);
            container.Register <ISqlSchema, SqlSchema>(LifeStyles.Singleton);

            container.Register <IGetTime, SqlServerTime>(LifeStyles.Singleton);
            container.Register <IGetFirstMessageDeliveryTime, GetFirstMessageDeliveryTime>(LifeStyles.Singleton);
            container
            .Register
            <ISqlServerMessageQueueTransportOptionsFactory, SqlServerMessageQueueTransportOptionsFactory>(
                LifeStyles.Singleton);

            container.Register <ICreationScope, CreationScopeNoOp>(LifeStyles.Singleton);
            container.Register <SqlServerCommandStringCache>(LifeStyles.Singleton);

            container.Register <IConnectionInformation>(() => new SqlConnectionInformation(queueConnection), LifeStyles.Singleton);

            container.Register <SqlServerMessageQueueTransportOptions>(LifeStyles.Singleton);
            container.Register <IConnectionHeader <SqlConnection, SqlTransaction, SqlCommand>, ConnectionHeader <SqlConnection, SqlTransaction, SqlCommand> >(LifeStyles.Singleton);
            //**all

            //**receive
            container.Register <IReceiveMessages, SqlServerMessageQueueReceive>(LifeStyles.Transient);
            container.Register <IConnectionHolderFactory <SqlConnection, SqlTransaction, SqlCommand>, ConnectionHolderFactory>(LifeStyles.Singleton);
            container.Register <ITransportRollbackMessage, RollbackMessage>(LifeStyles.Singleton);
            container.Register <ReceiveMessage>(LifeStyles.Transient);
            container.Register <CreateDequeueStatement>(LifeStyles.Singleton);
            container.Register <BuildDequeueCommand>(LifeStyles.Singleton);
            container.Register <ReadMessage>(LifeStyles.Singleton);
            //**receive

            //explicit registration of our job exists query
            container
            .Register <IQueryHandler <DoesJobExistQuery <SqlConnection, SqlTransaction>,
                                      QueueStatuses>,
                       DoesJobExistQueryHandler <SqlConnection, SqlTransaction> >(LifeStyles.Singleton);

            //because we have an explicit registration for job exists, we need to explicitly register the prepare statement
            container
            .Register <IPrepareQueryHandler <DoesJobExistQuery <SqlConnection, SqlTransaction>,
                                             QueueStatuses>,
                       DoesJobExistQueryPrepareHandler <SqlConnection, SqlTransaction> >(LifeStyles.Singleton);

            container
            .Register <ICommandHandlerWithOutput <SendHeartBeatCommand <long>, DateTime?>,
                       SendHeartBeatCommandHandler>(LifeStyles.Singleton);

            container
            .Register <ICommandHandler <MoveRecordToErrorQueueCommand <long> >,
                       MoveRecordToErrorQueueCommandHandler <SqlConnection, SqlTransaction, SqlCommand> >(LifeStyles.Singleton);

            //explicit registration of options
            container
            .Register <IQueryHandler <GetQueueOptionsQuery <SqlServerMessageQueueTransportOptions>, SqlServerMessageQueueTransportOptions>,
                       GetQueueOptionsQueryHandler <SqlServerMessageQueueTransportOptions> >(LifeStyles.Singleton);

            container
            .Register <ICommandHandlerWithOutput <DeleteTransactionalMessageCommand, long>,
                       DeleteTransactionalMessageCommandHandler <SqlConnection, SqlTransaction, SqlCommand> >(LifeStyles.Singleton);

            container
            .Register <IPrepareQueryHandler <GetQueueOptionsQuery <SqlServerMessageQueueTransportOptions>,
                                             SqlServerMessageQueueTransportOptions>,
                       GetQueueOptionsQueryPrepareHandler <SqlServerMessageQueueTransportOptions> >(LifeStyles.Singleton);

            container.RegisterDecorator(typeof(ICommandHandlerWithOutput <,>),
                                        typeof(RetryCommandHandlerOutputDecorator <,>), LifeStyles.Singleton);

            container.RegisterDecorator(typeof(ICommandHandler <>),
                                        typeof(RetryCommandHandlerDecorator <>), LifeStyles.Singleton);

            container.RegisterDecorator(typeof(ICommandHandlerWithOutputAsync <,>),
                                        typeof(RetryCommandHandlerOutputDecoratorAsync <,>), LifeStyles.Singleton);

            container.RegisterDecorator(typeof(IQueryHandler <,>),
                                        typeof(RetryQueryHandlerDecorator <,>), LifeStyles.Singleton);

            //register our decorator that handles table creation errors
            container.RegisterDecorator(
                typeof(ICommandHandlerWithOutput <CreateJobTablesCommand <ITable>, QueueCreationResult>),
                typeof(CreateJobTablesCommandDecorator), LifeStyles.Singleton);

            //register our decorator that handles table creation errors
            container.RegisterDecorator(
                typeof(ICommandHandlerWithOutput <CreateQueueTablesAndSaveConfigurationCommand <ITable>, QueueCreationResult>),
                typeof(CreateQueueTablesAndSaveConfigurationDecorator), LifeStyles.Singleton);

            //trace fallback command
            container.RegisterDecorator(
                typeof(ICommandHandler <RollbackMessageCommand <long> >),
                typeof(DotNetWorkQueue.Transport.SqlServer.Trace.Decorator.RollbackMessageCommandHandlerDecorator), LifeStyles.Singleton);

            //trace sending a message so that we can add specific tags
            container.RegisterDecorator(
                typeof(ICommandHandlerWithOutput <SendMessageCommand, long>),
                typeof(DotNetWorkQueue.Transport.SqlServer.Trace.Decorator.SendMessageCommandHandlerDecorator), LifeStyles.Singleton);

            container.RegisterDecorator(
                typeof(ICommandHandlerWithOutputAsync <SendMessageCommand, long>),
                typeof(DotNetWorkQueue.Transport.SqlServer.Trace.Decorator.SendMessageCommandHandlerAsyncDecorator), LifeStyles.Singleton);

            //query exists custom handler for SQL server
            container
            .Register <IPrepareQueryHandler <GetTableExistsQuery, bool>,
                       DotNetWorkQueue.Transport.SqlServer.Basic.QueryPrepareHandler.GetTableExistsQueryPrepareHandler>(LifeStyles.Singleton);

            //query exists custom handler for SQL server
            container
            .Register <IPrepareQueryHandler <GetTableExistsTransactionQuery, bool>,
                       DotNetWorkQueue.Transport.SqlServer.Basic.QueryPrepareHandler.GetTableExistsTransactionQueryPrepareHandler>(LifeStyles.Singleton);
        }
Beispiel #25
0
        /// <summary>
        /// Gets the specified queue.
        /// </summary>
        /// <typeparam name="TTransportInit">The type of the transport initialize.</typeparam>
        /// <param name="jobQueueCreation">The job queue creation.</param>
        /// <param name="queueConnection">Queue and connection information.</param>
        /// <param name="producerConfiguration">The producer configuration.</param>
        /// <returns></returns>
        /// <exception cref="DotNetWorkQueueException">Failed to create the queue. The error message is {createResult.ErrorMessage}</exception>
        public IProducerMethodJobQueue Get <TTransportInit>(IJobQueueCreation jobQueueCreation, QueueConnection queueConnection, Action <QueueProducerConfiguration> producerConfiguration = null)
            where TTransportInit : ITransportInit, new()
        {
            var connectionInfo = new BaseConnectionInformation(queueConnection);

            if (_queues.ContainsKey(connectionInfo))
            {
                return(_queues[connectionInfo]);
            }

            var transportName = typeof(TTransportInit).ToString();

            if (!_containers.ContainsKey(transportName))
            {
                var container = new QueueContainer <TTransportInit>(_registrations.QueueRegistrations, _registrations.QueueOptions);
                if (!_containers.TryAdd(transportName, container))
                {
                    container.Dispose();
                }
            }

            if (!_queues.ContainsKey(connectionInfo))
            {
                var createResult = jobQueueCreation.CreateJobSchedulerQueue(_registrations.QueueCreationRegistrations,
                                                                            queueConnection, _registrations.QueueCreationOptions);
                if (createResult.Success)
                {
                    var scope = jobQueueCreation.Scope;
                    var queue = _containers[transportName].CreateMethodJobProducer(queueConnection);
                    producerConfiguration?.Invoke(queue.Configuration);
                    if (!_queues.TryAdd(connectionInfo, queue))
                    {
                        queue.Dispose();
                        scope.Dispose();
                    }
                    else
                    {
                        queue.Start();
                        _creationScopes.TryAdd(connectionInfo, scope);
                    }
                }
                else
                {
                    throw new DotNetWorkQueueException($"Failed to create the queue. The error message is {createResult.ErrorMessage}");
                }
            }

            return(_queues[connectionInfo]);
        }
Beispiel #26
0
 /// <inheritdoc />
 public QueueCreationResult CreateJobSchedulerQueue(Action <IContainer> registerService, QueueConnection queueConnection, Action <IContainer> setOptions = null, bool enableRoute = false)
 {
     if (enableRoute)
     {
         _queueCreation.Options.EnableRoute = true;
     }
     return(_queueCreation.CreateQueue());
 }
 public static void VerifyQueueCount(QueueConnection queueConnection, IBaseTransportOptions arg3, ICreationScope arg4, int arg5, bool arg6, bool arg7)
 {
     new VerifyQueueRecordCount(queueConnection.Queue, queueConnection.Connection, (SqLiteMessageQueueTransportOptions)arg3).Verify(arg5, arg6, arg7);
 }
 /// <summary>
 /// Allows a transport to register its dependencies in the IoC container.
 /// </summary>
 /// <param name="container">The container.</param>
 /// <param name="registrationType">Type of the registration.</param>
 /// <param name="queueConnection">Queue and connection information.</param>
 public override void RegisterImplementations(IContainer container, RegistrationTypes registrationType, QueueConnection queueConnection)
 {
     container.Register <IConnectionInformation>(() => new BaseConnectionInformation(queueConnection), LifeStyles.Singleton);
     container.Register <IInternalSerializer, JsonSerializerInternal>(LifeStyles.Singleton);
     container.Register <IWorkerNotificationFactory, WorkerNotificationFactoryNoOp>(LifeStyles.Singleton);
     container.Register <IJobScheduler, JobScheduler>(LifeStyles.Singleton);
     container.Register <IJobQueue, JobQueue>(LifeStyles.Singleton);
 }
 public static void Verify(QueueConnection queueConnection, QueueProducerConfiguration queueProducerConfiguration, long messageCount, string route, ICreationScope scope)
 {
     new VerifyQueueData(queueConnection, queueProducerConfiguration.Options()).Verify(messageCount, route);
 }
Beispiel #30
0
 private void VerifyRoutes(Action <QueueConnection, QueueProducerConfiguration, long, string, ICreationScope> verify, QueueConnection arg1, QueueProducerConfiguration arg3, long arg4, string route, ICreationScope scope)
 {
     verify(arg1, arg3, arg4, route, scope);
 }
Beispiel #31
0
        static void Main(string[] args)
        {
            //we are using serilog for sample purposes
            var log = new LoggerConfiguration()
                      .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] [{SourceContext}] {Message:lj}{NewLine}{Exception}")
                      .MinimumLevel.Debug()
                      .CreateLogger();

            Log.Logger = log;
            log.Information("Startup");
            log.Information(SharedConfiguration.AllSettings);

            //verify that the queue exists
            var queueName        = ConfigurationManager.AppSettings.ReadSetting("QueueName");
            var connectionString = ConfigurationManager.AppSettings.ReadSetting("Database");
            var queueConnection  = new QueueConnection(queueName, connectionString);

            using (var createQueueContainer = new QueueCreationContainer <PostgreSqlMessageQueueInit>(serviceRegister =>
                                                                                                      Injectors.AddInjectors(Helpers.CreateForSerilog(), SharedConfiguration.EnableTrace, SharedConfiguration.EnableMetrics, SharedConfiguration.EnableCompression, SharedConfiguration.EnableEncryption, "PostgreSqlConsumer", serviceRegister)
                                                                                                      , options => Injectors.SetOptions(options, SharedConfiguration.EnableChaos)))
            {
                using (var createQueue =
                           createQueueContainer.GetQueueCreation <PostgreSqlMessageQueueCreation>(queueConnection))
                {
                    if (!createQueue.QueueExists)
                    {
                        //the consumer can't do anything if the queue hasn't been created
                        Log.Error($"Could not find {connectionString}. Verify that you have run the producer, which will create the queue");
                        return;
                    }
                }
            }

            using (var queueContainer = new QueueContainer <PostgreSqlMessageQueueInit>(serviceRegister =>
                                                                                        Injectors.AddInjectors(Helpers.CreateForSerilog(), SharedConfiguration.EnableTrace, SharedConfiguration.EnableMetrics, SharedConfiguration.EnableCompression, SharedConfiguration.EnableEncryption, "PostgreSqlConsumer", serviceRegister)
                                                                                        , options => Injectors.SetOptions(options, SharedConfiguration.EnableChaos)))
            {
                using (var queue = queueContainer.CreateConsumer(queueConnection))
                {
                    //set some processing options and start looking for work
                    queue.Configuration.Worker.WorkerCount    = 4;                        //lets run 4 worker threads
                    queue.Configuration.HeartBeat.UpdateTime  = "sec(*%10)";              //set a heartbeat every 10 seconds
                    queue.Configuration.HeartBeat.MonitorTime = TimeSpan.FromSeconds(15); //check for dead records every 15 seconds
                    queue.Configuration.HeartBeat.Time        = TimeSpan.FromSeconds(35); //records with no heartbeat after 35 seconds are considered dead

                    //an invalid data exception will be re-tried 3 times, with delays of 3, 6 and then finally 9 seconds
                    queue.Configuration.TransportConfiguration.RetryDelayBehavior.Add(typeof(InvalidDataException), new List <TimeSpan> {
                        TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(6), TimeSpan.FromSeconds(9)
                    });

                    queue.Configuration.MessageExpiration.Enabled     = true;
                    queue.Configuration.MessageExpiration.MonitorTime = TimeSpan.FromSeconds(20); //check for expired messages every 20 seconds
                    queue.Start <SimpleMessage>(MessageProcessing.HandleMessages);
                    Console.WriteLine("Processing messages - press any key to stop");
                    Console.ReadKey((true));
                }
            }

            //if jaeger is using udp, sometimes the messages get lost; there doesn't seem to be a flush() call ?
            if (SharedConfiguration.EnableTrace)
            {
                System.Threading.Thread.Sleep(2000);
            }
        }
Beispiel #32
0
        public void RunTest <TTransportInit, TMessage>(QueueConnection queueConnection,
                                                       bool addInterceptors,
                                                       int messageCount,
                                                       ILogger logProvider,
                                                       Func <QueueProducerConfiguration, AdditionalMessageData> generateData,
                                                       Action <QueueConnection, QueueProducerConfiguration, long, string, ICreationScope> verify,
                                                       bool sendViaBatch,
                                                       List <string> routes1,
                                                       List <string> routes2,
                                                       int runTime,
                                                       int timeOut,
                                                       int readerCount,
                                                       TimeSpan heartBeatTime,
                                                       TimeSpan heartBeatMonitorTime,
                                                       ICreationScope scope,
                                                       string updateTime, bool enableChaos)
            where TTransportInit : ITransportInit, new()
            where TMessage : class
        {
            //add data with routes - generate data per route passed in
            Parallel.ForEach(routes1, route =>
            {
                RunTest <TTransportInit, TMessage>(queueConnection, addInterceptors,
                                                   messageCount, logProvider, generateData, verify, sendViaBatch, route, scope, false);
            });

            Parallel.ForEach(routes2, route =>
            {
                RunTest <TTransportInit, TMessage>(queueConnection, addInterceptors,
                                                   messageCount, logProvider, generateData, verify, sendViaBatch, route, scope, false);
            });

            //run a consumer for each route
            using (var schedulerCreator = new SchedulerContainer())
            {
                var taskScheduler = schedulerCreator.CreateTaskScheduler();

                taskScheduler.Configuration.MaximumThreads = routes1.Count + routes2.Count;

                taskScheduler.Start();
                var taskFactory = schedulerCreator.CreateTaskFactory(taskScheduler);

                //spin up and process each route
                var running = new List <List <string> > {
                    routes1, routes2
                };
                Parallel.ForEach(running, route =>
                {
                    foreach (var route2 in route)
                    {
                        var consumer = new ConsumerAsyncShared <TMessage> {
                            Factory = taskFactory
                        };

                        consumer.RunConsumer <TTransportInit>(queueConnection, addInterceptors,
                                                              logProvider, runTime, messageCount, timeOut, readerCount, heartBeatTime,
                                                              heartBeatMonitorTime, updateTime, enableChaos, scope, route2);
                    }
                });
            }
        }
        /// <summary>
        /// Creates an async consumer queue that uses a task scheduler
        /// </summary>
        /// <param name="queueConnection">Queue and connection information.</param>
        /// <param name="factory">The task factory.</param>
        /// <param name="workGroup">The work group.</param>
        /// <returns></returns>
        public IConsumerQueueScheduler CreateConsumerQueueScheduler(QueueConnection queueConnection, ITaskFactory factory, IWorkGroup workGroup)
        {
            Guard.NotNull(() => queueConnection, queueConnection);

            return(CreateConsumerQueueSchedulerInternal(queueConnection, factory, workGroup, false));
        }
Beispiel #34
0
 /// <inheritdoc />
 public QueueCreationResult CreateJobSchedulerQueue(Action <IContainer> registerService, QueueConnection queueConnection, Action <IContainer> setOptions = null, bool enableRoute = false)
 {
     if (_queueCreation.Options.AdditionalColumns.Count == 0)
     {
         _queueCreation.Options.AdditionalColumns.Add(new Column("JobName", ColumnTypes.Varchar, 255, false));
         var constraint = new Constraint($"IX_{queueConnection.Queue}JobName", ConstraintType.Constraint,
                                         "JobName")
         {
             Unique = true
         };
         _queueCreation.Options.AdditionalConstraints.Add(constraint);
     }
     if (enableRoute)
     {
         _queueCreation.Options.EnableRoute = true;
     }
     return(_queueCreation.CreateQueue());
 }
        void RunConsumer <TTransportInit>(QueueConnection queueConnection,
                                          bool addInterceptors,
                                          ILogger logProvider,
                                          int runTime,
                                          int messageCount,
                                          int timeOut,
                                          int readerCount,
                                          TimeSpan heartBeatTime,
                                          TimeSpan heartBeatMonitorTime,
                                          Guid id,
                                          string updateTime,
                                          bool enableChaos, ICreationScope scope)
            where TTransportInit : ITransportInit, new()
        {
            if (enableChaos)
            {
                timeOut *= 2;
            }

            using (var trace = SharedSetup.CreateTrace("consumer"))
            {
                using (var metrics = new Metrics.Metrics(queueConnection.Queue))
                {
                    var addInterceptorConsumer = InterceptorAdding.No;
                    if (addInterceptors)
                    {
                        addInterceptorConsumer = InterceptorAdding.ConfigurationOnly;
                    }

                    using (
                        var creator = SharedSetup.CreateCreator <TTransportInit>(addInterceptorConsumer, logProvider,
                                                                                 metrics, false, enableChaos, scope, trace.Source)
                        )
                    {
                        using (
                            var queue =
                                creator
                                .CreateConsumerMethodQueueScheduler(
                                    queueConnection, Factory))
                        {
                            SharedSetup.SetupDefaultConsumerQueue(queue.Configuration, readerCount, heartBeatTime,
                                                                  heartBeatMonitorTime, updateTime, null);
                            queue.Start();
                            var counter = 0;
                            while (counter < timeOut)
                            {
                                if (MethodIncrementWrapper.Count(id) >= messageCount)
                                {
                                    break;
                                }

                                Thread.Sleep(1000);
                                counter++;
                            }
                        }

                        Assert.Equal(messageCount, MethodIncrementWrapper.Count(id));
                        VerifyMetrics.VerifyProcessedCount(queueConnection.Queue, metrics.GetCurrentMetrics(),
                                                           messageCount);
                        LoggerShared.CheckForErrors(queueConnection.Queue);
                    }
                }
            }
        }
Beispiel #36
0
 private void ValidateErrorCounts(QueueConnection queueConnection, int arg3, ICreationScope arg4)
 {
     new VerifyErrorCounts(queueConnection.Queue).Verify(arg3, 2);
 }
Beispiel #37
0
 private void VerifyQueueCount(QueueConnection queueConnection, IBaseTransportOptions arg3, ICreationScope arg4, int arg5, bool arg6, bool arg7)
 {
     new VerifyQueueRecordCount().Verify(arg4, 0, true);
 }
 public void Constructor()
 {
     var count = Substitute.For<IQueueCount>();
     var setup = new QueueConnection<object>();
     new StorageQueueAutoScaler<object>(count, setup);
 }