예제 #1
0
        /// <summary>
        /// This method is called before the body of the aspected method is about to be
        /// invoked.
        /// </summary>
        /// <param name="args">Descriptor representing the method call</param>
        /// <param name="result">Result descriptor coming from the previous aspect.</param>
        /// <returns>
        /// This method should return null value indicating that the aspected method's body should
        /// be called. If the method body invocation should be omitted, this method returns the
        /// result descriptor substituting the result coming from the invocation of the method body.
        /// </returns>
        public override IMethodResultDescriptor OnEntry(IMethodCallDescriptor args, IMethodResultDescriptor result)
        {
            if (args.Method.DeclaringType == typeof(IServiceObject))
            {
                return(null);
            }

            CallContext.LogicalSetData(START_TICK_LABEL, EnvironmentInfo.GetCurrentDateTimeUtc().Ticks);
            var details    = new StringBuilder();
            var traceAttrs = args.Method.GetCustomAttributes(typeof(NoArgumentTraceAttribute), true);

            if (traceAttrs.Length == 0)
            {
                for (var i = 0; i < args.ArgumentCount; i++)
                {
                    var arg     = args.GetArgument(i);
                    var argJson = JsonConvert.SerializeObject(arg.Value);
                    details.AppendFormat("{0}: {1}\r\n", arg.Name, argJson);
                }
            }

            var logItem = new TraceLogItem
            {
                Type            = TraceLogItemType.Informational,
                OperationType   = GetOperationName(args),
                Message         = "Enter",
                DetailedMessage = details.ToString()
            };

            Tracer.Log(logItem);
            return(null);
        }
예제 #2
0
 /// <summary>
 /// Gets messages from the queue.
 /// </summary>
 /// <param name="numberOfMessages">Number of messages to retrieve from the queue</param>
 /// <param name="visibilityTimeoutInSeconds">
 /// Timeot while messages are invisible for other GetMessages requests</param>
 /// <returns>The collection of messages obtained from the queue.</returns>
 public IEnumerable <IPoppedMessage> GetMessages(int numberOfMessages, int visibilityTimeoutInSeconds)
 {
     CheckIfDeleted();
     lock (_locker)
     {
         var now    = EnvironmentInfo.GetCurrentDateTimeUtc();
         var result = (from m in _messages
                       where m.NextVisibleTime <now && m.ExpirationTime> now
                       orderby m.InsertionTime descending
                       select m).Take(numberOfMessages).ToList();
         var copyResult = new List <MemoryPoppedMessage>();
         foreach (var message in result)
         {
             message.DequeueCount++;
             message.PopReceipt      = Guid.NewGuid().ToString();
             message.NextVisibleTime = now.AddSeconds(visibilityTimeoutInSeconds);
             var copyAdd = new MemoryPoppedMessage
             {
                 DequeueCount    = message.DequeueCount,
                 ExpirationTime  = message.ExpirationTime,
                 Id              = message.Id,
                 InsertionTime   = message.InsertionTime,
                 MessageText     = message.MessageText,
                 PopReceipt      = message.PopReceipt,
                 NextVisibleTime = message.NextVisibleTime
             };
             copyResult.Add(copyAdd);
         }
         return(copyResult);
     }
 }
예제 #3
0
        /// <summary>
        /// Starts processing messages.
        /// </summary>
        public override void Start()
        {
            var now = EnvironmentInfo.GetCurrentDateTimeUtc();

            _nextTimeToRun = ScheduleInfo.NextTimeToRun(now);
            base.Start();
        }
