Example #1
0
        /// <inheritdoc />
        protected override async Task <IEnumerable <QueuedMessage> > GetPendingMessages(CancellationToken cancellationToken = new CancellationToken())
        {
            var pendingMessages = new List <QueuedMessage>();
            var files           = _directory.EnumerateFiles("*.pmsg");

            foreach (var file in files)
            {
                try
                {
                    var messageFile = new MessageFile(file);
                    var message     = await messageFile.ReadMessage(cancellationToken);

                    if (message.IsEncrypted() && _messageEncryptionService != null)
                    {
                        message = await _messageEncryptionService.Decrypt(message);
                    }
                    var principal = await _securityTokenService.NullSafeValidate(message.Headers.SecurityToken);

                    var queuedMessage = new QueuedMessage(message, principal);
                    pendingMessages.Add(queuedMessage);
                }
                catch (Exception ex)
                {
                    DiagnosticService.Emit(new FilesystemEventBuilder(this, FilesystemEventType.MessageFileFormatError)
                    {
                        Detail    = "Error reading previously queued message file; skipping",
                        Path      = file.FullName,
                        Exception = ex
                    }.Build());
                }
            }
            return(pendingMessages);
        }
Example #2
0
        public async Task Given_ClaimsPrincipal_When_Reading_Principal_Should_Be_Read()
        {
            var tempDir = GetTempDirectory();
            var queueName = new QueueName(Guid.NewGuid().ToString());
            var queuePath = Path.Combine(tempDir.FullName, queueName);
            var queueDir = new DirectoryInfo(queuePath);
            if (!queueDir.Exists)
            {
                queueDir.Create();
            }

            var message = new Message(new MessageHeaders
            {
                {HeaderName.ContentType, "text/plain"},
                {HeaderName.MessageId, Guid.NewGuid().ToString()}
            }, "Hello, world!");

            var senderPrincipal = new ClaimsPrincipal(new ClaimsIdentity(new[]
            {
                new Claim("username", "testuser"),
                new Claim("role", "testrole")
            }));

            var file = (await MessageFile.Create(queueDir, message, senderPrincipal)).File;
            var messageFile = new MessageFile(file);
            var readSenderPrincipal = await messageFile.ReadSenderPrincipal();
            var readMessage = await messageFile.ReadMessage();

            Assert.That(readSenderPrincipal, Is.EqualTo(senderPrincipal).Using(new ClaimsPrincipalEqualityComparer()));
            Assert.That(readMessage, Is.EqualTo(message).Using(new MessageEqualityComparer()));
        }
Example #3
0
        private async Task MoveToDeadLetterDirectory(QueuedMessage queuedMessage)
        {
            var message       = queuedMessage.Message;
            var headers       = message.Headers;
            var pattern       = headers.MessageId + "*.pmsg";
            var matchingFiles = _directory.EnumerateFiles(pattern);

            foreach (var matchingFile in matchingFiles)
            {
                var messageFile = new MessageFile(matchingFile);
                var deadLetter  = await messageFile.MoveTo(_deadLetterDirectory);

                await DiagnosticService.EmitAsync(
                    new FilesystemEventBuilder(this, DiagnosticEventType.DeadLetter)
                {
                    Detail  = "Message file deleted",
                    Message = message,
                    Queue   = QueueName,
                    Path    = deadLetter.File.FullName
                }.Build());
            }
        }
Example #4
0
        private async Task CreateMessageFile(QueuedMessage queuedMessage)
        {
            var message       = queuedMessage.Message;
            var principal     = queuedMessage.Principal;
            var securityToken = await _securityTokenService.NullSafeIssue(principal, message.Headers.Expires);

            var storedMessage = message.WithSecurityToken(securityToken);

            if (_messageEncryptionService != null)
            {
                storedMessage = await _messageEncryptionService.Encrypt(storedMessage);
            }
            var messageFile = await MessageFile.Create(_directory, storedMessage);

            await DiagnosticService.EmitAsync(
                new FilesystemEventBuilder(this, FilesystemEventType.MessageFileCreated)
            {
                Detail  = "Message file created",
                Message = message,
                Queue   = QueueName,
                Path    = messageFile.File.FullName
            }.Build());
        }
 public FilesystemQueuedMessageContext(MessageFile queuedMessage)
 {
     _queuedMessage = queuedMessage;
 }
        // ReSharper disable once UnusedMethodReturnValue.Local
        private async Task ProcessQueuedMessage(MessageFile queuedMessage, CancellationToken cancellationToken)
        {
            var attemptCount = 0;
            var deadLetter = false;
            // ReSharper disable once ConditionIsAlwaysTrueOrFalse
            while (!deadLetter && attemptCount < _maxAttempts)
            {
                attemptCount++;

                Log.DebugFormat("Processing queued message {0} (attempt {1} of {2})...",
                    queuedMessage.File,
                    attemptCount,
                    _maxAttempts);

                var context = new FilesystemQueuedMessageContext(queuedMessage);
                cancellationToken.ThrowIfCancellationRequested();

                await _concurrentMessageProcessingSlot.WaitAsync(cancellationToken);
                cancellationToken.ThrowIfCancellationRequested();

                try
                {
                    var message = await queuedMessage.ReadMessage(cancellationToken);
                    await _listener.MessageReceived(message, context, cancellationToken);
                    if (_autoAcknowledge && !context.Acknowledged)
                    {
                        await context.Acknowledge();
                    }
                }
                catch (MessageFileFormatException ex)
                {
                    Log.ErrorFormat("Unable to read invalid or corrupt message file {0}", ex, ex.Path);
                    deadLetter = true;
                }
                catch (Exception ex)
                {
                    Log.WarnFormat("Unhandled exception handling queued message file {0}", ex, queuedMessage.File);
                }
                finally
                {
                    _concurrentMessageProcessingSlot.Release();
                }

                if (context.Acknowledged)
                {
                    Log.DebugFormat("Message acknowledged.  Deleting message file {0}...", queuedMessage.File);
                    // TODO: Implement journaling
                    await queuedMessage.Delete(cancellationToken);
                    Log.DebugFormat("Message file {0} deleted successfully", queuedMessage.File);
                    return;
                }

                // TODO: Use TTL/Expiry instead of max attempts per queue
                if (attemptCount >= _maxAttempts)
                {
                    Log.WarnFormat("Maximum attempts to proces message file {0} exceeded", queuedMessage.File);
                    deadLetter = true;
                }

                if (deadLetter)
                {
                    await queuedMessage.MoveTo(_deadLetterDirectory, cancellationToken);
                    return;
                }

                Log.DebugFormat("Message not acknowledged.  Retrying in {0}...", _retryDelay);
                await Task.Delay(_retryDelay, cancellationToken);
            }
        }
 private async Task EnqueueExistingFiles(CancellationToken cancellationToken)
 {
     var files = _directory.EnumerateFiles();
     foreach (var file in files)
     {
         Log.DebugFormat("Enqueueing existing message from file {0}...", file);
         var queuedMessage = new MessageFile(file);
         await _queuedMessages.SendAsync(queuedMessage, cancellationToken);
     }
 }