public static void AssertOutboxItemMatchesReceivedItem( ISqlTransactionalOutboxItem <Guid> outboxItem, ISqlTransactionalOutboxReceivedItem <Guid, string> receivedItem ) { Assert.IsNotNull(outboxItem); Assert.IsNotNull(receivedItem); Assert.AreEqual(outboxItem.UniqueIdentifier, receivedItem.UniqueIdentifier); Assert.AreEqual(outboxItem.FifoGroupingIdentifier, receivedItem.FifoGroupingIdentifier); Assert.AreEqual(OutboxReceivedItemProcessingStatus.AcknowledgeSuccessfulReceipt, receivedItem.Status); var publishedItem = receivedItem.PublishedItem; //Received Items should always be Successful Assert.AreEqual(OutboxItemStatus.Successful, publishedItem.Status); Assert.AreEqual(outboxItem.UniqueIdentifier, publishedItem.UniqueIdentifier); Assert.AreEqual(outboxItem.FifoGroupingIdentifier, publishedItem.FifoGroupingIdentifier); Assert.AreEqual(outboxItem.PublishTarget, publishedItem.PublishTarget); //Publishing process should increment the PublishAttempt by 1 Assert.AreEqual(outboxItem.PublishAttempts + 1, publishedItem.PublishAttempts); //Extract the Body from the original OutboxItem to compare (apples to apples) to the received item from // being published where the Payload would be automatically populated from the Body property mapping. var payloadBuilder = PayloadBuilder.FromJsonSafely(outboxItem.Payload); Assert.AreEqual(payloadBuilder.Body, publishedItem.Payload); //Dates need to be compared at the Millisecond level due to minute differences in Ticks when re-parsing(?)... Assert.AreEqual(0, (int)(publishedItem.CreatedDateTimeUtc - outboxItem.CreatedDateTimeUtc).TotalMilliseconds, "The Created Dates differ at the Millisecond level" ); }
/// <summary> /// Convenience method for adding a completely dynamic JSON payload item easily to the Outbox. Using this approach /// is highly flexible as the payload can control the Outbox and publishing process in very dynamic way; /// any failed validation of required fields will result in exceptions. /// This will parse and process the json payload with the Transactional Outbox using Default implementations (e.g. GUID identifier). /// This method will create and commit the Transaction automatically, but may error if a running transaction /// is already in progress in which case the custom extension of the Transaction should be used directly instead. /// </summary> /// <param name="sqlConnection"></param> /// <param name="jsonText"></param> /// <param name="publishTopic"></param> /// <param name="fifoGroupingIdentifier"></param> /// <returns></returns> public static async Task <ISqlTransactionalOutboxItem <Guid> > AddTransactionalOutboxPendingItemAsync( this SqlConnection sqlConnection, string jsonText, string publishTopic = null, string fifoGroupingIdentifier = null ) { var payloadBuilder = PayloadBuilder.FromJsonSafely(jsonText); //Publishing Target may be defined in the Payload OR as a discrete parameter that overrides the payload, // but it is REQUIRED! var publishingTarget = publishTopic ?? payloadBuilder.PublishTarget; publishingTarget.AssertNotNullOrWhiteSpace(nameof(payloadBuilder.PublishTarget), "No Publishing Topic was defined in the Payload or as a parameter."); //FIFO Grouping Identifier may be defined in the Payload OR as a discrete parameter that overrides the payload, // but it is OPTIONAL. var fifoGroupId = fifoGroupingIdentifier ?? payloadBuilder.FifoGroupingId; var results = await sqlConnection .AddTransactionalOutboxPendingItemAsync( publishingTarget, payloadBuilder.ToJObject(), fifoGroupId ) .ConfigureAwait(false); return(results); }
public void TestPayloadBuilderFromJsonToJObject() { var jsonText = $@" {{ ""publishTopic"": ""{TestConfiguration.AzureServiceBusTopic}"", ""fifoGroupingId"": ""HttpProxy-IntegrationTest"", ""to"": ""CajunCoding"", ""body"": ""Testing Json Payload from HttpProxy"" }} "; var payloadBuilder = PayloadBuilder.FromJsonSafely(jsonText); var jsonPayload = payloadBuilder.ToJObject(); Assert.AreEqual(TestConfiguration.AzureServiceBusTopic, jsonPayload.ValueSafely <string>(nameof(PayloadBuilder.PublishTarget))); Assert.AreEqual("HttpProxy-IntegrationTest", jsonPayload.ValueSafely <string>(nameof(PayloadBuilder.FifoGroupingId))); Assert.AreEqual("CajunCoding", jsonPayload.ValueSafely <string>(nameof(PayloadBuilder.To))); Assert.AreEqual("Testing Json Payload from HttpProxy", jsonPayload.ValueSafely <string>(nameof(PayloadBuilder.Body))); }
public void TestPayloadBuilderFromJsonWithPlainTextBody() { //TODO: Add ALL Field options... var jsonText = $@" {{ ""topic"": ""{TestConfiguration.AzureServiceBusTopic}"", ""fifoGroupingId"": ""HttpProxy-IntegrationTest"", ""to"": ""CajunCoding"", ""body"": ""Testing Json Payload from HttpProxy"" }} "; var payloadBuilder = PayloadBuilder.FromJsonSafely(jsonText); Assert.AreEqual(TestConfiguration.AzureServiceBusTopic, payloadBuilder.PublishTarget); Assert.AreEqual("HttpProxy-IntegrationTest", payloadBuilder.FifoGroupingId); Assert.AreEqual("CajunCoding", payloadBuilder.To); Assert.AreEqual("Testing Json Payload from HttpProxy", payloadBuilder.Body); }
public async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, ILogger log) { log.LogInformation($"HTTP [{nameof(TransactionalOutboxHttpProxySendPayloadFunction)}]."); var configSettings = new SampleAppConfig(); //Initialize the Payload from the Body as Json! var jsonText = await req.ReadAsStringAsync(); var payloadBuilder = PayloadBuilder.FromJsonSafely(jsonText); //Apply fallback values from the QueryString //NOTE: this will only set values not already initialized from Json! var queryLookup = req.Query.ToLookup(k => k.Key, v => v.Value.FirstOrDefault()); payloadBuilder.ApplyValues(queryLookup, false); await using var sqlConnection = new SqlConnection(configSettings.SqlConnectionString); await sqlConnection.OpenAsync(); //************************************************************ //*** Add The Payload to our Outbox //************************************************************ var outboxItem = await sqlConnection.AddTransactionalOutboxPendingItemAsync( publishTarget : payloadBuilder.PublishTarget, payload : payloadBuilder.ToJObject(), //It's always a good idea to ensure that a FIFO Group Id/Name is specified for any FIFO Subscriptions that may receive the messages... fifoGroupingIdentifier : payloadBuilder.FifoGroupingId ?? "DefaultFifoGroup" ).ConfigureAwait(false); //Log results and return response to the client... log.LogDebug($"Payload:{Environment.NewLine}{outboxItem.Payload}"); return(new ContentResult() { Content = outboxItem.Payload, ContentType = MessageContentTypes.Json, StatusCode = (int)HttpStatusCode.OK }); }