/// <summary> /// Tests that two SubscribedMessage are equal. /// </summary> /// <param name="expected"></param> /// <param name="actual"></param> protected void AssertSubscribedEquals(Model.SubscribedMessage expected, Model.SubscribedMessage actual) { if (expected == null && actual == null) { return; } Assert.IsNotNull(actual, "Actual is null, expected is not."); Assert.IsNotNull(expected, "Expected is null, actual is not."); Assert.AreEqual(expected.Headers, actual.Headers); Assert.AreEqual(expected.MessageId, actual.MessageId); AssertSqlDbDateTime(expected.NotBefore, actual.NotBefore); Assert.AreEqual(expected.Id, actual.Id); Assert.AreEqual(expected.Body, actual.Body); AssertSqlDbDateTime(expected.Completed, actual.Completed); AssertSqlDbDateTime(expected.Enqueued, actual.Enqueued); AssertSqlDbDateTime(expected.Failed, actual.Failed); Assert.AreEqual(expected.Retries, actual.Retries); Assert.AreEqual(expected.SubscriberId, actual.SubscriberId); AssertSqlDbDateTime(expected.ValidUntil, actual.ValidUntil); }
/// <summary> /// Publishes the message /// </summary> /// <param name="category"></param> /// <param name="type"></param> /// <param name="message"></param> /// <param name="notBefore"></param> /// <returns></returns> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="ArgumentException"></exception> public async Task Publish(string category, Type type, object message, DateTime?notBefore = null) { if (message == null) { throw new ArgumentNullException(nameof(message), $"{nameof(message)} must not be null."); } if (string.IsNullOrWhiteSpace(category)) { throw new ArgumentException($"{nameof(category)} must not be null and not empty."); } if (type == null) { throw new ArgumentNullException(nameof(type), $"{nameof(type)} must not be null."); } if (notBefore.HasValue && notBefore.Value.Kind == DateTimeKind.Unspecified) { throw new ArgumentException($"{nameof(notBefore)} must not have an Unspecified DateTimeKind.", nameof(notBefore)); } // expire any out of data subscribers so we don't waste resources // sending to subscribers that are not renewing their subscriptions. await _dataAccess.ExpireSubscriptions(); // get a list of all subscribers for the category var subscribers = await _dataAccess.GetSubscribers(category); // note the type in the headers so it can be deserialized. var headers = new Headers { MessageClass = type.FullName + ", " + type.Assembly.GetName().Name }; var validUntil = notBefore.HasValue ? notBefore.Value.ToUniversalTime().Add(_subscribedLifespan.Duration) : _clock.UtcNow.Add(_subscribedLifespan.Duration); var nb = notBefore.HasValue ? notBefore.Value.ToUniversalTime() : _clock.UtcNow; var headerstring = _serializer.SerializeHeaders(headers); var bodystring = _serializer.SerializeMessage(message, type); foreach (var subscriber in subscribers) { // create the message entity, serializing the headers and body. var sm = new Model.SubscribedMessage { ValidUntil = validUntil, SubscriberId = subscriber, MessageId = Guid.NewGuid(), NotBefore = nb, Enqueued = _clock.UtcNow, Completed = null, Failed = null, Retries = 0, Headers = headerstring, Body = bodystring }; await _dataAccess.AddMessage(sm); _counters.SentMessage(); } }