예제 #4
0
        /// <summary>
        /// You mark the given amount of messages as invisible until the visibilityTimeoutInSeconds. You can freely process the messages then. All messages get a GUID named PopReceipt in the database
        /// </summary>
        /// <param name="numberOfMessages">The amount of messages you want to process</param>
        /// <param name="visibilityTimeoutInSeconds">The time you ask to process the data in seconds</param>
        /// <returns></returns>
        public IEnumerable <IPoppedMessage> GetMessages(int numberOfMessages, int visibilityTimeoutInSeconds)
        {
            List <IPoppedMessage> returnlist;

            using (var conn = SqlHelper.CreateSqlConnection(Provider.NameOrConnectionString))
            {
                conn.Open();
                using (var command = new SqlCommand())
                {
                    command.Connection = conn;
                    command.Parameters.Add("@dequeueCount", SqlDbType.Int).Value           = numberOfMessages;
                    command.Parameters.Add("@newVisibilityTime", SqlDbType.DateTime).Value =
                        EnvironmentInfo.GetCurrentDateTimeUtc().AddSeconds(visibilityTimeoutInSeconds);
                    command.Parameters.Add("@queueId", SqlDbType.Int).Value          = Id;
                    command.Parameters.Add("@currentTime", SqlDbType.DateTime).Value =
                        EnvironmentInfo.GetCurrentDateTimeUtc();
                    command.CommandText = GetDequeueMessagesSql();
                    using (var reader = command.ExecuteReader())
                    {
                        returnlist = new List <IPoppedMessage>();
                        while (reader.Read())
                        {
                            returnlist.Add(new SqlPoppedMessage(
                                               new SqlQueuedMessage(
                                                   reader.GetString(6),
                                                   reader.GetGuid(2).ToString(),
                                                   reader.GetDateTime(3),
                                                   reader.GetDateTime(4),
                                                   reader.GetInt32(5)
                                                   ),
                                               visibilityTimeoutInSeconds,
                                               reader.GetGuid(7).ToString()));
                        }
                        reader.Close();

                        if (returnlist.Count == 0)
                        {
                            using (var doesExistCommand = new SqlCommand())
                            {
                                doesExistCommand.Connection = conn;
                                doesExistCommand.Parameters.Add("@queueid", SqlDbType.Int).Value = Id;
                                doesExistCommand.CommandText = GetSelectQueueSql();
                                using (var reader2 = doesExistCommand.ExecuteReader())
                                {
                                    if (reader2.HasRows == false)
                                    {
                                        throw new InvalidOperationException("The queue was already deleted");
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return(returnlist);
        }
        public void GetCurrentDateTimeUtcWorksAsExpected()
        {
            // --- Arrange
            EnvironmentInfo.Reset();

            // --- Act
            var utcNow = EnvironmentInfo.GetCurrentDateTimeUtc();

            // --- Assert
            ((DateTime.UtcNow - utcNow) < TimeSpan.FromMilliseconds(100)).ShouldBeTrue();
        }
예제 #6
0
        /// <summary>
        /// Processes tasks that are ready to run.
        /// </summary>
        protected override void ProcessTasks()
        {
            // --- Create the task, and dispose it when processed
            using (var newTask = new TTask())
            {
                var success   = true;
                var stopwatch = new Stopwatch();
                try
                {
                    stopwatch.Restart();

                    // --- Setup with graceful cancellation
                    if (ShouldStopTaskProcessing)
                    {
                        return;
                    }
                    newTask.Setup(Context);

                    // --- Run with graceful cancellation
                    CancellationToken.ThrowIfCancellationRequested();
                    newTask.Run();
                    NumTasksPmc.Increment();
                    NumTasksPerSecondPmc.Increment();
                }
                catch (OperationCanceledException ex)
                {
                    // --- The message procession canceled, log this failure.
                    WindowsEventLogger.Log <TaskExecutionInterrupted>(
                        "Task execution interrupted while processing a scheduled task.", ex);
                    success = false;
                }
                catch (Exception ex)
                {
                    // --- The message procession failed, log this failure.
                    WindowsEventLogger.Log <TaskExecutionFailed>(
                        "Task execution failed while processing scheduled task.", ex);
                    success = false;
                }
                finally
                {
                    // --- Set up the next time when the task should run
                    _nextTimeToRun = ScheduleInfo.NextTimeToRun(EnvironmentInfo.GetCurrentDateTimeUtc());
                }
                stopwatch.Stop();
                if (!success)
                {
                    NumFailuresPmc.Increment();
                    NumFailuresPerSecondPmc.Increment();
                }
                LastProcessTimePmc.RawValue = (int)stopwatch.ElapsedMilliseconds;
            }
        }
예제 #7
0
 /// <summary>
 /// Checks the queue for messages without locking or removing the messages from the queue.
 /// </summary>
 /// <param name="numberOfMessages">Number of messages to peek it the queue</param>
 /// <returns>The collection of messages obtained from the queue.</returns>
 public IEnumerable <IQueuedMessage> PeekMessages(int numberOfMessages)
 {
     CheckIfDeleted();
     lock (_locker)
     {
         var now    = EnvironmentInfo.GetCurrentDateTimeUtc();
         var result = (from m in _messages
                       where m.NextVisibleTime <now && m.ExpirationTime> now
                       orderby m.InsertionTime descending
                       select m).Take(numberOfMessages).ToList();
         return(result);
     }
 }
예제 #8
0
 /// <summary>
 /// Deletes the specified message from the queue.
 /// </summary>
 /// <param name="poppedMessage">Message to delete from the queue</param>
 public void DeleteMessage(IPoppedMessage poppedMessage)
 {
     CheckIfDeleted();
     lock (_locker)
     {
         var message = _messages.Single(m => m.Id == poppedMessage.Id &&
                                        m.PopReceipt == poppedMessage.PopReceipt &&
                                        m.NextVisibleTime >= EnvironmentInfo.GetCurrentDateTimeUtc());
         if (message != null)
         {
             _messages.Remove(message);
         }
     }
 }
        public void ConfigureWorksAsExpected()
        {
            // --- Arrange
            EnvironmentInfo.Reset();

            // --- Act
            EnvironmentInfo.Configure(new MockEnvironpentInfoProvider());
            var utcNow      = EnvironmentInfo.GetCurrentDateTimeUtc();
            var machineName = EnvironmentInfo.GetMachineName();

            // --- Assert
            EnvironmentInfo.Provider.ShouldBeOfType(typeof(MockEnvironpentInfoProvider));
            utcNow.ShouldEqual(new DateTime(2012, 1, 1, 0, 0, 0, DateTimeKind.Utc));
            machineName.ShouldEqual("DummyMachine");
        }
예제 #10
0
 /// <summary>
 /// Puts a new message to the queue.
 /// </summary>
 /// <param name="content">Message content</param>
 /// <param name="timeToLiveInSeconds">Time to live in seconds</param>
 public void PutMessage(string content, int timeToLiveInSeconds)
 {
     CheckIfDeleted();
     lock (_locker)
     {
         _messages.Add(new MemoryPoppedMessage
         {
             MessageText     = content,
             ExpirationTime  = EnvironmentInfo.GetCurrentDateTimeUtc().AddSeconds(timeToLiveInSeconds),
             DequeueCount    = 0,
             InsertionTime   = EnvironmentInfo.GetCurrentDateTimeUtc(),
             Id              = Guid.NewGuid().ToString(),
             PopReceipt      = null,
             NextVisibleTime = DateTime.MinValue,
         });
     }
 }
예제 #11
0
        /// <summary>
        /// Fills up properties that are not defined explicitly.
        /// </summary>
        public void EnsureProperties()
        {
            // --- Provide a timestamp
            if (!TimestampUtc.HasValue)
            {
                TimestampUtc = EnvironmentInfo.GetCurrentDateTimeUtc().ToLocalTime();
            }

            // --- Provide the current machine's name as server name
            if (ServerName == null)
            {
                ServerName = EnvironmentInfo.GetMachineName();
            }

            // --- Provide thread information
            if (!ThreadId.HasValue)
            {
                ThreadId = Thread.CurrentThread.ManagedThreadId;
            }
        }
        /// <summary>
        /// Gets the specified value from the cache.
        /// </summary>
        /// <param name="key">Object key</param>
        /// <returns>The object obtained from the cache</returns>
        /// <exception cref="KeyNotFoundException">
        /// Object with the specified key is not in the cache
        /// </exception>
        public TValue GetValue(TKey key)
        {
            Tuple <TValue, DateTime> outValue;
            var found = _cache.TryGetValue(key, out outValue);

            // --- Check if item is in the cache
            if (!found)
            {
                throw new KeyNotFoundException();
            }

            // --- Check if item is still valid
            if (outValue.Item2 > EnvironmentInfo.GetCurrentDateTimeUtc())
            {
                return(outValue.Item1);
            }

            // --- Item expires
            _cache.TryRemove(key, out outValue);
            throw new KeyNotFoundException();
        }
예제 #13
0
 /// <summary>
 /// This function communicates with the database directly. Most of the message attributes in the
 /// database are generated or gained from the queue itself.
 /// </summary>
 /// <param name="content">The content(text) of the message</param>
 /// <param name="timeToLiveInSeconds">
 /// The worker threads will try to process your message till
 /// current time delayed by this parameter. After that, your message is dropped
 /// </param>
 public void PutMessage(string content, int timeToLiveInSeconds)
 {
     using (var conn = SqlHelper.CreateSqlConnection(Provider.NameOrConnectionString))
     {
         conn.Open();
         using (var command = new SqlCommand())
         {
             command.Connection = conn;
             command.Parameters.Add("@queueid", SqlDbType.Int).Value = Id;
             command.Parameters.Add("@visibilitystarttime", SqlDbType.DateTime).Value =
                 EnvironmentInfo.GetCurrentDateTimeUtc();
             command.Parameters.Add("@messageid", SqlDbType.UniqueIdentifier).Value = Guid.NewGuid();
             command.Parameters.Add("@expitytime", SqlDbType.DateTime).Value        =
                 EnvironmentInfo.GetCurrentDateTimeUtc().AddSeconds(timeToLiveInSeconds);
             command.Parameters.Add("@insertiontime", SqlDbType.DateTime).Value =
                 EnvironmentInfo.GetCurrentDateTimeUtc();
             command.Parameters.Add("@dequeuecount", SqlDbType.Int).Value = 0;
             command.Parameters.Add("@data", SqlDbType.NVarChar).Value    = content;
             command.CommandText = GetInsertMessageSql();
             command.ExecuteNonQuery();
         }
     }
 }
        /// <summary>
        /// Tries to obtain the specified value from the cache
        /// </summary>
        /// <param name="key">Object key</param>
        /// <param name="value">The value, if found in the cahce</param>
        /// <returns>True, if the object has been found in the cache; otherwise, false</returns>
        public bool TryGetValue(TKey key, out TValue value)
        {
            Tuple <TValue, DateTime> outValue;
            var found = _cache.TryGetValue(key, out outValue);

            value = default(TValue);

            // --- Check if item is in the cache
            if (!found)
            {
                return(false);
            }

            // --- Check if item is still valid
            if (outValue.Item2 > EnvironmentInfo.GetCurrentDateTimeUtc())
            {
                value = outValue.Item1;
                return(true);
            }

            // --- Item expires
            _cache.TryRemove(key, out outValue);
            return(false);
        }
예제 #15
0
        /// <summary>
        /// This method is called right after <see cref="IMethodAspect.OnExit"/>, when the method body
        /// invocation was successful. Otherwise, the <see cref="IMethodAspect.OnException"/> method is
        /// called.
        /// </summary>
        /// <param name="args">Descriptor representing the method call</param>
        /// <param name="result">Result descriptor representing the return values of the call</param>
        /// <returns>
        /// This method should return the value of <paramref name="result"/> by default, or it
        /// can modify the original result on return that value.
        /// </returns>
        public override IMethodResultDescriptor OnSuccess(IMethodCallDescriptor args, IMethodResultDescriptor result)
        {
            if (args.Method.DeclaringType == typeof(IServiceObject))
            {
                return(null);
            }

            var startTimeData = CallContext.GetData(START_TICK_LABEL);
            var timeSpan      = startTimeData == null
                ? (TimeSpan?)null
                : TimeSpan.FromTicks(EnvironmentInfo.GetCurrentDateTimeUtc().Ticks - (long)startTimeData);

            var logItem = new TraceLogItem
            {
                Type            = TraceLogItemType.Success,
                OperationType   = GetOperationName(args),
                Message         = "Exit",
                DetailedMessage = string.Format("({0} ms)",
                                                timeSpan.HasValue ? timeSpan.Value.Milliseconds.ToString(CultureInfo.InvariantCulture) : "??")
            };

            Tracer.Log(logItem);
            return(result);
        }
예제 #16
0
 /// <summary>
 /// </summary>
 /// <param name="messageText">The data/text of the message</param>
 /// <param name="id">The messageid property column in the database</param>
 /// <param name="timetoliveinseconds">The message should be processed until this time is up</param>
 /// <param name="insertionTime">The date of the insertion into the queue</param>
 /// <param name="dequeueCount">It shows that how much times the message was gotten out of the queue</param>
 public SqlQueuedMessage(string messageText, string id, int timetoliveinseconds,
                         DateTime insertionTime, int dequeueCount) :
     this(messageText, id, EnvironmentInfo.GetCurrentDateTimeUtc()
          .AddSeconds(timetoliveinseconds), insertionTime, dequeueCount)
 {
 }
예제 #17
0
        /// <summary>
        /// Checks wether there is any task to execute
        /// </summary>
        /// <returns>
        /// True, if there is any task that can be executed; otherwise, false.
        /// </returns>
        protected override bool HasAnyTaskToExecute()
        {
            var now = EnvironmentInfo.GetCurrentDateTimeUtc();

            return((_nextTimeToRun - now) < _epsilon);
        }
 /// <summary>
 /// Puts the object with the specified key into the cache.
 /// </summary>
 /// <param name="key">Object key</param>
 /// <param name="value">Object value</param>
 public void SetValue(TKey key, TValue value)
 {
     _cache[key] = new Tuple <TValue, DateTime>(value, EnvironmentInfo.GetCurrentDateTimeUtc() + ExpirationTimeSpan);
 }