Versioning your MassTransit message contracts

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome back to the channel in this next installment on the mass transit message versioning I'm going to talk about some ways that we can version messages and go over a few scenarios I'm also going to get to some user questions around how to version ANS so first I'm going to start off with a new message type that I've added here called get order status and order status now this is a pretty simple type get order status you pass in an order ID and then I fill in some fluff that comes back uh I can simulate this in the UI I execute it and I get an order ID the order number and the status and that all goes through the message broker as expected now let's say that we've added some new capabilities to this consumer we add say that now we want to be able to put like an expected ship date okay well expected ship date doesn't exist yet because I haven't updated my contracts so let's go to my contracts let's go to my order status and let's put in a expected ship date this is just a value that lets us put some stuff out there um and we're going to get that extra piece of data now you'll notice this little noise down here just ignore that for now this is something system Tech Json gives us to do and it's actually pretty cool um but first I'm going to go update my contract I have to update my version number again because we have to go to Six we have to go and build it pack the nougat package because again we're sharing with nougat these aren't project references the code is directly using that nougat package so I've got to push that to my nougat repo I have to tell my Nate repo that I need to refresh because I just pushed a new 1.06 version and I'm going to not touch my API but I'm going to update my components to have the new version 106 cuz my API is in production it's deployed I'm not going to do anything with it I'm now going to go over to my order status consumer and I'm going to set my uh let's say date time . today plus time span. from dayss let's say it's going to take 3 days three days sounds like a good amount of time for something to ship I mean I'd be upset but you know we got the Amazon expectations but whatever so let's go run this so again my API is still running haven't touched it not a pee we're going to go ahead and rerun this service it's going to be up and running we're going to go back over to here and now I haven't touched this at all all I'm going to do is hit execute with the same thing and surprisingly that expected ship date shows up now it doesn't really show up because if I go into my controller and I try to use it like let's see here here's my response if I try to use response. message. expected ship dat it isn't there but that little hack for that data for that dictionary of string element this is a little trick with system text Json where you can basically say hey if you do serialized into this type and there are properties that I don't know how to handle just chunk them into this dictionary and then of course in my controller because I'm just serializing out that message J system text Json sees that extension data and says oh well I will chunk all that stuff back out to the client as well might be good might be bad it's just kind of a trick that you can use to push some data back to a system without having to know about everything but when I do go and update my controller so that I say have a downstream system that wants to use that expected ship date I have that first class property that I can deserialize it into so kind of a neat little feature and the transparency of how it just dumps it out in the same format it was there pretty slick stuff so that's the Json extension data and it needs to be a type of dictionary string Json element and it'll just do what it needs to do pretty cool thing so let's talk about another one of the things that we wanted to talk about let's say that I have my submit order command and my submit order command takes the current properties of order ID customer order number and customer number now let's say for whatever reason that the service needs to evolve because again this is a command so it's owned by the consumer that consumes this message so let's say that we want to add a new property in here to handle purchase order number now because this isn't originally required we don't want to require this so we know it's it's going to be null and we're going to say we're going to have a purchase order number now this could be anything I'm just using something that people can relate to uh and I've added a new purchase order number to that and I'm also going to update my order submitted because you know I I have this information now maybe I want to share it back out with people who use this contract so again because I'm updating here I'm going to update my new get I'm going to set it up to another version I'm going to go pack it I'm going to push it to my local Nate repository and then I'm going to go ahead and stop my order service here I'm going to update the nougat package for that service one more time again the API is still on five I haven't touched that it's in production nothing to see here but I'm going to go ahead and I'm going to update this to 107 because I'm in I'm incrementing the version number that I need for that because it's nullable it's still backwards compatible so I don't need to worry about that but within in the Pro submit order consumer now I have an additional piece of data here so first I want to add my purchase order number to contacts. message. purchase order number because I want to add that to my event but if I want to do some processing I need to check to see that it's there so like my normal order processing might be here but then I might say oh well if I know if if I could type if I know the order number so I could say like if context. message. purchase order and let's just use string. is null or empty and if it's not null or empty do the processing of this property because we might not have it we may not have a purchase order number because that API is still accepting orders from people who were never submitting a purchase order this is new Behavior but because it's nullable we always want to make sure that we can handle that Backward Compatible path this might mean that we have to go look up a purchase order number or see if there is one or just do something or flag it for followup with the accounts payable department anything could be possible there or accounts receivable Department I'm not an accountant obviously um so that's how we can handle the versioning of that now if we come in here and let's just say let's just do another uh simple little thing here let's just put it in the logger of the submit order consumer and let's go ahead and log out no purchase order provided and the reason we do that is just because we're just going to show that because there's no UI for that back in there's nothing really to see here so we're just going to run it so now we're going to run it we didn't change anything it didn't change the message contract if I go out to Rabbit mq and look at the submit order Q it's still only bound to that original submit order message that's the only one that it's consuming so when I come in here and look and I go back to my UI and let's go ahead and make sure I have let's go ahead and get my GD order number get that so I don't have to create it for twice so we're going to try this out we're going to pass in an order ID and an order number and we're going to pass in a customer number of whatever and we're going to submit that order at this point we've published the message we got a response the order ID uh well we just returned the order ID we didn't actually do anything with that but if we look here in our logs we see nothing why did we not see anything interesting is it actually running we go back here to the cues we can see it's there let's take a look here I'm fairly sure we process it we don't write any anything so oh no we do because we got the order ID back so we did get a response it's just for whatever reason the logger didn't write the warning don't know why we didn't pass one so crazy is it uh is it the controller let's look at the order controller so the order controller when we did the post submit order model request client get response order submission accepted okay I don't know why we didn't get the warning message but but we were able to submit it with the old version of the contract and it worked let's do it again see if it happens seems kind of odd to me but we'll do it again guess we number can have Springs in them right yeah so we got our order ID we got that I don't know why I didn't display the warning yeah oh well nothing I can do about it it should have but it didn't don't know why but nonetheless so that I'm still able to accept things with the old contract and it's able to return those back nothing broken nothing bad so that's just kind of a way to do it if I wanted to add integers or things that could also be optional definitely use nullable integers you know like int question mark or datetime question mark or any of those because then you can check if those properties are there and valid before you actually process the message so let's look at one more thing that we want to do we want to talk about someone asked a question how do I version in New and enes are a little tricky because they're kind of like closed collections it's like these are the valid values for an En so if I were to get a value back the anume wouldn't have it or know it and it would get an error deserializing so something to seriously consider before just jumping in and using an in your system um the one thing that I would say is and I created a message type for this here so let's see if we can do it so I created a process order command with an order priority and and I thought this would be just you know something completely separate order priority has default low and high I mean you can't get more basic than it than that kind of a new and then I have an order process and the order process just is a simple event it doesn't have any additional Types on it but my process order consumer is going to use those different um priorities to determine how quickly to process the order so with that in mind let's go ahead and just kind of run this as like a little demo case to kind of see what happens let me go ahead and fire these Services back up and I'm not going to start the backend service yet I'm going to just leave this one running because what I want to do is I want to come in here and I want to process this order and I want to process it with a priority of high and you'll notice I put the string high and I'll go over that in a second so I'm going to hit execute I get a response back that just says High nothing super fancy but I wanted to come over to Rabbit mq and give you kind of a view of what we see here so the message is sitting in the queue and if I look at this message we can see that the message is serialized within the envelope it has the or ID and the priority is written as two so by default mass transit is going to write your strings as number in news um you can change that behavior by configuring the mass transit serializer but I'm not going to do that for now because you know it's it's not what we're here to talk about the the other thing that I will point out is that when I configured this API service I added the Json string and converter to the options for asp.net system Tech Json serializer options so I added that converter to the list you do it very similar with mass transit you would say configure Json serializer and you get the options you would do the exact same thing as that so that's kind of the key piece of code to get them serialized as strings if you want that I just did it so that the UI and the API is more easy to understand and doesn't have to know magic magic numbers of two um yeah so anyway I'm going to start the service back up now and we should see it immediately come up and start processing that order with a high priority just like that is there so again service was offline but again rabbit mq durable messaging hello we got messages so let's say we want to add an enumeration value to that so let's go ahead and stop the service and I'm going to go into my contracts assembly yet again I'm going to make a version 8 cuz you know we like to keep incrementing our version and we're going to add a new priority called super low I don't know whatever super low and let's just call it three now our super low priority is going to be like super super slow whatever obviously it's super low but we're going to go to our consumer and then we're going to put a new case in here called super low but it doesn't exist yet we're going to say that that takes 30 seconds whatever um again because I've incremented my contracts I need to push this out I need to get it onto the local nou server I need to go to my nougats refresh my packages install version 8 you'll notice that my API is still on 1.0.5 I have not versioned my API to do any of this stuff yet it's still on the oldest version of the contracts that I could possibly have so now it compiles I've got my super low with my 30 seconds let's just say 20 why not right we're having some fun but now we're going to put this in here we're going to build that out and we are going to run our service again so with our service set up to go we're going to run it we've added this new capability but again our API hasn't changed it still has just the ability to do high because it doesn't know about super low if I execute that I I just expect it's going to kind of do its thing processing High just like we thought it would if I come in here and say normal we will see that it is going to eventually process one normal I think is it normal no it's not normal it's default so that's obviously not going to deserialize I don't know why the errors aren't showing up that's weird if I do yeah so default worked it's like something's not logging properly in the service that must be the problem um yeah priority default piece of cake the uh but I can't do super low because my API doesn't know about super low yet so if I try to do super low here it's going to blow up and say the model validation failed because that's not a valid order priority but if I do come in here stop my API service and let's say I finally get around to upgrading my API because I need to be able to call this new command I can upgrade that I can just literally rebuild redeploy and now we get the ability to do super low and super low comes back and if we go over to our service it processed super low so those are the ways that we can kind of version messages in a number of different ways I've gone over three or four different scenarios definitely make comments if you have questions or think there's things that I haven't covered there are probably some things I haven't covered but you know we're sharing messages through nugat you know we have decoupled systems order management frontend API we aren't required to update all the contracts every time the one other question I did get was how to do it with like feature management or feature toggles it's a little harder question and it goes into like how do you transfer that information around the system uh it goes into a lot of midw filters and headers and passing information around outside of messages but it is something that I'm willing to cover if there's enough interest although I really think I need to talk about feature management as a larger question um but anyway hopefully that was useful give you some ideas and we'll see you next time
Info
Channel: Chris Patterson
Views: 991
Rating: undefined out of 5
Keywords:
Id: PNNxJthctgk
Channel Id: undefined
Length: 16min 43sec (1003 seconds)
Published: Mon Apr 15 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.