/// <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); }
/// <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); } }
/// <summary> /// Starts processing messages. /// </summary> public override void Start() { var now = EnvironmentInfo.GetCurrentDateTimeUtc(); _nextTimeToRun = ScheduleInfo.NextTimeToRun(now); base.Start(); }
/// <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(); }
/// <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; } }
/// <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); } }
/// <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"); }
/// <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, }); } }
/// <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(); }
/// <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); }
/// <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); }
/// <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) { }
/// <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); }