Microsoft Azure Web Jobs: The new way to run your workloads in the Cloud
Mårtensson, Magnus
The new Web Job in the Microsoft Azure Platforms allows you to run background workloads easily and effortlessly as support for your Microsoft Azure Web Sites or other web-facing assets. The service has powerful monitoring and logging capabilities built into the Microsoft Azure Portal allowing you full control of what jobs have executed, are executing and will execute. Another very tasty fact about Web Jobs is that they may be programmed without any knowledge of the Cloud paradigm at all enabling any developer to build them in C#, PHP or as a simple command script. Deploying and monitoring Web Jobs is an operations task which allows for good separation between dev and ops. Let’s have a look at this new delicious service in Microsoft Azure which will change the way you think about Cloud based workloads.
 So Tech Guy says everything is good to go. Sweet. I'm on the screen. Maybe we should get started. Let's do that. Hi. Welcome. Welcome to this, the last session slot of the day. I appreciate you guys being in this room because obviously it means that you are really passionate about being at this presentation. There are some other really good ones going on at the same time, so I appreciate your attendance. I will do my best to entertain. I just want to check with you. Are you running any workloads in Azure at this time? Hands up. Most of you are. Are you running web apps? Okay. So anyone running the web jobs? One guy. All right. That's great. That's great. That's a good baseline for this talk. Now I know what you're all about. You look like a pretty intelligent bunch. So when you leave here, I know the answer to that really strange question. They're asking by the door. There are three colors. Anyone colorblind? No? Okay, good. The answer is green, just so you know. Making sure you know this. Okay, cool. So web jobs that I'm going to talk about is basically background processing in your Azure web apps. That's what it is, right? And means that it's part of the Azure app service. You got the logic apps and all those things you can do. But it's kind of cool because it's baked in there so you don't have to, you don't pay any extra to run this stuff. And also it means that if you have something simple, something batch processing like that is simple that you want to run, you can run that in web jobs. And it's a simple batch. It's sort of italic here in this slide because that was the code name for web jobs when they were building it. All right. My name is Magnus. Martin Sonam from Sweden, from Malmo. So I could go with Swedish Norwegian but I guess there are some people here who are not from Norway. Anyone not from Norway? Yes, several. So we'll stick to English of course. If there is anything at all, like don't hesitate to send me an email and ask, you know, about this session or, you know, about Azure actually. Because Azure is what I do. I'm also an MVP for Azure. I was the first one to be an Azure MVP in the Nordic countries. And I'm also what Microsoft call a regional director, which kind of means that they're still not paying me unfortunately. But they kind of like having me around. So I'm a business partner of Microsoft. I like to do community stuff. Have anybody here heard about the global Azure boot camp? Several people. Cool. So the global Azure boot camp happens once a year. It has happened three times now. We'll see if it happens next year in the spring. All of these locations all over the world. It was 182 locations last time through a one day Azure community gathering, get together, learn about Azure event as a community. All these community leaders all over the world did it and we did it on the same day. So it's pretty cool. 182 locations, something like in the size of 10,000 attendees, pretty big event. And we had a hashtag for that. So it's kind of fun. That's the kind of thing that I like to do on my spare time. And also we have a small conference called cloud burst, which is pretty good. If you ask me, we invite basically like five or six, seven, eight MVP speakers and talk about Azure and it's streamed online. So you might want to catch that. So that's kind of base base lining this this session. I've been about been around this web jobs thing since it was called simple batch and since before you guys knew about it. That's one of the perks of being an MVP. Get sort of get invited by our, you know, people we know on the on the development teams that there are our friends and they're showing us the latest stuff. Hey, look at this. This thing here. We're building this simple batch thing and that. So I got kind of got sucked into that. And you know, I don't mean to imply that I'm cool or anything. I just want to show you guys that Azure Web Jobs documentation resources on the website there. If you scroll down on that far enough, you will get to some additional web jobs resources and there's a link to my blog right there. So and some videos that I made the videos link is right there as well. So on my blog post reason I'm showing you this is not, you know, again, I don't want to stress, you know, any, any fame or anything at all. I just want to point you to a valid resource. You could you should check out these videos after the presentation. There's a bunch of them there that goes through several of the features of Web Jobs so you can learn all these things. You should do that. We're going to start off with a demo and I'm going to show you what a Web Job is. Here is Visual Studio and I've got a very, very simple console application here. Now there is a file new experience for this thing. You can do file new projects and get an Azure Web Job set up and running and you'll have the stuff that I'm going to add manually. But I like to show it manually step by step because that'll give you exactly what's in here at all, you know, specifics about it. If you have your very simple application, super simple, very straightforward console app, this thing runs. It doesn't do anything. It runs and stops. It's just a console app. What I can do is go ahead and add, of course, everything is a new get package these days. I'll go and add Microsoft Azure Web Jobs to the console app. It'll install a few things. It looks like a lot but it's really not that bad. I'm going to show you mostly we're going to interact with just one thing. Just make sure that this thing finishes. I'm on a hard line so I think even though the Wi-Fi is spotty, I think we're still good. That would be bad. It's kind of difficult to do an Azure session without the Internet. It's like, yeah. But it seems to be, yeah, it's going through. Okay, cool. So now we've added a bunch of references in here. And again, you would think that it looks like a lot but we're really only going to be interacting with the first two here, the Web Jobs SDK. Now, I'm writing code in C sharp but you could have, you can create a Web job which is a PowerShell script or a BAT file or whatever command line stuff. You can, and the Python scripts and stuff like that. But I'm going to stick to plain old C sharp code web application or console applications. So this is stuff we're going to be interacting with. What are you doing? All right, all right, party seems to be starting. That's cool. So don't mind the other people are actually having fun. Stick around. So we're going to do a job host. One of those. A job host is the thing that hosts your Web jobs and you'll see in a minute what a Web job is. I like configuration on that. This is not something you always have to do but for the sake of demoing, there's one little thing I'd like to tweak in the queue setup. And you'll know more what this means in a minute. But I need to set the max polling interval there to, not milliseconds, sorry. From seconds to five seconds. Otherwise it might poll as little as 30 seconds and we'll have to wait for demos to complete. So I'll just do that. Now there's one more thing that I need to do in my main method and it's just to say job host run and block. This run and block statement here is the equivalence of building a VCF application and saying host.open. That's exactly what happens now. So I can run this thing now and no, actually I can't. There's one more thing I need to do. So you need to have the Nougat reference and you need to configure one thing in your app config file to get a Web job running properly. And that's a reference to some storage. These two references have to be in there by default but you can set them in code as well if you like. But it's better. It's really easy to put them in here. So I always do that. The reference is here's the Azure portal and here's my Web jobs, demos, resource group and I have a storage account in there. That's the storage account that's being referenced in my Web jobs project. So that's the one. It's empty and I'll show you that in an explorer in a minute. So once we have these two things, the Nougat package reference, the host.open, run and block statement and your configuration there. You're ready to go. But we still don't have any Web jobs. This is empty now. If I launch it, it's going to say there are no Web jobs here. So what is a Web job finally? Well, it's a method. Should we do hello? Let's do hello NDC or something like that, right? Now this is just a method. Not a Web job method yet. I'll add a parameter to it. A Q trigger. Let's call the Q NDC. We're going to be watching a Q called NDC for messages. So they'll be coming in as strings. Now this thing is a Web job. It's not doing anything, but the Q trigger tells the Web job host that, hey, this method is a Web job. So you can call this method and you're going to be calling this method every time there's a message on the Q. So Web jobs has a polling mechanism that you don't have to build or maintain or take care of. How many have worked with Azure Storage Qs? Few, but not that many. Okay. Well, Qs are really great. You can use service bus as well if you want to, but I'm going to use Azure Storage Qs in my demos. It's roughly the same in this context. We need to do something with this and I'm actually going to add two more parameters to our little method. I'm going to bind to a blob and let's say NDC again. NDC, cool.txt. And that's going to be an out string result. And then one more parameter. Let's do a text writer. Log. We're going to call that log. So there are a couple of magic parameters with Web jobs. Log is one of those. This means I can do logging from inside of my Web job methods. All right. Result. Don't type and talk at the same time. Result equals the message is plus the message. All right. And then let's do logging on that as well. Right line. Result. Okay. Now this is a proper Web job method that does have a little bit of logic. I'm taking note of what the messages are that we send in. So this is it. This is really it. And the cool thing about this is if I set a break point, instead I can execute this from my PC from from Visual Studio hitting at five. This job host is now starting. And then there's not a lot of interesting stuff happening on the console window, but but it is starting. So we're talking about now using a queue to trigger this Web job, a queue called NDC. And then there's a little bit of magic going on here because we don't actually have a queue called NDC yet. If you go to my storage account here inside of inside of the Azure management studio, I can see my Web jobs demo. Storage account and there is no queue there. So let's create one. We need to name it NDC, of course. Oh, this is difficult. Let's let's zoom out again. You create it and call it NDC. And so now the queue exists. And let's put a message on that queue. This is cool. Right. So this is cool. Okay. That is pretty cool. So the Web jobs host knows about my method knows that it triggers on the queue on the message on the queue and it pulls the queue for me. I don't have to do anything. As you may or may not notice here, if you've been using Azure storage, there is nothing in here that says Azure storage. The coder that codes this doesn't have to know anything at all about Azure. Nothing. It's a console app, literally. So I'm going to send that message through and the message has now produced a result. The result is going to be in a file. Isn't it awesome to have like a session when the party started? That's pretty cool. I appreciate you guys being here because it sounds like they have a blast down there. All right, cool. Blob containers. Let's look. Is there an NDC container? Indeed, there is. There is a file called cool.text and yes, the message is in there. Okay. So it was that simple to read from a queue and write to a blob. That's, of course, a stupefiling simple Web job. I have some sort of, I have actual business scenario demos further down the line here to show that, of course, you can do more complicated things like this. But this shows the baseline. This shows what it is. So we have that. So where are these Web jobs anyway? Well, that's the thing. It's kind of a hidden feature. They've talked about making Web jobs sort of a first class citizen of Azure making in its own service that stand alone. So we're pairing the menu and stuff like that. But it's sort of a hidden feature right now inside of Web apps. And that means that because your Web jobs are hosted together with your Web apps, first of all, you actually have to pay for any cost of running them. Now, has anyone in here used a cloud service, a worker role? Yeah, a few have used a cloud service worker role. That's your complete full entire like a Windows server running your code for doing batch processing, right? That's what it is. But this thing, this little process runs together with your Web apps. You don't actually have to pay for any cloud service machines anymore. So you can just run this whenever you're doing small stuff like, I don't know, making a thumbnail out of an image or things like that, that you usually do on your background processing threads. So I'm going to show you how to deploy now our stupid, finally simple Web app or, sorry, Web job to Azure. And that's easy too. Let me get rid of this magnifying glass there. Cool. So again, here is the Web job. I right click on this and I say publish as an Azure Web job. I get to give it a name and I get to choose to run it maybe continuously, run it on a schedule, run it on demand. Continuously is the one that makes sense when you're pulling a queue, but you can schedule things and it's going to use the Azure schedule or to schedule calls into your Web job method on a given schedule. And you can run it on demand when you're running specific workloads as well, if you like. But we're going to run it simply as continuously and say, okay, this adds another new get packet, package reference that only actually does one simple thing, creates a little configuration file for your Web job. That's what it does. So again, if I publish now, I already have that first step done. I'm going to choose a Web app and it just so happens, of course, that I have an empty Web app in Azure right now. Let's go and look at that in the portal. So if I click here, you'll see that I have a Hello World Web job Web app. It's out there and you can browse to it. And if I browse to it, you can see that there's nothing there. It's just an empty host. Get rid of some of these tabs. There's just an empty host. So there could potentially be a Web job in here, but there isn't one yet. So I'm going to choose my Web app already created in Azure and say, okay, this is the one I want to publish to and do publish. Oh, while debugging. Sorry. Yes, I want to stop debugging. We'll see. Needed to build the thing. Did I get it to publish? I think so. I was still debugging. I was still running. Yeah, so it's doing the should be. Yeah, there we go. Publish succeeded. It's really fast. The landline is really fast. I've been running these demos on the Wi-Fi and they've been taking so much longer. So this is good. So again, where are the Web jobs now that I've deployed one? Well, if you go into settings, there is this little obscure option there called Web jobs. And you click into that and you get your running Web job continues running in Azure. So what I said always on this thing won't always be on because I'm hosting this in free mode. It's a free Web app. That's that's how it how it runs, which means it's actually going to shut down after a while unless somebody actually calls the Web application. Right. So there are settings for that, like always on, which is the best thing to remember. If you want to have your Web job running continuously always, you would want to set always on and then you can't host it in free mode. But if you have that set up, you probably have a Web application anyway and you can host them together. So that's fine. So just flip the always on and then your Web job will be always running. So it's right there now. The Web job is running in Azure. So let's let's test it out. I'm not running locally anymore, but let's send a message to the Web job again. This is also cool in Azure. Right. So we'll send that. And you can actually look of course in the queue, but but the Web job has already picked up the message and therefore the text in here should have been changed already. So now the Web job is running in Azure. And if I flip on always on, this is going to perpetually keep pinging my queue to see if there are any messages. I mean, could it be simpler? Really? That that's just this is mental. But I love it. It's it's it's very powerful. So deployment done. What about before the Web jobs? I was talking. I saw some people had been using the cloud service, the cloud service worker roles. So again, that's a full server right there. And I happen to have one right here. A cloud service. Not going to spend too much time on this because it's not what this session is about. But basically you have your your cloud service deployment project and you have your worker and the worker has this worker role. That contains all this code. It's a role entry point. And there seems to be some sort of a life cycle here on start run. And you got to configure a bunch of stuff in there. Yes, more code. And then you run something. Okay, async a method. Something's run there. Oh, down here somewhere is the actual code I wanted to run like one line of code was the thing I wanted to do. But I have all this other stuff and that raises a bunch of questions. You know, what is all of this? You know, how is this hosted? How do I deploy it? What's the life cycle? And how do I configure this and diagnostics and oh, there's lots of stuff. Now, all I wanted to do was run a simple line of code. And I would say you would kind of degrade a Windows server if you just run one line of code on the thing and just leave the process to doing nothing the rest of the time. And you will be paying for the whole machine the whole time, right? So therefore web jobs is much more logical. So that's what we had and this, the cloud service, it's great. If that's what you need, it's the proper tool. If that's what you need to run. Fine. But if you run something simple like a simple batch, hence the code name simple batch, you will run a web job instead. All right. Now, you're saying here, Magnus, that you're running a process on a background thread in a web app. Like, do I need web jobs for that? I can roll my own. And I can code this, not a problem. I can code this, of course. You know, I'm a developer. Let's not, you know, use something somebody else built. Let's build it ourselves, right? Of course. So let's do that. Roll my own. Okay. I'll probably need an API or something. I'll run a web app and I'm in the global here. I'm going to go and do, so I've been a good citizen. I've created an engine interface. Of course. That's what we're doing. Running something on a background thread there. Run container. Okay. Cool. So I did a bit of an implementation here. And so my implementation is about, you know, less than 120 lines of code. And I'm trying to do it kind of proper with a task factory here and started task. And I need something to monitor this task, keep running a timer that times out and checks that the process is actually up and running still. And, you know, there are some things I need to do. So, you know, with this, about maybe two, 300 lines of code, I can do this myself, no problem. But then I have code that I need to maintain that I need to take care of. And there are some other things. How do I know how well this is processing? Oh, right. But that's fine. I'll do some diagnostics, right? And this continues and continues. And all of a sudden you're building something that isn't your business. Again, your business was built running that one line of code. You don't want to do all that other stuff, hosting a process and stuff like that. So, you know, let's not do that. That's probably unnecessary. So, that's sort of summarized what we've learned so far. This is not a big cloud service. This is a simple thing, right? It'll make it easier to use Azure Storage and other types of services. As I said, you can use the service bus. The coder that codes this needs to know nothing of these things. It doesn't have to understand anything of Azure at all, which is good, because at any given company you might have somebody who is like the Azure wizard, probably you guys in the room right now. You are the Azure guys at your companies. And then the other guys just don't know about it. And they don't have to. And then, statistics included. Okay. So, the next step then is to show that dashboard that comes with the web jobs. Going back to the portal, we have our web job here. And if I say I want to browse again to this thing, like I said before, it's just there. Do you guys know about Kudu, the thing that runs underneath your web apps in Azure? Kudu is the engine that runs your web apps when you host them in Azure. And you can reach that by typing in site control manager, SCM, inside of the URL like that. You'll come into Kudu. So, Kudu is running behind every web app that runs as an Azure web app. Okay. And inside there you can also do Azure jobs, slash Azure jobs. There's actually a link that you can follow to get to this, but I wanted to show you properly. So, the web jobs will say that, hey, this site actually has a running web job. But if I look at the functions that I have there, I get this error message. And the reason I get an error message is because I didn't configure. It says what you need to do quite clearly. Magnifier, there you go, that you need to have a connection string named Azure WebJob dashboard, blah, blah, blah. This configuration, you only need to do once. But I am not going to do that. I'm going to go back to this other web job, which is already configured by other demo. It's already configured. And it's looking at the same function. So we can see in here that I have a function which is deployed and it should be there. No functions, really? No. Yes, there it is. So hello, NDC is running. I get some nice statistics on how many times this has run. And I can see these invocations in here that we have. I can see the file as well. I can look at the file and see the content of the file. I can get that loaded. I can see the input and output parameters and all that stuff. And the log that I was talking about, it goes in here. So you can see the log messages inside of your invocations of the web jobs. And then you can actually replay this, baby, if you want to. This is cool in Azure from the dashboard. All right. And that's just because we can output that to cool 42, another text. And just replay that function from inside the dashboard. So you can see if something went wrong, what went wrong, you'll get the full stack trace and everything in here, all the statistics, and make sure you can monitor your web jobs to see how they're doing. All this data is stored in your storage account, so it's not a problem either. It's your data. There's no magical thing here that's happening. If I go over now to Azure there, then there's indeed a file called cool 42, which contains the new data. So I can run it from the dashboard as well. I think that is actually quite excellent. You agree? Yep. I got some nodding heads. Cool. Thank you. Thank you for interacting with me. So now we have a dashboard and I didn't have to code that, which is, you know, it makes me happy. And I can focus on that one line of code that I was going to deploy. But now it's your turn. Anyone got Wi-Fi in here? You should go to this site right now and see if you can send me a nice message. It'll be fun if you send me a nice message. I'd appreciate that. You know, I don't really have a lot of good self-confidence. So please send me a message. WebJobs live. This very simple website is running in Azure. And right now there is not a WebJob processing it. So I can enter. And this is the name of a blob. So for you guys who think you can break my code, you probably can. Send me a blob file name that isn't valid, like containing strange characters and stuff like that. And which means I'll get a nice error message from when my code isn't properly executing. I'm sure somebody is able to break my stuff. Fail, for instance, is a good one. I'll send another. I'll send me a message myself. But a lot of you guys are sending messages. Cool thing about this is now I have a front end, the web application that takes the messages and puts them on a queue. Now this queue is in here. Live demo messages. And you can see there are a couple of messages in there. People have submitted some messages. And nothing is processing this thing right now. It's just sitting there on the queue. You can continue to put messages on there if you like. And I'll show you the code behind this thing. So inside of my demo code here, I have a web application which will send messages onto a queue. I believe the code is here. So there, the post will take the file name of the body and turn that into a message and add that to a queue. This code here needs the guy who writes this or gal, the person will have to have some experience with Azure storage in this case. But I've talked to that team about that and they say they might actually create something that is void of the concept of this underlying storage structure that you can just send to and have that processed by the web job. Anyway, I'm sending on a message onto the queue here and I have the web job which again isn't deployed yet. But I will deploy it soon. It's a very similar setup like you saw before. Oops. And I have a function called process messages which will trigger off the queue. And you can see here some really, really cool things I can get the file name and that's a property on this message object. And wait a minute. That was a string before. Now it's an object. Well, guess what? Web jobs will assume that the content of your queue message is a JSON serialized object if you bind to something in this case called message. It will assume that the incoming messages will be of that type. So you might try to break my code there. Well, I don't think it will serialize unless when you start adding curly braces. I don't know. So the property file name is one of the properties of that JSON object. And I might be able to get that in here so that I can actually output two blobs using that file name. So I can get those pieces of information from my incoming message in the signature of my method. And I'm doing the same kind of simple thing here. The next thing I want to show is I'm using two methods now. I'm triggering off the blob that I just wrote using a blob trigger. So when there is a new blob in storage, please trigger this method instead. I have a second method here that I'm also going to run. And then I'm interacting with tables, Azure storage tables. Early on in the development of SimpleBatch, they actually did not use the Azure table operation and stuff like that because they tried to make an abstraction on top of tables, but it was horrible. It was really bad. They were trying to use dictionaries and key value pairs and stuff like that. And it was like, ah, no, no, no, no. They reverted to actually, in the case of tables, actually using Azure tables. So I'm executing an operation on the table to insert your messages. So your messages, excuse me, your messages will go on a queue. And they will be pulled from the queue and written to a blob. Then they will be pulled from the blob and written into a table just to show you that you can do that. So very simple web job methods still. Let's go ahead and deploy this. Now, what I want to do now is I want to deploy the web app and the web job at the same time. The web app is actually already deployed. You've used it, but the web job is not deployed. So I want to deploy them together. So how do I do that? Well, I can right click on my web app and say add existing project as Azure web job. So there's tooling for it. I'll have to select the project, this one, and it doesn't like that name. So I'll say live web jobs. Okay, this now adds the configuration to the web job and it adds a reference into my web app that says, here's the web job you're going to have to deploy together with the web app. So when I now go and say I'd like to publish this web app up to Azure to my web job's live site, the one you've been using, the web job will come along with it. It'll deploy together. It's quite handy. All right. So this means that in a second or two, in a short while, we should have, go to the other app, we should have a web job up there as well, which will then automatically begin processing the queue messages that you've so nicely sent to me. So web jobs. See if it's already, yeah, so it's there and it's running. And if I go back to the queue live demo messages, you can see that, yeah, and here you can see something funny. I'm glad we caught that. Some of the messages you sent did not process okay. And you can see it has a DQ count here on these things because these messages are not working properly. One good one is to send null. That's not a valid message. That'll break the code. So the web job will try to process the messages off the queue. I think the default is 10 times. You can change that, I think. But it'll try to process the same message 10 times and it'll assume the message is poisonous because it can't be processed. So what happens then is actually you will get a poison message queue where your messages that are poisonous that the code can't handle will wind up. So these are the broken messages that are not functional. So that automatically gets deferred into a separate queue which you can then process manually or with some other method. But you won't be losing any data just because a message is poisonous and you won't crash your web job because a message is poisonous because that's already taken care of. Poison message handling is important. So this means that we should have some data, at least some data inside of our actual table. Here's our table, live demo messages. Let's see. We do indeed have beer and Live Long and Prosper as some nice messages that you guys just sent me. So those messages came through and wound up in the table. And we should have some blobs also showing the temporary storage for these messages here that you sent me. Okay. So that's it. And on all of this storage interaction stuff, as you can see here, there are a bunch of queues here called web jobs and there are a bunch of blob containers called web jobs. All of this stuff is diagnostics. The diagnostics that base the stuff you see on the dashboard. So web jobs automatically stores diagnostics about the stuff that was invoked. And if there's an error, it's going to catch the stack trace and put in the blob file for you. And all of that stuff is just happening automatically by web jobs, which then motivates why there are two storage accounts that you can configure. One for the diagnostics and another one for the data. I'm using just one storage account in this demo, but I usually want to have two separate ones. Just put the diagnostics to one side and have the business data on another account. All right. Any thoughts or questions so far? You guys look really intently like you're really engaging in this. I love that. I can see you guys nodding and nodding us and sleeping. Nodding us and you like this. I appreciate it because this is actually fun stuff. When I see this, every time I go like, nice. Now I don't have to build that myself. That's just so handy. So I guess you can all imagine the many types of scenarios, lots of things you can do with this. You can process queues, of course. You can do an RSS aggregator. You can do file maintenance, resizing images and all kinds of things that you want to run. All kinds of things that you want to run on a background thread. Couple of caveats, though. If you run something that really sucks your CPU, what's going to happen? Anyone? It's going to cost. It's going to cost the hell of it. What it's going to cost is it's going to cost your website because your website is running on the same box. But the Hello World WebJob that I deployed was deployed to a web application slot without any web app. So you can run them separately if you need to, if you're running stuff that will consume a lot of CPU. And actually, it runs 16 parallel processes by default. You can change that number as well. You can go down to one if that's what you need. And you can also scale. Again, this is deployed as web apps. So you can take advantage of that and use auto scaling, for instance. If you have a lot of messages coming in on the queue, like tens of thousands of messages, you might need to check the queue length and scale on the queue length and have more machines processing the queue. And everyone that starts up in the scaling will run 16 parallel processes just hammering away on that queue. So there's a lot of power here. You can quickly move up to a lot of processing power and you can also move down to very little if that's what you need. So, and again, by the way, whenever somebody shows you a long list like this with bullet points, it's that they don't really want you to remember all the facts and the details. They just want to show you that there's a lot of stuff you can do. So I have a couple of more demos. Let's see what we're doing on time. We have about 20 minutes. Good. I have a couple of more demos. It's actually just me showing you code. Just to show you something that is a little bit more production worthy than Hello World. Here's one that I really like. I did this with a customer and their response from the customer was that after we'd done this together, we built this thing together, they wanted to copy files. Classic, they wanted to have, we're going to upload our product releases to a storage account, but we also want to copy that to have different mirror sites downloaded, like one in Asia, one in the US, one in Europe. And we need to make sure we copy the files to all those locations. I said, hey, that's a web job. Really easy to do, actually, with a web job. Just mirror files, incoming blob files, copy them to another location in our implementation. After we were done, they were like, if it gets any simpler than this, we'll have to think the code and have it execute in our head or something, because this is just too easy. I would agree. I have a method here called copy release, which will take a message off a queue and write a response message once the method is finished. And for those of you who are paying attention, you can see that I'm also using the async process programming model here to use non-blocking operations, which is kind of handy as well. So you can do that, and you can even use a cancellation token there if you want to. So what I'm doing is I'm getting a reference to the blob I want to copy from. I'm getting a reference to the blob I want to copy to, making sure that the first blob actually exists. And then I create a shared access signature for those of you who know what that is. It's something I can append to my URL to make it, in this case, read-only. And now for the fun part. When I'm copying here, I'm using an Azure Storage feature, which is a long name. Start copy from blob async. This is a command I'm sending to storage, giving it a URL saying, this URL, copy the file you find there into yourself. That's what I'm doing. So that means that no, I'm not copying the, I'm not streaming the blob into memory on my box and then streaming it back out into another storage account. I'm telling storage to copy from A to B. And while that's happening, I'm going to wait, I'm going to hang around here and do like a little delay and wait and go back and check to the server, are you done yet? Are you done yet? Are you done yet? Until it's done. When the copy status is success, I've actually copied the blob from A to B, and then I'm done, I'm going to write out a message saying, yes, I've copied this blob. This is almost production-worthy code, and it'll solve the problem of copying files with using very, very few resources. Just like a few lines of code, it's easy once you get to know these web job things. Now, the other example that I have is also quite interesting. It's the classic, classic example of you having a web application that receives maybe an upload file or some data that needs to be processed, and then the code that receives that on your web server takes a few seconds or 10 seconds or something to process this. Like when you hit the submit button, the confirm button when you're booking holiday tickets or something, it's going to process for a while while you wait, right? It's going to think about this and make sure that everything went through and then come back to you and say, ah, it's done. So while that's happening, you're looking at the spinning donut of death wondering how long this is going to take. Well, that feature, that thing is much better processed in the background, and after the processing is done, send an email or a notification or have the web application go back and check, is it actually done yet? That's much better to do. So in this example, I can't run this actually because I don't have the database for it, but I can show you the code that does this, and you'll understand, of course, how this is done. Send emails. So this web app that I have here is part of a demo workshop that I had. It has some simple views that will take some input when you order cakes online to have them delivered, and your order coming in will have to connect to some sort of repository and get some data, and when you post back, it's going to take your order and your quantity and stuff like that and put something on some kind of ordering service and submit that order, and then after that's done, the ordering service has submitted the data. You're also going to send out an email to the person who placed the order saying, thank you for your order, blah, blah, blah. All right? So this takes a few seconds to process if you run this code, and while you're doing that, the user is waiting, and that's not a really good user experience, and also it consumes resources on your web application, so when you have like a million people ordering cakes from your business, you need some really powerful machines. So instead of doing that, I'll replace the ordering bit here. I'll just take this code, replace that with this code, which is my implementation of an Azure ordering service. It's going to take the same information and plop it on a queue and return to the waiting customer saying, thank you for your order on the web browser, and then once the order is processed on the background by the web job, the email will be sent to the waiting customer saying, yes, we have your order, your confirmation number, blah, blah, blah. So that's a lot better to do it that way. So in this case, of course, then I will be using this ordering service to do pretty much the same thing as I did before, except that instead of submitting it to the database, blocking the application, et cetera, I'm going to just simply put it on a queue again. So I got the queue message here, putting that on the queue, adding the message to the queue. And of course, on the back end, the web job is going to do roughly what the code did before inside of my business logic, right? It's going to take the message and process it and send the email. That's it. Now, if I do it this way, your users will have a much better experience, your web application will scale, and everything will just be really beautiful, and pretty soon you guys will be downstairs drinking beer instead of coding. All right. Cool. So basically, that is the session, but there are a lot of more features that are interesting to look at, and the rest of this session is basically like a feature bonanza thing where I go through different features and we can talk about those and you'll be enlightened and everything will be beautiful. Does anyone have, yes, questions, exactly. Regarding the signature of the... Regarding the signature of the function, well, it needs to be a public static method, and it needs to have some parameter that has those triggers. It needs to trigger on something, but I did continuous web jobs in my example. I did continuous ones. I have web job methods that you can flag them saying, this is a web job method, and that might be run by you on demand instead of the triggering method that I did with the attributes. You can have things that run on a schedule, things that run on demand. Yes, the parameters for the order in this case, this is packed inside of JSON, the parameters of the... No, it's not packed into it. The question is, are the parameters packed into the JSON or anything like that? No, it's not, because what web jobs will do, it will inspect the code that it has in its bin folder, and it will find the methods that have any web job attributes on them, and it will do that using reflection. So it will just figure out what stuff there is, and you saw when I had, for instance, I had a message that was a string, and then in another case I had a message which was of type message, and when it sees, well, message of type message, that must mean that the incoming message will be a JSON serialized object with these parameters, otherwise I can't serialize into that. And if that breaks, then you'll get an error saying, well, the message I received wasn't a JSON serialized message object, it was something else, I couldn't deserialize. So you'll get the sort of full support in these parameters, and it'll tell you when you do something wrong, because you will see that there were invocations that were not processed properly. So it'll help you all the way. Again, this is built to be simple, right? Simple, simple, simple. That is what it is. Any more questions? Yes. Is a queue the only way to trigger a continuous web job? Is a queue the only way to trigger a continuous web job? There are three ways of doing it. You can trigger a continuous web job on a queue, an Azure Storage queue, on a Service Bus queue, or on a blob. The blob one is a little bit more dicey. It means that you upload a blob to a blob storage account, and at some point the web job using the Azure Blob Storage statistics will see, is there a new file which is added later to this container than when I checked last. So it'll keep statistics on this, and it will execute your method based on incoming blobs. But I've had a problem with a customer scenario for this exact thing. They needed to make sure that the triggering was happening fast. And with the specific blob trigger, it can take a little time. It depends on how much traffic there is on your storage account and stuff like that. With the queues, you could set the number of seconds, how often do you pull? The default is to fall back and pull as few times as once every 30 seconds if there are no messages on the queue, but if there are messages, it's going to continuously just process them. But the blobs will take a little more time. That's a great question. Did they answer your question? Yeah, it was blobs. Yeah, blobs, it works. How to target it to allow the......time schedule? Yeah. How long can you go ahead and do it? What's the question? Yeah, so the question is, if I use a scheduled trigger on intervals called this web job method, how fast can I put that schedule? And I believe you can do something along the lines of once every second or something, but you'd have to pay for that scheduler. This is the Azure scheduler you're running at that point. You're running the scheduler which is in Azure. That's the thing which is going to be configured to call into your method on a given or called your web job and say, hey, dude, wake up, call this method, do it. And it's going to do that on the schedule that you set. So it's based on that feature. Okay? Still, it's a very valid way of doing it. Like, have the scheduler call frequently to your web job method and have your web job then do something. It doesn't even have to have any parameters at that point. Really only have to have an attribute saying, I'm a web job. Good question. All right? Yes, another question. What's the maximum... What's the maximum length of time a web job can last? Yes, what's the maximum length of time a web job can last? That is a great question. And it's not as long as I would like because I've had some web job methods go and say, never finished. And it gets sort of this yellow status. You can have red, failed, green, okay, and yellow, I didn't complete. And the reason why that happened to me was that I was starving my machine because I was running it really hot and it couldn't process everything so it stopped processing things after a while. So that happened to me and I was trying to do too much inside of a web job basically but at least I got information about it. So it'll shut it down. But the web job itself can run for a long time because Azure Storage, also the service bus queues, have the feature that you're able to go back to the message and update the lease time you have on the message. So for those of you who know how Azure Storage queues work, when you dequeue a message, it's hidden on the queue for you for a period of time. And if you don't return and say, delete message, which means I'm done with the message now, the message will reappear on the queue and you will get that dequeue count increase. And after 10 tries, I got poison messages, right? So that was built into the feature of the web jobs. But it's leaning on a feature of Azure Storage and you can go back to the queue and say I'd like to update the message and you can actually change the content of the message funny enough but you can also say I'd like to have the lease extended for another period of time and you can go back and do that however many times you like. So you can, in theory, keep a message forever but forever in Azure Storage queues is seven days. So a long time is the answer. But it's a valid question. It's one of those like, what is this? Yes, these are great questions. It means that you guys are paying attention. I love that. Any more questions? What are the maximum size of the message in the queue? The maximum size of the message in the queue is not a web job question. It's an Azure Storage queue question but I can answer that, absolutely. It's 64K and if you need bigger ones, the normal process is to put the message body in a blob in Azure Storage and put a reference to the blob in the queue. So that works but then you have to do two things but it works. Yeah, great question. So sometimes you have messages that are larger than 64K. It's actually 256 in service bus queues. So you can use those instead if you have messages that are not larger than 256. Great. I see that you guys are thinking about all the things you're going to build with this when you come home and that's basically the point of this talk is really to give you a tool that you didn't know about and then when you go back home it's like, oh, holy crap, we're going to throw some stuff out now. And this engine thing that we were having, we're maintaining, no. This background thread thing we're running, no, no, no, no, no. Don't do it that way, that's the wrong way of doing it. All right, we only have a few more minutes. I think most of this stuff I have talked about is sync-weight binding. Yeah, you saw me parameterizing bindings using parameters from the, using your names and stuff like that from the messages and things like that. It's really, really handy. You can get the DQ count if you want to do something with that inside of your code. You can get the DQ count saying, hey, have I processed this message before? Because sometimes that's something you need to know inside of your code. And streams are really cool. If you're reading off a blob trigger, you can get the input as a stream. You can get it as a text reader. You can even get it as a string. So all of these bindings just work out of the box depending on what you want to do. If it's an image file, getting a text reader or a string doesn't make any sense. You might want to get the stream instead. But, you know, you can even actually go and do a stream binder to bind to other types of objects. In this case, a web image is my parameter. But the blob, the job host doesn't know how to read a web image. So you can create your iCloud stream binder of web image and explain to web jobs how to change your stream into a web image and back. So it's actually quite handy and powerful. So your methods can have a really smart signature and you'll just have this conversion thing running in the background. So no automatic trigger means only manual triggering. Right. So basically that and then the service bus, I've told you that. I think I've told you all the features that I wanted to talk about. There are videos in my blog post that you can check if there are any specific ones you want to learn about and I have videos showing that. So are there any more questions at this point? Before I summarize. I think we may have emptied out all the questions. That's great. Thank you. So this is not a big cloud service. This is simple stuff. It's easier to use than and using storage direct because I just have to have an attribute and then I can use a string instead of doing add message or get message and delete message. And how do I handle these and all that stuff? You don't have to know that inside of your your your logic that runs the web job and all that monitoring and diagnostic stuff that you get included in the package. And again, like I don't want to sound like a cheap car salesman or anything, but you run this at no additional cost because it's it's you're still. If you are running your web apps, of course, I mean, if you're not running web apps, then it's going to cost you a web app. But other than that, but wait, there's more. Now, I can't actually run the debugging demo because I'm using Visual Studio RC and Windows 10 and stuff like that. I tried, but it's not working. But I can show you how it would be working if if I didn't run this RC version and stuff like that. You know about the service server explorer, you can go and look at your your Azure stuff. And if I go down to my web apps, we have two web apps running now the Hello World web job would be the one that I would connect to if I could. But unfortunately, me installing my my machine was not a smart thing to do. It goes out to Azure and checks do I have a web job running in this application I do indeed. And then I can right click on this. Am I running it? Oh, it's not. Oh, it's not. It's not running. It detected that. Yes, it's there, but it stopped running. So I might have to start it up first. But once I've started it up, I can attach. Well, in theory, I can attach the debugger to a running web job, which is running out in Azure. And I can debug from Visual Studio right into my code. And I think that's pretty sweet. I can't demo it today, unfortunately, but you'll have to trust me that it works. So that was, I guess that that's the summary. And whoops, let's get rid of the magnifier. Go away. I said go away. Ah, that was the presentation, ladies and gentlemen, I appreciate you taking the time. And again, this is my passion. I love doing this. I love talking about it, but I love doing it. And if there are any additional questions, do not hesitate to send me an email. That's not a problem at all. And you know, you should go and drink beer now. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you.
 So Tech Guy says everything is good to go.  Sweet. I'm on the screen. Maybe we should get started.  Let's do that.  Hi.  Welcome. Welcome to this, the last session slot of the day.  I appreciate you guys being in this room because obviously it means that you are really passionate about being at this presentation.  There are some other really good ones going on at the same time, so I appreciate your attendance.  I will do my best to entertain.  I just want to check with you. Are you running any workloads in Azure at this time? Hands up.  Most of you are. Are you running web apps?  Okay. So anyone running the web jobs?  One guy. All right. That's great. That's great. That's a good baseline for this talk.  Now I know what you're all about.  You look like a pretty intelligent bunch.  So when you leave here, I know the answer to that really strange question.  They're asking by the door. There are three colors. Anyone colorblind?  No? Okay, good.  The answer is green, just so you know.  Making sure you know this. Okay, cool.  So web jobs that I'm going to talk about is basically background processing in your Azure web apps.  That's what it is, right?  And means that it's part of the Azure app service.  You got the logic apps and all those things you can do.  But it's kind of cool because it's baked in there so you don't have to, you don't pay any extra to run this stuff.  And also it means that if you have something simple, something batch processing like that is simple that you want to run,  you can run that in web jobs.  And it's a simple batch. It's sort of italic here in this slide because that was the code name for web jobs when they were building it.  All right.  My name is Magnus. Martin Sonam from Sweden, from Malmo.  So I could go with Swedish Norwegian but I guess there are some people here who are not from Norway.  Anyone not from Norway? Yes, several.  So we'll stick to English of course.  If there is anything at all, like don't hesitate to send me an email and ask, you know, about this session or, you know, about Azure actually.  Because Azure is what I do.  I'm also an MVP for Azure.  I was the first one to be an Azure MVP in the Nordic countries.  And I'm also what Microsoft call a regional director, which kind of means that they're still not paying me unfortunately.  But they kind of like having me around.  So I'm a business partner of Microsoft.  I like to do community stuff.  Have anybody here heard about the global Azure boot camp?  Several people. Cool.  So the global Azure boot camp happens once a year.  It has happened three times now.  We'll see if it happens next year in the spring.  All of these locations all over the world. It was 182 locations last time through a one day Azure community gathering, get together, learn about Azure event as a community.  All these community leaders all over the world did it and we did it on the same day.  So it's pretty cool.  182 locations, something like in the size of 10,000 attendees, pretty big event.  And we had a hashtag for that.  So it's kind of fun.  That's the kind of thing that I like to do on my spare time.  And also we have a small conference called cloud burst, which is pretty good.  If you ask me, we invite basically like five or six, seven, eight MVP speakers and talk about Azure and it's streamed online.  So you might want to catch that.  So that's kind of base base lining this this session.  I've been about been around this web jobs thing since it was called simple batch and since before you guys knew about it.  That's one of the perks of being an MVP.  Get sort of get invited by our, you know, people we know on the on the development teams that there are our friends and they're showing us the latest stuff.  Hey, look at this. This thing here.  We're building this simple batch thing and that.  So I got kind of got sucked into that.  And you know, I don't mean to imply that I'm cool or anything.  I just want to show you guys that Azure Web Jobs documentation resources on the website there.  If you scroll down on that far enough, you will get to some additional web jobs resources and there's a link to my blog right there.  So and some videos that I made the videos link is right there as well.  So on my blog post reason I'm showing you this is not, you know, again, I don't want to stress, you know, any, any fame or anything at all.  I just want to point you to a valid resource.  You could you should check out these videos after the presentation.  There's a bunch of them there that goes through several of the features of Web Jobs so you can learn all these things.  You should do that.  We're going to start off with a demo and I'm going to show you what a Web Job is.  Here is Visual Studio and I've got a very, very simple console application here.  Now there is a file new experience for this thing.  You can do file new projects and get an Azure Web Job set up and running and you'll have the stuff that I'm going to add manually.  But I like to show it manually step by step because that'll give you exactly what's in here at all, you know, specifics about it.  If you have your very simple application, super simple, very straightforward console app, this thing runs.  It doesn't do anything. It runs and stops. It's just a console app.  What I can do is go ahead and add, of course, everything is a new get package these days.  I'll go and add Microsoft Azure Web Jobs to the console app.  It'll install a few things. It looks like a lot but it's really not that bad.  I'm going to show you mostly we're going to interact with just one thing.  Just make sure that this thing finishes.  I'm on a hard line so I think even though the Wi-Fi is spotty, I think we're still good.  That would be bad.  It's kind of difficult to do an Azure session without the Internet.  It's like, yeah.  But it seems to be, yeah, it's going through.  Okay, cool.  So now we've added a bunch of references in here.  And again, you would think that it looks like a lot but we're really only going to be interacting with the first two here, the Web Jobs SDK.  Now, I'm writing code in C sharp but you could have, you can create a Web job which is a PowerShell script or a BAT file or whatever command line stuff.  You can, and the Python scripts and stuff like that.  But I'm going to stick to plain old C sharp code web application or console applications.  So this is stuff we're going to be interacting with.  What are you doing?  All right, all right, party seems to be starting.  That's cool.  So don't mind the other people are actually having fun.  Stick around.  So we're going to do a job host.  One of those.  A job host is the thing that hosts your Web jobs and you'll see in a minute what a Web job is.  I like configuration on that.  This is not something you always have to do but for the sake of demoing, there's one little thing I'd like to tweak in the queue setup.  And you'll know more what this means in a minute.  But I need to set the max polling interval there to, not milliseconds, sorry.  From seconds to five seconds.  Otherwise it might poll as little as 30 seconds and we'll have to wait for demos to complete.  So I'll just do that.  Now there's one more thing that I need to do in my main method and it's just to say job host run and block.  This run and block statement here is the equivalence of building a VCF application and saying host.open.  That's exactly what happens now.  So I can run this thing now and no, actually I can't.  There's one more thing I need to do.  So you need to have the Nougat reference and you need to configure one thing in your app config file to get a Web job running properly.  And that's a reference to some storage.  These two references have to be in there by default but you can set them in code as well if you like.  But it's better.  It's really easy to put them in here.  So I always do that.  The reference is here's the Azure portal and here's my Web jobs, demos, resource group and I have a storage account in there.  That's the storage account that's being referenced in my Web jobs project.  So that's the one.  It's empty and I'll show you that in an explorer in a minute.  So once we have these two things, the Nougat package reference, the host.open, run and block statement and your configuration there.  You're ready to go.  But we still don't have any Web jobs.  This is empty now.  If I launch it, it's going to say there are no Web jobs here.  So what is a Web job finally?  Well, it's a method.  Should we do hello?  Let's do hello NDC or something like that, right?  Now this is just a method.  Not a Web job method yet.  I'll add a parameter to it.  A Q trigger.  Let's call the Q NDC.  We're going to be watching a Q called NDC for messages.  So they'll be coming in as strings.  Now this thing is a Web job.  It's not doing anything, but the Q trigger tells the Web job host that, hey, this method is a Web job.  So you can call this method and you're going to be calling this method every time there's a message on the Q.  So Web jobs has a polling mechanism that you don't have to build or maintain or take care of.  How many have worked with Azure Storage Qs?  Few, but not that many.  Okay.  Well, Qs are really great.  You can use service bus as well if you want to, but I'm going to use Azure Storage Qs in my demos.  It's roughly the same in this context.  We need to do something with this and I'm actually going to add two more parameters to our little method.  I'm going to bind to a blob and let's say NDC again.  NDC, cool.txt.  And that's going to be an out string result.  And then one more parameter.  Let's do a text writer.  Log.  We're going to call that log.  So there are a couple of magic parameters with Web jobs.  Log is one of those.  This means I can do logging from inside of my Web job methods.  All right.  Result.  Don't type and talk at the same time.  Result equals the message is plus the message.  All right.  And then let's do logging on that as well.  Right line.  Result.  Okay.  Now this is a proper Web job method that does have a little bit of logic.  I'm taking note of what the messages are that we send in.  So this is it.  This is really it.  And the cool thing about this is if I set a break point, instead I can execute this from my PC from from Visual Studio hitting at five.  This job host is now starting.  And then there's not a lot of interesting stuff happening on the console window, but but it is starting.  So we're talking about now using a queue to trigger this Web job, a queue called NDC.  And then there's a little bit of magic going on here because we don't actually have a queue called NDC yet.  If you go to my storage account here inside of inside of the Azure management studio, I can see my Web jobs demo.  Storage account and there is no queue there.  So let's create one.  We need to name it NDC, of course.  Oh, this is difficult.  Let's let's zoom out again.  You create it and call it NDC.  And so now the queue exists.  And let's put a message on that queue.  This is cool.  Right.  So this is cool.  Okay.  That is pretty cool.  So the Web jobs host knows about my method knows that it triggers on the queue on the message on the queue and it pulls the queue for me.  I don't have to do anything.  As you may or may not notice here, if you've been using Azure storage, there is nothing in here that says Azure storage.  The coder that codes this doesn't have to know anything at all about Azure.  Nothing.  It's a console app, literally.  So I'm going to send that message through and the message has now produced a result.  The result is going to be in a file.  Isn't it awesome to have like a session when the party started?  That's pretty cool.  I appreciate you guys being here because it sounds like they have a blast down there.  All right, cool.  Blob containers.  Let's look.  Is there an NDC container?  Indeed, there is.  There is a file called cool.text and yes, the message is in there.  Okay.  So it was that simple to read from a queue and write to a blob.  That's, of course, a stupefiling simple Web job.  I have some sort of, I have actual business scenario demos further down the line here to show that, of course, you can do more complicated things like this.  But this shows the baseline.  This shows what it is.  So we have that.  So where are these Web jobs anyway?  Well, that's the thing.  It's kind of a hidden feature.  They've talked about making Web jobs sort of a first class citizen of Azure making in its own service that stand alone.  So we're pairing the menu and stuff like that.  But it's sort of a hidden feature right now inside of Web apps.  And that means that because your Web jobs are hosted together with your Web apps, first of all, you actually have to pay for any cost of running them.  Now, has anyone in here used a cloud service, a worker role?  Yeah, a few have used a cloud service worker role.  That's your complete full entire like a Windows server running your code for doing batch processing, right?  That's what it is.  But this thing, this little process runs together with your Web apps.  You don't actually have to pay for any cloud service machines anymore.  So you can just run this whenever you're doing small stuff like, I don't know, making a thumbnail out of an image or things like that, that you usually do on your background processing threads.  So I'm going to show you how to deploy now our stupid, finally simple Web app or, sorry, Web job to Azure.  And that's easy too.  Let me get rid of this magnifying glass there.  Cool.  So again, here is the Web job.  I right click on this and I say publish as an Azure Web job.  I get to give it a name and I get to choose to run it maybe continuously, run it on a schedule, run it on demand.  Continuously is the one that makes sense when you're pulling a queue, but you can schedule things and it's going to use the Azure schedule or to schedule calls into your Web job method on a given schedule.  And you can run it on demand when you're running specific workloads as well, if you like.  But we're going to run it simply as continuously and say, okay, this adds another new get packet, package reference that only actually does one simple thing, creates a little configuration file for your Web job.  That's what it does.  So again, if I publish now, I already have that first step done.  I'm going to choose a Web app and it just so happens, of course, that I have an empty Web app in Azure right now.  Let's go and look at that in the portal.  So if I click here, you'll see that I have a Hello World Web job Web app.  It's out there and you can browse to it.  And if I browse to it, you can see that there's nothing there.  It's just an empty host.  Get rid of some of these tabs.  There's just an empty host.  So there could potentially be a Web job in here, but there isn't one yet.  So I'm going to choose my Web app already created in Azure and say, okay, this is the one I want to publish to and do publish.  Oh, while debugging.  Sorry.  Yes, I want to stop debugging.  We'll see.  Needed to build the thing.  Did I get it to publish?  I think so.  I was still debugging.  I was still running.  Yeah, so it's doing the should be.  Yeah, there we go.  Publish succeeded.  It's really fast.  The landline is really fast.  I've been running these demos on the Wi-Fi and they've been taking so much longer.  So this is good.  So again, where are the Web jobs now that I've deployed one?  Well, if you go into settings, there is this little obscure option there called Web jobs.  And you click into that and you get your running Web job continues running in Azure.  So what I said always on this thing won't always be on because I'm hosting this in free mode.  It's a free Web app.  That's that's how it how it runs, which means it's actually going to shut down after a while unless somebody actually calls the Web application.  Right.  So there are settings for that, like always on, which is the best thing to remember.  If you want to have your Web job running continuously always, you would want to set always on and then you can't host it in free mode.  But if you have that set up, you probably have a Web application anyway and you can host them together.  So that's fine.  So just flip the always on and then your Web job will be always running.  So it's right there now.  The Web job is running in Azure.  So let's let's test it out.  I'm not running locally anymore, but let's send a message to the Web job again.  This is also cool in Azure.  Right.  So we'll send that.  And you can actually look of course in the queue, but but the Web job has already picked up the message and therefore the text in here should have been changed already.  So now the Web job is running in Azure.  And if I flip on always on, this is going to perpetually keep pinging my queue to see if there are any messages.  I mean, could it be simpler?  Really?  That that's just this is mental.  But I love it.  It's it's it's very powerful.  So deployment done.  What about before the Web jobs?  I was talking.  I saw some people had been using the cloud service, the cloud service worker roles.  So again, that's a full server right there.  And I happen to have one right here.  A cloud service.  Not going to spend too much time on this because it's not what this session is about.  But basically you have your your cloud service deployment project and you have your worker and the worker has this worker role.  That contains all this code.  It's a role entry point.  And there seems to be some sort of a life cycle here on start run.  And you got to configure a bunch of stuff in there.  Yes, more code.  And then you run something.  Okay, async a method.  Something's run there.  Oh, down here somewhere is the actual code I wanted to run like one line of code was the thing I wanted to do.  But I have all this other stuff and that raises a bunch of questions.  You know, what is all of this?  You know, how is this hosted?  How do I deploy it?  What's the life cycle?  And how do I configure this and diagnostics and oh, there's lots of stuff.  Now, all I wanted to do was run a simple line of code.  And I would say you would kind of degrade a Windows server if you just run one line of code on the thing and just leave the process to doing nothing the rest of the time.  And you will be paying for the whole machine the whole time, right?  So therefore web jobs is much more logical.  So that's what we had and this, the cloud service, it's great.  If that's what you need, it's the proper tool.  If that's what you need to run.  Fine.  But if you run something simple like a simple batch, hence the code name simple batch, you will run a web job instead.  All right.  Now, you're saying here, Magnus, that you're running a process on a background thread in a web app.  Like, do I need web jobs for that?  I can roll my own.  And I can code this, not a problem.  I can code this, of course.  You know, I'm a developer.  Let's not, you know, use something somebody else built.  Let's build it ourselves, right?  Of course.  So let's do that.  Roll my own.  Okay.  I'll probably need an API or something.  I'll run a web app and I'm in the global here.  I'm going to go and do, so I've been a good citizen.  I've created an engine interface.  Of course.  That's what we're doing.  Running something on a background thread there.  Run container.  Okay.  Cool.  So I did a bit of an implementation here.  And so my implementation is about, you know, less than 120 lines of code.  And I'm trying to do it kind of proper with a task factory here and started task.  And I need something to monitor this task, keep running a timer that times out and checks  that the process is actually up and running still.  And, you know, there are some things I need to do.  So, you know, with this, about maybe two, 300 lines of code, I can do this myself, no problem.  But then I have code that I need to maintain that I need to take care of.  And there are some other things.  How do I know how well this is processing?  Oh, right.  But that's fine.  I'll do some diagnostics, right?  And this continues and continues.  And all of a sudden you're building something that isn't your business.  Again, your business was built running that one line of code.  You don't want to do all that other stuff, hosting a process and stuff like that.  So, you know, let's not do that.  That's probably unnecessary.  So, that's sort of summarized what we've learned so far.  This is not a big cloud service.  This is a simple thing, right?  It'll make it easier to use Azure Storage and other types of services.  As I said, you can use the service bus.  The coder that codes this needs to know nothing of these things.  It doesn't have to understand anything of Azure at all, which is good,  because at any given company you might have somebody who is like the Azure wizard,  probably you guys in the room right now.  You are the Azure guys at your companies.  And then the other guys just don't know about it.  And they don't have to.  And then, statistics included.  Okay.  So, the next step then is to show that dashboard that comes with the web jobs.  Going back to the portal, we have our web job here.  And if I say I want to browse again to this thing, like I said before, it's just there.  Do you guys know about Kudu, the thing that runs underneath your web apps in Azure?  Kudu is the engine that runs your web apps when you host them in Azure.  And you can reach that by typing in site control manager, SCM, inside of the URL like that.  You'll come into Kudu.  So, Kudu is running behind every web app that runs as an Azure web app.  Okay.  And inside there you can also do Azure jobs, slash Azure jobs.  There's actually a link that you can follow to get to this,  but I wanted to show you properly.  So, the web jobs will say that, hey, this site actually has a running web job.  But if I look at the functions that I have there, I get this error message.  And the reason I get an error message is because I didn't configure.  It says what you need to do quite clearly.  Magnifier, there you go, that you need to have a connection string named Azure WebJob dashboard, blah, blah, blah.  This configuration, you only need to do once.  But I am not going to do that.  I'm going to go back to this other web job, which is already configured by other demo.  It's already configured.  And it's looking at the same function.  So we can see in here that I have a function which is deployed and it should be there.  No functions, really?  No.  Yes, there it is.  So hello, NDC is running.  I get some nice statistics on how many times this has run.  And I can see these invocations in here that we have.  I can see the file as well.  I can look at the file and see the content of the file.  I can get that loaded.  I can see the input and output parameters and all that stuff.  And the log that I was talking about, it goes in here.  So you can see the log messages inside of your invocations of the web jobs.  And then you can actually replay this, baby, if you want to.  This is cool in Azure from the dashboard.  All right.  And that's just because we can output that to cool 42, another text.  And just replay that function from inside the dashboard.  So you can see if something went wrong, what went wrong, you'll get the full stack trace and everything in here, all the statistics,  and make sure you can monitor your web jobs to see how they're doing.  All this data is stored in your storage account, so it's not a problem either.  It's your data.  There's no magical thing here that's happening.  If I go over now to Azure there, then there's indeed a file called cool 42, which contains the new data.  So I can run it from the dashboard as well.  I think that is actually quite excellent.  You agree?  Yep.  I got some nodding heads.  Cool.  Thank you.  Thank you for interacting with me.  So now we have a dashboard and I didn't have to code that, which is, you know, it makes me happy.  And I can focus on that one line of code that I was going to deploy.  But now it's your turn.  Anyone got Wi-Fi in here?  You should go to this site right now and see if you can send me a nice message.  It'll be fun if you send me a nice message.  I'd appreciate that.  You know, I don't really have a lot of good self-confidence.  So please send me a message.  WebJobs live.  This very simple website is running in Azure.  And right now there is not a WebJob processing it.  So I can enter.  And this is the name of a blob.  So for you guys who think you can break my code, you probably can.  Send me a blob file name that isn't valid, like containing strange characters and stuff like that.  And which means I'll get a nice error message from when my code isn't properly executing.  I'm sure somebody is able to break my stuff.  Fail, for instance, is a good one.  I'll send another.  I'll send me a message myself.  But a lot of you guys are sending messages.  Cool thing about this is now I have a front end, the web application that takes the messages and puts them on a queue.  Now this queue is in here.  Live demo messages.  And you can see there are a couple of messages in there.  People have submitted some messages.  And nothing is processing this thing right now.  It's just sitting there on the queue.  You can continue to put messages on there if you like.  And I'll show you the code behind this thing.  So inside of my demo code here, I have a web application which will send messages onto a queue.  I believe the code is here.  So there, the post will take the file name of the body and turn that into a message and add that to a queue.  This code here needs the guy who writes this or gal, the person will have to have some experience with Azure storage in this case.  But I've talked to that team about that and they say they might actually create something that is void of the concept of this underlying storage structure that you can just send to and have that processed by the web job.  Anyway, I'm sending on a message onto the queue here and I have the web job which again isn't deployed yet.  But I will deploy it soon.  It's a very similar setup like you saw before.  Oops.  And I have a function called process messages which will trigger off the queue.  And you can see here some really, really cool things I can get the file name and that's a property on this message object.  And wait a minute.  That was a string before.  Now it's an object.  Well, guess what?  Web jobs will assume that the content of your queue message is a JSON serialized object if you bind to something in this case called message.  It will assume that the incoming messages will be of that type.  So you might try to break my code there.  Well, I don't think it will serialize unless when you start adding curly braces.  I don't know.  So the property file name is one of the properties of that JSON object.  And I might be able to get that in here so that I can actually output two blobs using that file name.  So I can get those pieces of information from my incoming message in the signature of my method.  And I'm doing the same kind of simple thing here.  The next thing I want to show is I'm using two methods now.  I'm triggering off the blob that I just wrote using a blob trigger.  So when there is a new blob in storage, please trigger this method instead.  I have a second method here that I'm also going to run.  And then I'm interacting with tables, Azure storage tables.  Early on in the development of SimpleBatch, they actually did not use the Azure table operation and stuff like that  because they tried to make an abstraction on top of tables, but it was horrible.  It was really bad.  They were trying to use dictionaries and key value pairs and stuff like that.  And it was like, ah, no, no, no, no.  They reverted to actually, in the case of tables, actually using Azure tables.  So I'm executing an operation on the table to insert your messages.  So your messages, excuse me, your messages will go on a queue.  And they will be pulled from the queue and written to a blob.  Then they will be pulled from the blob and written into a table just to show you that you can do that.  So very simple web job methods still.  Let's go ahead and deploy this.  Now, what I want to do now is I want to deploy the web app and the web job at the same time.  The web app is actually already deployed.  You've used it, but the web job is not deployed.  So I want to deploy them together.  So how do I do that?  Well, I can right click on my web app and say add existing project as Azure web job.  So there's tooling for it.  I'll have to select the project, this one, and it doesn't like that name.  So I'll say live web jobs.  Okay, this now adds the configuration to the web job and it adds a reference into my web app that says,  here's the web job you're going to have to deploy together with the web app.  So when I now go and say I'd like to publish this web app up to Azure to my web job's live site,  the one you've been using, the web job will come along with it.  It'll deploy together.  It's quite handy.  All right.  So this means that in a second or two, in a short while, we should have,  go to the other app, we should have a web job up there as well,  which will then automatically begin processing the queue messages that you've so nicely sent to me.  So web jobs.  See if it's already, yeah, so it's there and it's running.  And if I go back to the queue live demo messages, you can see that, yeah,  and here you can see something funny.  I'm glad we caught that.  Some of the messages you sent did not process okay.  And you can see it has a DQ count here on these things because these messages are not working properly.  One good one is to send null.  That's not a valid message.  That'll break the code.  So the web job will try to process the messages off the queue.  I think the default is 10 times.  You can change that, I think.  But it'll try to process the same message 10 times and it'll assume the message is poisonous because it can't be processed.  So what happens then is actually you will get a poison message queue where your messages that are poisonous that the code can't handle will wind up.  So these are the broken messages that are not functional.  So that automatically gets deferred into a separate queue which you can then process manually or with some other method.  But you won't be losing any data just because a message is poisonous and you won't crash your web job because a message is poisonous because that's already taken care of.  Poison message handling is important.  So this means that we should have some data, at least some data inside of our actual table.  Here's our table, live demo messages.  Let's see.  We do indeed have beer and Live Long and Prosper as some nice messages that you guys just sent me.  So those messages came through and wound up in the table.  And we should have some blobs also showing the temporary storage for these messages here that you sent me.  Okay.  So that's it.  And on all of this storage interaction stuff, as you can see here, there are a bunch of queues here called web jobs and there are a bunch of blob containers called web jobs.  All of this stuff is diagnostics.  The diagnostics that base the stuff you see on the dashboard.  So web jobs automatically stores diagnostics about the stuff that was invoked.  And if there's an error, it's going to catch the stack trace and put in the blob file for you.  And all of that stuff is just happening automatically by web jobs, which then motivates why there are two storage accounts that you can configure.  One for the diagnostics and another one for the data.  I'm using just one storage account in this demo, but I usually want to have two separate ones.  Just put the diagnostics to one side and have the business data on another account.  All right.  Any thoughts or questions so far?  You guys look really intently like you're really engaging in this.  I love that.  I can see you guys nodding and nodding us and sleeping.  Nodding us and you like this.  I appreciate it because this is actually fun stuff.  When I see this, every time I go like, nice.  Now I don't have to build that myself.  That's just so handy.  So I guess you can all imagine the many types of scenarios, lots of things you can do with this.  You can process queues, of course.  You can do an RSS aggregator.  You can do file maintenance, resizing images and all kinds of things that you want to run.  All kinds of things that you want to run on a background thread.  Couple of caveats, though.  If you run something that really sucks your CPU, what's going to happen?  Anyone?  It's going to cost.  It's going to cost the hell of it.  What it's going to cost is it's going to cost your website because your website is running on the same box.  But the Hello World WebJob that I deployed was deployed to a web application slot without any web app.  So you can run them separately if you need to, if you're running stuff that will consume a lot of CPU.  And actually, it runs 16 parallel processes by default.  You can change that number as well.  You can go down to one if that's what you need.  And you can also scale.  Again, this is deployed as web apps.  So you can take advantage of that and use auto scaling, for instance.  If you have a lot of messages coming in on the queue, like tens of thousands of messages,  you might need to check the queue length and scale on the queue length and have more machines processing the queue.  And everyone that starts up in the scaling will run 16 parallel processes just hammering away on that queue.  So there's a lot of power here.  You can quickly move up to a lot of processing power and you can also move down to very little if that's what you need.  So, and again, by the way, whenever somebody shows you a long list like this with bullet points,  it's that they don't really want you to remember all the facts and the details.  They just want to show you that there's a lot of stuff you can do.  So I have a couple of more demos. Let's see what we're doing on time.  We have about 20 minutes. Good.  I have a couple of more demos. It's actually just me showing you code.  Just to show you something that is a little bit more production worthy than Hello World.  Here's one that I really like. I did this with a customer and their response from the customer was that after we'd done this together,  we built this thing together, they wanted to copy files.  Classic, they wanted to have, we're going to upload our product releases to a storage account,  but we also want to copy that to have different mirror sites downloaded, like one in Asia, one in the US, one in Europe.  And we need to make sure we copy the files to all those locations.  I said, hey, that's a web job. Really easy to do, actually, with a web job.  Just mirror files, incoming blob files, copy them to another location in our implementation.  After we were done, they were like, if it gets any simpler than this,  we'll have to think the code and have it execute in our head or something, because this is just too easy.  I would agree.  I have a method here called copy release, which will take a message off a queue and write a response message once the method is finished.  And for those of you who are paying attention, you can see that I'm also using the async process programming model here  to use non-blocking operations, which is kind of handy as well.  So you can do that, and you can even use a cancellation token there if you want to.  So what I'm doing is I'm getting a reference to the blob I want to copy from.  I'm getting a reference to the blob I want to copy to, making sure that the first blob actually exists.  And then I create a shared access signature for those of you who know what that is.  It's something I can append to my URL to make it, in this case, read-only.  And now for the fun part.  When I'm copying here, I'm using an Azure Storage feature, which is a long name.  Start copy from blob async.  This is a command I'm sending to storage, giving it a URL saying,  this URL, copy the file you find there into yourself.  That's what I'm doing.  So that means that no, I'm not copying the, I'm not streaming the blob into memory on my box  and then streaming it back out into another storage account.  I'm telling storage to copy from A to B.  And while that's happening, I'm going to wait, I'm going to hang around here and do like a little delay and wait  and go back and check to the server, are you done yet?  Are you done yet?  Are you done yet?  Until it's done.  When the copy status is success, I've actually copied the blob from A to B,  and then I'm done, I'm going to write out a message saying, yes, I've copied this blob.  This is almost production-worthy code, and it'll solve the problem of copying files with using very, very few resources.  Just like a few lines of code, it's easy once you get to know these web job things.  Now, the other example that I have is also quite interesting.  It's the classic, classic example of you having a web application that receives maybe an upload file  or some data that needs to be processed, and then the code that receives that on your web server  takes a few seconds or 10 seconds or something to process this.  Like when you hit the submit button, the confirm button when you're booking holiday tickets or something,  it's going to process for a while while you wait, right?  It's going to think about this and make sure that everything went through and then come back to you and say,  ah, it's done.  So while that's happening, you're looking at the spinning donut of death wondering how long this is going to take.  Well, that feature, that thing is much better processed in the background, and after the processing is done,  send an email or a notification or have the web application go back and check, is it actually done yet?  That's much better to do.  So in this example, I can't run this actually because I don't have the database for it,  but I can show you the code that does this, and you'll understand, of course, how this is done.  Send emails.  So this web app that I have here is part of a demo workshop that I had.  It has some simple views that will take some input when you order cakes online to have them delivered,  and your order coming in will have to connect to some sort of repository and get some data,  and when you post back, it's going to take your order and your quantity and stuff like that  and put something on some kind of ordering service and submit that order,  and then after that's done, the ordering service has submitted the data.  You're also going to send out an email to the person who placed the order saying,  thank you for your order, blah, blah, blah.  All right?  So this takes a few seconds to process if you run this code,  and while you're doing that, the user is waiting,  and that's not a really good user experience,  and also it consumes resources on your web application,  so when you have like a million people ordering cakes from your business,  you need some really powerful machines.  So instead of doing that, I'll replace the ordering bit here.  I'll just take this code, replace that with this code,  which is my implementation of an Azure ordering service.  It's going to take the same information and plop it on a queue  and return to the waiting customer saying,  thank you for your order on the web browser,  and then once the order is processed on the background by the web job,  the email will be sent to the waiting customer saying,  yes, we have your order, your confirmation number, blah, blah, blah.  So that's a lot better to do it that way.  So in this case, of course, then I will be using this ordering service  to do pretty much the same thing as I did before,  except that instead of submitting it to the database,  blocking the application, et cetera,  I'm going to just simply put it on a queue again.  So I got the queue message here, putting that on the queue,  adding the message to the queue.  And of course, on the back end, the web job is going to do  roughly what the code did before inside of my business logic, right?  It's going to take the message and process it and send the email.  That's it.  Now, if I do it this way, your users will have a much better experience,  your web application will scale,  and everything will just be really beautiful,  and pretty soon you guys will be downstairs drinking beer  instead of coding.  All right.  Cool.  So basically, that is the session,  but there are a lot of more features that are interesting to look at,  and the rest of this session is basically like a feature bonanza thing  where I go through different features and we can talk about those  and you'll be enlightened and everything will be beautiful.  Does anyone have, yes, questions, exactly.  Regarding the signature of the...  Regarding the signature of the function,  well, it needs to be a public static method,  and it needs to have some parameter that has those triggers.  It needs to trigger on something,  but I did continuous web jobs in my example.  I did continuous ones.  I have web job methods that you can flag them saying,  this is a web job method,  and that might be run by you on demand instead of the triggering method  that I did with the attributes.  You can have things that run on a schedule, things that run on demand.  Yes, the parameters for the order in this case,  this is packed inside of JSON,  the parameters of the...  No, it's not packed into it.  The question is, are the parameters packed into the JSON  or anything like that?  No, it's not, because what web jobs will do,  it will inspect the code that it has in its bin folder,  and it will find the methods that have any web job attributes on them,  and it will do that using reflection.  So it will just figure out what stuff there is,  and you saw when I had, for instance, I had a message that was a string,  and then in another case I had a message which was of type message,  and when it sees, well, message of type message,  that must mean that the incoming message will be a JSON serialized object  with these parameters, otherwise I can't serialize into that.  And if that breaks, then you'll get an error saying,  well, the message I received wasn't a JSON serialized message object,  it was something else, I couldn't deserialize.  So you'll get the sort of full support in these parameters,  and it'll tell you when you do something wrong,  because you will see that there were invocations that were not processed properly.  So it'll help you all the way.  Again, this is built to be simple, right?  Simple, simple, simple.  That is what it is.  Any more questions?  Yes.  Is a queue the only way to trigger a continuous web job?  Is a queue the only way to trigger a continuous web job?  There are three ways of doing it.  You can trigger a continuous web job on a queue,  an Azure Storage queue, on a Service Bus queue, or on a blob.  The blob one is a little bit more dicey.  It means that you upload a blob to a blob storage account,  and at some point the web job using the Azure Blob Storage statistics will see,  is there a new file which is added later to this container than when I checked last.  So it'll keep statistics on this,  and it will execute your method based on incoming blobs.  But I've had a problem with a customer scenario for this exact thing.  They needed to make sure that the triggering was happening fast.  And with the specific blob trigger, it can take a little time.  It depends on how much traffic there is on your storage account and stuff like that.  With the queues, you could set the number of seconds, how often do you pull?  The default is to fall back and pull as few times as once every 30 seconds  if there are no messages on the queue, but if there are messages,  it's going to continuously just process them.  But the blobs will take a little more time. That's a great question.  Did they answer your question?  Yeah, it was blobs.  Yeah, blobs, it works.  How to target it to allow the... ...time schedule?  Yeah.  How long can you go ahead and do it?  What's the question?  Yeah, so the question is, if I use a scheduled trigger on intervals  called this web job method, how fast can I put that schedule?  And I believe you can do something along the lines of once every second or something,  but you'd have to pay for that scheduler.  This is the Azure scheduler you're running at that point.  You're running the scheduler which is in Azure.  That's the thing which is going to be configured to call into your method  on a given or called your web job and say,  hey, dude, wake up, call this method, do it.  And it's going to do that on the schedule that you set.  So it's based on that feature.  Okay?  Still, it's a very valid way of doing it.  Like, have the scheduler call frequently to your web job method  and have your web job then do something.  It doesn't even have to have any parameters at that point.  Really only have to have an attribute saying, I'm a web job.  Good question.  All right?  Yes, another question.  What's the maximum...  What's the maximum length of time a web job can last?  Yes, what's the maximum length of time a web job can last?  That is a great question.  And it's not as long as I would like because I've had some web job methods go and say,  never finished.  And it gets sort of this yellow status.  You can have red, failed, green, okay, and yellow, I didn't complete.  And the reason why that happened to me was that I was starving my machine  because I was running it really hot and it couldn't process everything  so it stopped processing things after a while.  So that happened to me and I was trying to do too much inside of a web job basically  but at least I got information about it.  So it'll shut it down.  But the web job itself can run for a long time  because Azure Storage, also the service bus queues,  have the feature that you're able to go back to the message  and update the lease time you have on the message.  So for those of you who know how Azure Storage queues work,  when you dequeue a message, it's hidden on the queue for you for a period of time.  And if you don't return and say, delete message, which means I'm done with the message now,  the message will reappear on the queue and you will get that dequeue count increase.  And after 10 tries, I got poison messages, right?  So that was built into the feature of the web jobs.  But it's leaning on a feature of Azure Storage  and you can go back to the queue and say I'd like to update the message  and you can actually change the content of the message funny enough  but you can also say I'd like to have the lease extended for another period of time  and you can go back and do that however many times you like.  So you can, in theory, keep a message forever  but forever in Azure Storage queues is seven days.  So a long time is the answer.  But it's a valid question. It's one of those like, what is this?  Yes, these are great questions. It means that you guys are paying attention.  I love that. Any more questions?  What are the maximum size of the message in the queue?  The maximum size of the message in the queue is not a web job question.  It's an Azure Storage queue question but I can answer that, absolutely.  It's 64K and if you need bigger ones, the normal process is to put the message body  in a blob in Azure Storage and put a reference to the blob in the queue.  So that works but then you have to do two things but it works.  Yeah, great question.  So sometimes you have messages that are larger than 64K.  It's actually 256 in service bus queues.  So you can use those instead if you have messages that are not larger than 256.  Great.  I see that you guys are thinking about all the things you're going to build with this when you come home  and that's basically the point of this talk is really to give you a tool that you didn't know about  and then when you go back home it's like, oh, holy crap, we're going to throw some stuff out now.  And this engine thing that we were having, we're maintaining, no.  This background thread thing we're running, no, no, no, no, no.  Don't do it that way, that's the wrong way of doing it.  All right, we only have a few more minutes.  I think most of this stuff I have talked about is sync-weight binding.  Yeah, you saw me parameterizing bindings using parameters from the, using your names and stuff like that  from the messages and things like that.  It's really, really handy.  You can get the DQ count if you want to do something with that inside of your code.  You can get the DQ count saying, hey, have I processed this message before?  Because sometimes that's something you need to know inside of your code.  And streams are really cool.  If you're reading off a blob trigger, you can get the input as a stream.  You can get it as a text reader.  You can even get it as a string.  So all of these bindings just work out of the box depending on what you want to do.  If it's an image file, getting a text reader or a string doesn't make any sense.  You might want to get the stream instead.  But, you know, you can even actually go and do a stream binder to bind to other types of objects.  In this case, a web image is my parameter.  But the blob, the job host doesn't know how to read a web image.  So you can create your iCloud stream binder of web image and explain to web jobs how to change your stream into a web image and back.  So it's actually quite handy and powerful.  So your methods can have a really smart signature and you'll just have this conversion thing running in the background.  So no automatic trigger means only manual triggering.  Right.  So basically that and then the service bus, I've told you that.  I think I've told you all the features that I wanted to talk about.  There are videos in my blog post that you can check if there are any specific ones you want to learn about and I have videos showing that.  So are there any more questions at this point?  Before I summarize.  I think we may have emptied out all the questions.  That's great. Thank you.  So this is not a big cloud service.  This is simple stuff.  It's easier to use than and using storage direct because I just have to have an attribute and then I can use a string instead of doing add message or get message and delete message.  And how do I handle these and all that stuff?  You don't have to know that inside of your your your logic that runs the web job and all that monitoring and diagnostic stuff that you get included in the package.  And again, like I don't want to sound like a cheap car salesman or anything, but you run this at no additional cost because it's it's you're still.  If you are running your web apps, of course, I mean, if you're not running web apps, then it's going to cost you a web app.  But other than that, but wait, there's more.  Now, I can't actually run the debugging demo because I'm using Visual Studio RC and Windows 10 and stuff like that.  I tried, but it's not working.  But I can show you how it would be working if if I didn't run this RC version and stuff like that.  You know about the service server explorer, you can go and look at your your Azure stuff.  And if I go down to my web apps, we have two web apps running now the Hello World web job would be the one that I would connect to if I could.  But unfortunately, me installing my my machine was not a smart thing to do.  It goes out to Azure and checks do I have a web job running in this application I do indeed.  And then I can right click on this.  Am I running it?  Oh, it's not.  Oh, it's not.  It's not running.  It detected that.  Yes, it's there, but it stopped running.  So I might have to start it up first.  But once I've started it up, I can attach.  Well, in theory, I can attach the debugger to a running web job, which is running out in Azure.  And I can debug from Visual Studio right into my code.  And I think that's pretty sweet.  I can't demo it today, unfortunately, but you'll have to trust me that it works.  So that was, I guess that that's the summary.  And whoops, let's get rid of the magnifier.  Go away.  I said go away.  Ah, that was the presentation, ladies and gentlemen, I appreciate you taking the time.  And again, this is my passion.  I love doing this.  I love talking about it, but I love doing it.  And if there are any additional questions, do not hesitate to send me an email.  That's not a problem at all.  And you know, you should go and drink beer now.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.
Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_0_4007.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_4008_5099.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_5100_6167.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_6168_6239.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_6240_6347.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_6348_7331.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_7332_7619.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_7620_7919.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_7920_8243.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_8244_8687.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_8688_13379.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_13380_13847.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_13848_14111.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_14112_18827.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_18828_18923.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_18924_19295.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_19296_19379.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_19380_19859.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_19860_20663.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_20664_20999.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_21000_21203.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_21204_21911.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_21912_21959.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_21960_24215.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_24216_24983.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_24984_25235.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_25236_25955.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_25956_26111.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_26112_26267.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_26268_26315.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_26316_26603.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_26604_27311.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_27312_27491.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_27492_29087.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_29088_30287.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_30288_32999.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_33000_33515.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_33516_36959.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_36960_37031.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_37032_37187.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_37188_38687.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_38688_38795.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_38796_38951.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_38952_39011.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_39012_39083.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_39084_39563.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_39564_41279.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_41280_41627.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_41628_42047.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_42048_42491.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_42492_42563.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_42564_44111.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_44112_44531.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_44532_44639.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_44640_46175.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_46176_51539.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_51540_51623.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_51624_52211.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_52212_52703.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_52704_52823.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_52824_55247.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_55248_56975.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_56976_57131.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_57132_60479.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_60480_71303.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_71304_86939.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_86940_88919.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_88920_89027.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_89028_89435.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_89436_89543.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_89544_89639.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_89640_89783.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_89784_89831.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_89832_90071.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_90072_90947.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_90948_91007.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_91008_91223.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_91224_92027.png Microsoft_Azure_Web_Jobs_-_the_new_way_to_run_your_workloads_92028_100604.png
So Tech Guy says everything is good to go. Sweet. I'm on the screen. Maybe we should get started. Let's do that. Hi. Welcome. Welcome to this, the last session slot of the day. I appreciate you guys being in this room because obviously it means that you are really passionate about being at this presentation. There are some other really good ones going on at the same time, so I appreciate your attendance. I will do my best to entertain. I just want to check with you. Are you running any workloads in Azure at this time? Hands up. Most of you are. Are you running web apps? Okay. So anyone running the web jobs? One guy. All right. That's great. That's great. That's a good baseline for this talk. Now I know what you're all about. You look like a pretty intelligent bunch. So when you leave here, I know the answer to that really strange question. They're asking by the door. There are three colors. Anyone colorblind? No? Okay, good. The answer is green, just so you know. Making sure you know this. Okay, cool. So web jobs that I'm going to talk about is basically background processing in your Azure web apps. That's what it is, right? And means that it's part of the Azure app service. You got the logic apps and all those things you can do. But it's kind of cool because it's baked in there so you don't have to, you don't pay any extra to run this stuff. And also it means that if you have something simple, something batch processing like that is simple that you want to run, you can run that in web jobs. And it's a simple batch. It's sort of italic here in this slide because that was the code name for web jobs when they were building it. All right. My name is Magnus. Martin Sonam from Sweden, from Malmo. So I could go with Swedish Norwegian but I guess there are some people here who are not from Norway. Anyone not from Norway? Yes, several. So we'll stick to English of course. If there is anything at all, like don't hesitate to send me an email and ask, you know, about this session or, you know, about Azure actually. Because Azure is what I do. I'm also an MVP for Azure. I was the first one to be an Azure MVP in the Nordic countries. And I'm also what Microsoft call a regional director, which kind of means that they're still not paying me unfortunately. But they kind of like having me around. So I'm a business partner of Microsoft. I like to do community stuff. Have anybody here heard about the global Azure boot camp? Several people. Cool. So the global Azure boot camp happens once a year. It has happened three times now. We'll see if it happens next year in the spring. All of these locations all over the world. It was 182 locations last time through a one day Azure community gathering, get together, learn about Azure event as a community. All these community leaders all over the world did it and we did it on the same day. So it's pretty cool. 182 locations, something like in the size of 10,000 attendees, pretty big event. And we had a hashtag for that. So it's kind of fun. That's the kind of thing that I like to do on my spare time. And also we have a small conference called cloud burst, which is pretty good. If you ask me, we invite basically like five or six, seven, eight MVP speakers and talk about Azure and it's streamed online. So you might want to catch that. So that's kind of base base lining this this session. I've been about been around this web jobs thing since it was called simple batch and since before you guys knew about it. That's one of the perks of being an MVP. Get sort of get invited by our, you know, people we know on the on the development teams that there are our friends and they're showing us the latest stuff. Hey, look at this. This thing here. We're building this simple batch thing and that. So I got kind of got sucked into that. And you know, I don't mean to imply that I'm cool or anything. I just want to show you guys that Azure Web Jobs documentation resources on the website there. If you scroll down on that far enough, you will get to some additional web jobs resources and there's a link to my blog right there. So and some videos that I made the videos link is right there as well. So on my blog post reason I'm showing you this is not, you know, again, I don't want to stress, you know, any, any fame or anything at all. I just want to point you to a valid resource. You could you should check out these videos after the presentation. There's a bunch of them there that goes through several of the features of Web Jobs so you can learn all these things. You should do that. We're going to start off with a demo and I'm going to show you what a Web Job is. Here is Visual Studio and I've got a very, very simple console application here. Now there is a file new experience for this thing. You can do file new projects and get an Azure Web Job set up and running and you'll have the stuff that I'm going to add manually. But I like to show it manually step by step because that'll give you exactly what's in here at all, you know, specifics about it. If you have your very simple application, super simple, very straightforward console app, this thing runs. It doesn't do anything. It runs and stops. It's just a console app. What I can do is go ahead and add, of course, everything is a new get package these days. I'll go and add Microsoft Azure Web Jobs to the console app. It'll install a few things. It looks like a lot but it's really not that bad. I'm going to show you mostly we're going to interact with just one thing. Just make sure that this thing finishes. I'm on a hard line so I think even though the Wi-Fi is spotty, I think we're still good. That would be bad. It's kind of difficult to do an Azure session without the Internet. It's like, yeah. But it seems to be, yeah, it's going through. Okay, cool. So now we've added a bunch of references in here. And again, you would think that it looks like a lot but we're really only going to be interacting with the first two here, the Web Jobs SDK. Now, I'm writing code in C sharp but you could have, you can create a Web job which is a PowerShell script or a BAT file or whatever command line stuff. You can, and the Python scripts and stuff like that. But I'm going to stick to plain old C sharp code web application or console applications. So this is stuff we're going to be interacting with. What are you doing? All right, all right, party seems to be starting. That's cool. So don't mind the other people are actually having fun. Stick around. So we're going to do a job host. One of those. A job host is the thing that hosts your Web jobs and you'll see in a minute what a Web job is. I like configuration on that. This is not something you always have to do but for the sake of demoing, there's one little thing I'd like to tweak in the queue setup. And you'll know more what this means in a minute. But I need to set the max polling interval there to, not milliseconds, sorry. From seconds to five seconds. Otherwise it might poll as little as 30 seconds and we'll have to wait for demos to complete. So I'll just do that. Now there's one more thing that I need to do in my main method and it's just to say job host run and block. This run and block statement here is the equivalence of building a VCF application and saying host.open. That's exactly what happens now. So I can run this thing now and no, actually I can't. There's one more thing I need to do. So you need to have the Nougat reference and you need to configure one thing in your app config file to get a Web job running properly. And that's a reference to some storage. These two references have to be in there by default but you can set them in code as well if you like. But it's better. It's really easy to put them in here. So I always do that. The reference is here's the Azure portal and here's my Web jobs, demos, resource group and I have a storage account in there. That's the storage account that's being referenced in my Web jobs project. So that's the one. It's empty and I'll show you that in an explorer in a minute. So once we have these two things, the Nougat package reference, the host.open, run and block statement and your configuration there. You're ready to go. But we still don't have any Web jobs. This is empty now. If I launch it, it's going to say there are no Web jobs here. So what is a Web job finally? Well, it's a method. Should we do hello? Let's do hello NDC or something like that, right? Now this is just a method. Not a Web job method yet. I'll add a parameter to it. A Q trigger. Let's call the Q NDC. We're going to be watching a Q called NDC for messages. So they'll be coming in as strings. Now this thing is a Web job. It's not doing anything, but the Q trigger tells the Web job host that, hey, this method is a Web job. So you can call this method and you're going to be calling this method every time there's a message on the Q. So Web jobs has a polling mechanism that you don't have to build or maintain or take care of. How many have worked with Azure Storage Qs? Few, but not that many. Okay. Well, Qs are really great. You can use service bus as well if you want to, but I'm going to use Azure Storage Qs in my demos. It's roughly the same in this context. We need to do something with this and I'm actually going to add two more parameters to our little method. I'm going to bind to a blob and let's say NDC again. NDC, cool.txt. And that's going to be an out string result. And then one more parameter. Let's do a text writer. Log. We're going to call that log. So there are a couple of magic parameters with Web jobs. Log is one of those. This means I can do logging from inside of my Web job methods. All right. Result. Don't type and talk at the same time. Result equals the message is plus the message. All right. And then let's do logging on that as well. Right line. Result. Okay. Now this is a proper Web job method that does have a little bit of logic. I'm taking note of what the messages are that we send in. So this is it. This is really it. And the cool thing about this is if I set a break point, instead I can execute this from my PC from from Visual Studio hitting at five. This job host is now starting. And then there's not a lot of interesting stuff happening on the console window, but but it is starting. So we're talking about now using a queue to trigger this Web job, a queue called NDC. And then there's a little bit of magic going on here because we don't actually have a queue called NDC yet. If you go to my storage account here inside of inside of the Azure management studio, I can see my Web jobs demo. Storage account and there is no queue there. So let's create one. We need to name it NDC, of course. Oh, this is difficult. Let's let's zoom out again. You create it and call it NDC. And so now the queue exists. And let's put a message on that queue. This is cool. Right. So this is cool. Okay. That is pretty cool. So the Web jobs host knows about my method knows that it triggers on the queue on the message on the queue and it pulls the queue for me. I don't have to do anything. As you may or may not notice here, if you've been using Azure storage, there is nothing in here that says Azure storage. The coder that codes this doesn't have to know anything at all about Azure. Nothing. It's a console app, literally. So I'm going to send that message through and the message has now produced a result. The result is going to be in a file. Isn't it awesome to have like a session when the party started? That's pretty cool. I appreciate you guys being here because it sounds like they have a blast down there. All right, cool. Blob containers. Let's look. Is there an NDC container? Indeed, there is. There is a file called cool.text and yes, the message is in there. Okay. So it was that simple to read from a queue and write to a blob. That's, of course, a stupefiling simple Web job. I have some sort of, I have actual business scenario demos further down the line here to show that, of course, you can do more complicated things like this. But this shows the baseline. This shows what it is. So we have that. So where are these Web jobs anyway? Well, that's the thing. It's kind of a hidden feature. They've talked about making Web jobs sort of a first class citizen of Azure making in its own service that stand alone. So we're pairing the menu and stuff like that. But it's sort of a hidden feature right now inside of Web apps. And that means that because your Web jobs are hosted together with your Web apps, first of all, you actually have to pay for any cost of running them. Now, has anyone in here used a cloud service, a worker role? Yeah, a few have used a cloud service worker role. That's your complete full entire like a Windows server running your code for doing batch processing, right? That's what it is. But this thing, this little process runs together with your Web apps. You don't actually have to pay for any cloud service machines anymore. So you can just run this whenever you're doing small stuff like, I don't know, making a thumbnail out of an image or things like that, that you usually do on your background processing threads. So I'm going to show you how to deploy now our stupid, finally simple Web app or, sorry, Web job to Azure. And that's easy too. Let me get rid of this magnifying glass there. Cool. So again, here is the Web job. I right click on this and I say publish as an Azure Web job. I get to give it a name and I get to choose to run it maybe continuously, run it on a schedule, run it on demand. Continuously is the one that makes sense when you're pulling a queue, but you can schedule things and it's going to use the Azure schedule or to schedule calls into your Web job method on a given schedule. And you can run it on demand when you're running specific workloads as well, if you like. But we're going to run it simply as continuously and say, okay, this adds another new get packet, package reference that only actually does one simple thing, creates a little configuration file for your Web job. That's what it does. So again, if I publish now, I already have that first step done. I'm going to choose a Web app and it just so happens, of course, that I have an empty Web app in Azure right now. Let's go and look at that in the portal. So if I click here, you'll see that I have a Hello World Web job Web app. It's out there and you can browse to it. And if I browse to it, you can see that there's nothing there. It's just an empty host. Get rid of some of these tabs. There's just an empty host. So there could potentially be a Web job in here, but there isn't one yet. So I'm going to choose my Web app already created in Azure and say, okay, this is the one I want to publish to and do publish. Oh, while debugging. Sorry. Yes, I want to stop debugging. We'll see. Needed to build the thing. Did I get it to publish? I think so. I was still debugging. I was still running. Yeah, so it's doing the should be. Yeah, there we go. Publish succeeded. It's really fast. The landline is really fast. I've been running these demos on the Wi-Fi and they've been taking so much longer. So this is good. So again, where are the Web jobs now that I've deployed one? Well, if you go into settings, there is this little obscure option there called Web jobs. And you click into that and you get your running Web job continues running in Azure. So what I said always on this thing won't always be on because I'm hosting this in free mode. It's a free Web app. That's that's how it how it runs, which means it's actually going to shut down after a while unless somebody actually calls the Web application. Right. So there are settings for that, like always on, which is the best thing to remember. If you want to have your Web job running continuously always, you would want to set always on and then you can't host it in free mode. But if you have that set up, you probably have a Web application anyway and you can host them together. So that's fine. So just flip the always on and then your Web job will be always running. So it's right there now. The Web job is running in Azure. So let's let's test it out. I'm not running locally anymore, but let's send a message to the Web job again. This is also cool in Azure. Right. So we'll send that. And you can actually look of course in the queue, but but the Web job has already picked up the message and therefore the text in here should have been changed already. So now the Web job is running in Azure. And if I flip on always on, this is going to perpetually keep pinging my queue to see if there are any messages. I mean, could it be simpler? Really? That that's just this is mental. But I love it. It's it's it's very powerful. So deployment done. What about before the Web jobs? I was talking. I saw some people had been using the cloud service, the cloud service worker roles. So again, that's a full server right there. And I happen to have one right here. A cloud service. Not going to spend too much time on this because it's not what this session is about. But basically you have your your cloud service deployment project and you have your worker and the worker has this worker role. That contains all this code. It's a role entry point. And there seems to be some sort of a life cycle here on start run. And you got to configure a bunch of stuff in there. Yes, more code. And then you run something. Okay, async a method. Something's run there. Oh, down here somewhere is the actual code I wanted to run like one line of code was the thing I wanted to do. But I have all this other stuff and that raises a bunch of questions. You know, what is all of this? You know, how is this hosted? How do I deploy it? What's the life cycle? And how do I configure this and diagnostics and oh, there's lots of stuff. Now, all I wanted to do was run a simple line of code. And I would say you would kind of degrade a Windows server if you just run one line of code on the thing and just leave the process to doing nothing the rest of the time. And you will be paying for the whole machine the whole time, right? So therefore web jobs is much more logical. So that's what we had and this, the cloud service, it's great. If that's what you need, it's the proper tool. If that's what you need to run. Fine. But if you run something simple like a simple batch, hence the code name simple batch, you will run a web job instead. All right. Now, you're saying here, Magnus, that you're running a process on a background thread in a web app. Like, do I need web jobs for that? I can roll my own. And I can code this, not a problem. I can code this, of course. You know, I'm a developer. Let's not, you know, use something somebody else built. Let's build it ourselves, right? Of course. So let's do that. Roll my own. Okay. I'll probably need an API or something. I'll run a web app and I'm in the global here. I'm going to go and do, so I've been a good citizen. I've created an engine interface. Of course. That's what we're doing. Running something on a background thread there. Run container. Okay. Cool. So I did a bit of an implementation here. And so my implementation is about, you know, less than 120 lines of code. And I'm trying to do it kind of proper with a task factory here and started task. And I need something to monitor this task, keep running a timer that times out and checks that the process is actually up and running still. And, you know, there are some things I need to do. So, you know, with this, about maybe two, 300 lines of code, I can do this myself, no problem. But then I have code that I need to maintain that I need to take care of. And there are some other things. How do I know how well this is processing? Oh, right. But that's fine. I'll do some diagnostics, right? And this continues and continues. And all of a sudden you're building something that isn't your business. Again, your business was built running that one line of code. You don't want to do all that other stuff, hosting a process and stuff like that. So, you know, let's not do that. That's probably unnecessary. So, that's sort of summarized what we've learned so far. This is not a big cloud service. This is a simple thing, right? It'll make it easier to use Azure Storage and other types of services. As I said, you can use the service bus. The coder that codes this needs to know nothing of these things. It doesn't have to understand anything of Azure at all, which is good, because at any given company you might have somebody who is like the Azure wizard, probably you guys in the room right now. You are the Azure guys at your companies. And then the other guys just don't know about it. And they don't have to. And then, statistics included. Okay. So, the next step then is to show that dashboard that comes with the web jobs. Going back to the portal, we have our web job here. And if I say I want to browse again to this thing, like I said before, it's just there. Do you guys know about Kudu, the thing that runs underneath your web apps in Azure? Kudu is the engine that runs your web apps when you host them in Azure. And you can reach that by typing in site control manager, SCM, inside of the URL like that. You'll come into Kudu. So, Kudu is running behind every web app that runs as an Azure web app. Okay. And inside there you can also do Azure jobs, slash Azure jobs. There's actually a link that you can follow to get to this, but I wanted to show you properly. So, the web jobs will say that, hey, this site actually has a running web job. But if I look at the functions that I have there, I get this error message. And the reason I get an error message is because I didn't configure. It says what you need to do quite clearly. Magnifier, there you go, that you need to have a connection string named Azure WebJob dashboard, blah, blah, blah. This configuration, you only need to do once. But I am not going to do that. I'm going to go back to this other web job, which is already configured by other demo. It's already configured. And it's looking at the same function. So we can see in here that I have a function which is deployed and it should be there. No functions, really? No. Yes, there it is. So hello, NDC is running. I get some nice statistics on how many times this has run. And I can see these invocations in here that we have. I can see the file as well. I can look at the file and see the content of the file. I can get that loaded. I can see the input and output parameters and all that stuff. And the log that I was talking about, it goes in here. So you can see the log messages inside of your invocations of the web jobs. And then you can actually replay this, baby, if you want to. This is cool in Azure from the dashboard. All right. And that's just because we can output that to cool 42, another text. And just replay that function from inside the dashboard. So you can see if something went wrong, what went wrong, you'll get the full stack trace and everything in here, all the statistics, and make sure you can monitor your web jobs to see how they're doing. All this data is stored in your storage account, so it's not a problem either. It's your data. There's no magical thing here that's happening. If I go over now to Azure there, then there's indeed a file called cool 42, which contains the new data. So I can run it from the dashboard as well. I think that is actually quite excellent. You agree? Yep. I got some nodding heads. Cool. Thank you. Thank you for interacting with me. So now we have a dashboard and I didn't have to code that, which is, you know, it makes me happy. And I can focus on that one line of code that I was going to deploy. But now it's your turn. Anyone got Wi-Fi in here? You should go to this site right now and see if you can send me a nice message. It'll be fun if you send me a nice message. I'd appreciate that. You know, I don't really have a lot of good self-confidence. So please send me a message. WebJobs live. This very simple website is running in Azure. And right now there is not a WebJob processing it. So I can enter. And this is the name of a blob. So for you guys who think you can break my code, you probably can. Send me a blob file name that isn't valid, like containing strange characters and stuff like that. And which means I'll get a nice error message from when my code isn't properly executing. I'm sure somebody is able to break my stuff. Fail, for instance, is a good one. I'll send another. I'll send me a message myself. But a lot of you guys are sending messages. Cool thing about this is now I have a front end, the web application that takes the messages and puts them on a queue. Now this queue is in here. Live demo messages. And you can see there are a couple of messages in there. People have submitted some messages. And nothing is processing this thing right now. It's just sitting there on the queue. You can continue to put messages on there if you like. And I'll show you the code behind this thing. So inside of my demo code here, I have a web application which will send messages onto a queue. I believe the code is here. So there, the post will take the file name of the body and turn that into a message and add that to a queue. This code here needs the guy who writes this or gal, the person will have to have some experience with Azure storage in this case. But I've talked to that team about that and they say they might actually create something that is void of the concept of this underlying storage structure that you can just send to and have that processed by the web job. Anyway, I'm sending on a message onto the queue here and I have the web job which again isn't deployed yet. But I will deploy it soon. It's a very similar setup like you saw before. Oops. And I have a function called process messages which will trigger off the queue. And you can see here some really, really cool things I can get the file name and that's a property on this message object. And wait a minute. That was a string before. Now it's an object. Well, guess what? Web jobs will assume that the content of your queue message is a JSON serialized object if you bind to something in this case called message. It will assume that the incoming messages will be of that type. So you might try to break my code there. Well, I don't think it will serialize unless when you start adding curly braces. I don't know. So the property file name is one of the properties of that JSON object. And I might be able to get that in here so that I can actually output two blobs using that file name. So I can get those pieces of information from my incoming message in the signature of my method. And I'm doing the same kind of simple thing here. The next thing I want to show is I'm using two methods now. I'm triggering off the blob that I just wrote using a blob trigger. So when there is a new blob in storage, please trigger this method instead. I have a second method here that I'm also going to run. And then I'm interacting with tables, Azure storage tables. Early on in the development of SimpleBatch, they actually did not use the Azure table operation and stuff like that because they tried to make an abstraction on top of tables, but it was horrible. It was really bad. They were trying to use dictionaries and key value pairs and stuff like that. And it was like, ah, no, no, no, no. They reverted to actually, in the case of tables, actually using Azure tables. So I'm executing an operation on the table to insert your messages. So your messages, excuse me, your messages will go on a queue. And they will be pulled from the queue and written to a blob. Then they will be pulled from the blob and written into a table just to show you that you can do that. So very simple web job methods still. Let's go ahead and deploy this. Now, what I want to do now is I want to deploy the web app and the web job at the same time. The web app is actually already deployed. You've used it, but the web job is not deployed. So I want to deploy them together. So how do I do that? Well, I can right click on my web app and say add existing project as Azure web job. So there's tooling for it. I'll have to select the project, this one, and it doesn't like that name. So I'll say live web jobs. Okay, this now adds the configuration to the web job and it adds a reference into my web app that says, here's the web job you're going to have to deploy together with the web app. So when I now go and say I'd like to publish this web app up to Azure to my web job's live site, the one you've been using, the web job will come along with it. It'll deploy together. It's quite handy. All right. So this means that in a second or two, in a short while, we should have, go to the other app, we should have a web job up there as well, which will then automatically begin processing the queue messages that you've so nicely sent to me. So web jobs. See if it's already, yeah, so it's there and it's running. And if I go back to the queue live demo messages, you can see that, yeah, and here you can see something funny. I'm glad we caught that. Some of the messages you sent did not process okay. And you can see it has a DQ count here on these things because these messages are not working properly. One good one is to send null. That's not a valid message. That'll break the code. So the web job will try to process the messages off the queue. I think the default is 10 times. You can change that, I think. But it'll try to process the same message 10 times and it'll assume the message is poisonous because it can't be processed. So what happens then is actually you will get a poison message queue where your messages that are poisonous that the code can't handle will wind up. So these are the broken messages that are not functional. So that automatically gets deferred into a separate queue which you can then process manually or with some other method. But you won't be losing any data just because a message is poisonous and you won't crash your web job because a message is poisonous because that's already taken care of. Poison message handling is important. So this means that we should have some data, at least some data inside of our actual table. Here's our table, live demo messages. Let's see. We do indeed have beer and Live Long and Prosper as some nice messages that you guys just sent me. So those messages came through and wound up in the table. And we should have some blobs also showing the temporary storage for these messages here that you sent me. Okay. So that's it. And on all of this storage interaction stuff, as you can see here, there are a bunch of queues here called web jobs and there are a bunch of blob containers called web jobs. All of this stuff is diagnostics. The diagnostics that base the stuff you see on the dashboard. So web jobs automatically stores diagnostics about the stuff that was invoked. And if there's an error, it's going to catch the stack trace and put in the blob file for you. And all of that stuff is just happening automatically by web jobs, which then motivates why there are two storage accounts that you can configure. One for the diagnostics and another one for the data. I'm using just one storage account in this demo, but I usually want to have two separate ones. Just put the diagnostics to one side and have the business data on another account. All right. Any thoughts or questions so far? You guys look really intently like you're really engaging in this. I love that. I can see you guys nodding and nodding us and sleeping. Nodding us and you like this. I appreciate it because this is actually fun stuff. When I see this, every time I go like, nice. Now I don't have to build that myself. That's just so handy. So I guess you can all imagine the many types of scenarios, lots of things you can do with this. You can process queues, of course. You can do an RSS aggregator. You can do file maintenance, resizing images and all kinds of things that you want to run. All kinds of things that you want to run on a background thread. Couple of caveats, though. If you run something that really sucks your CPU, what's going to happen? Anyone? It's going to cost. It's going to cost the hell of it. What it's going to cost is it's going to cost your website because your website is running on the same box. But the Hello World WebJob that I deployed was deployed to a web application slot without any web app. So you can run them separately if you need to, if you're running stuff that will consume a lot of CPU. And actually, it runs 16 parallel processes by default. You can change that number as well. You can go down to one if that's what you need. And you can also scale. Again, this is deployed as web apps. So you can take advantage of that and use auto scaling, for instance. If you have a lot of messages coming in on the queue, like tens of thousands of messages, you might need to check the queue length and scale on the queue length and have more machines processing the queue. And everyone that starts up in the scaling will run 16 parallel processes just hammering away on that queue. So there's a lot of power here. You can quickly move up to a lot of processing power and you can also move down to very little if that's what you need. So, and again, by the way, whenever somebody shows you a long list like this with bullet points, it's that they don't really want you to remember all the facts and the details. They just want to show you that there's a lot of stuff you can do. So I have a couple of more demos. Let's see what we're doing on time. We have about 20 minutes. Good. I have a couple of more demos. It's actually just me showing you code. Just to show you something that is a little bit more production worthy than Hello World. Here's one that I really like. I did this with a customer and their response from the customer was that after we'd done this together, we built this thing together, they wanted to copy files. Classic, they wanted to have, we're going to upload our product releases to a storage account, but we also want to copy that to have different mirror sites downloaded, like one in Asia, one in the US, one in Europe. And we need to make sure we copy the files to all those locations. I said, hey, that's a web job. Really easy to do, actually, with a web job. Just mirror files, incoming blob files, copy them to another location in our implementation. After we were done, they were like, if it gets any simpler than this, we'll have to think the code and have it execute in our head or something, because this is just too easy. I would agree. I have a method here called copy release, which will take a message off a queue and write a response message once the method is finished. And for those of you who are paying attention, you can see that I'm also using the async process programming model here to use non-blocking operations, which is kind of handy as well. So you can do that, and you can even use a cancellation token there if you want to. So what I'm doing is I'm getting a reference to the blob I want to copy from. I'm getting a reference to the blob I want to copy to, making sure that the first blob actually exists. And then I create a shared access signature for those of you who know what that is. It's something I can append to my URL to make it, in this case, read-only. And now for the fun part. When I'm copying here, I'm using an Azure Storage feature, which is a long name. Start copy from blob async. This is a command I'm sending to storage, giving it a URL saying, this URL, copy the file you find there into yourself. That's what I'm doing. So that means that no, I'm not copying the, I'm not streaming the blob into memory on my box and then streaming it back out into another storage account. I'm telling storage to copy from A to B. And while that's happening, I'm going to wait, I'm going to hang around here and do like a little delay and wait and go back and check to the server, are you done yet? Are you done yet? Are you done yet? Until it's done. When the copy status is success, I've actually copied the blob from A to B, and then I'm done, I'm going to write out a message saying, yes, I've copied this blob. This is almost production-worthy code, and it'll solve the problem of copying files with using very, very few resources. Just like a few lines of code, it's easy once you get to know these web job things. Now, the other example that I have is also quite interesting. It's the classic, classic example of you having a web application that receives maybe an upload file or some data that needs to be processed, and then the code that receives that on your web server takes a few seconds or 10 seconds or something to process this. Like when you hit the submit button, the confirm button when you're booking holiday tickets or something, it's going to process for a while while you wait, right? It's going to think about this and make sure that everything went through and then come back to you and say, ah, it's done. So while that's happening, you're looking at the spinning donut of death wondering how long this is going to take. Well, that feature, that thing is much better processed in the background, and after the processing is done, send an email or a notification or have the web application go back and check, is it actually done yet? That's much better to do. So in this example, I can't run this actually because I don't have the database for it, but I can show you the code that does this, and you'll understand, of course, how this is done. Send emails. So this web app that I have here is part of a demo workshop that I had. It has some simple views that will take some input when you order cakes online to have them delivered, and your order coming in will have to connect to some sort of repository and get some data, and when you post back, it's going to take your order and your quantity and stuff like that and put something on some kind of ordering service and submit that order, and then after that's done, the ordering service has submitted the data. You're also going to send out an email to the person who placed the order saying, thank you for your order, blah, blah, blah. All right? So this takes a few seconds to process if you run this code, and while you're doing that, the user is waiting, and that's not a really good user experience, and also it consumes resources on your web application, so when you have like a million people ordering cakes from your business, you need some really powerful machines. So instead of doing that, I'll replace the ordering bit here. I'll just take this code, replace that with this code, which is my implementation of an Azure ordering service. It's going to take the same information and plop it on a queue and return to the waiting customer saying, thank you for your order on the web browser, and then once the order is processed on the background by the web job, the email will be sent to the waiting customer saying, yes, we have your order, your confirmation number, blah, blah, blah. So that's a lot better to do it that way. So in this case, of course, then I will be using this ordering service to do pretty much the same thing as I did before, except that instead of submitting it to the database, blocking the application, et cetera, I'm going to just simply put it on a queue again. So I got the queue message here, putting that on the queue, adding the message to the queue. And of course, on the back end, the web job is going to do roughly what the code did before inside of my business logic, right? It's going to take the message and process it and send the email. That's it. Now, if I do it this way, your users will have a much better experience, your web application will scale, and everything will just be really beautiful, and pretty soon you guys will be downstairs drinking beer instead of coding. All right. Cool. So basically, that is the session, but there are a lot of more features that are interesting to look at, and the rest of this session is basically like a feature bonanza thing where I go through different features and we can talk about those and you'll be enlightened and everything will be beautiful. Does anyone have, yes, questions, exactly. Regarding the signature of the... Regarding the signature of the function, well, it needs to be a public static method, and it needs to have some parameter that has those triggers. It needs to trigger on something, but I did continuous web jobs in my example. I did continuous ones. I have web job methods that you can flag them saying, this is a web job method, and that might be run by you on demand instead of the triggering method that I did with the attributes. You can have things that run on a schedule, things that run on demand. Yes, the parameters for the order in this case, this is packed inside of JSON, the parameters of the... No, it's not packed into it. The question is, are the parameters packed into the JSON or anything like that? No, it's not, because what web jobs will do, it will inspect the code that it has in its bin folder, and it will find the methods that have any web job attributes on them, and it will do that using reflection. So it will just figure out what stuff there is, and you saw when I had, for instance, I had a message that was a string, and then in another case I had a message which was of type message, and when it sees, well, message of type message, that must mean that the incoming message will be a JSON serialized object with these parameters, otherwise I can't serialize into that. And if that breaks, then you'll get an error saying, well, the message I received wasn't a JSON serialized message object, it was something else, I couldn't deserialize. So you'll get the sort of full support in these parameters, and it'll tell you when you do something wrong, because you will see that there were invocations that were not processed properly. So it'll help you all the way. Again, this is built to be simple, right? Simple, simple, simple. That is what it is. Any more questions? Yes. Is a queue the only way to trigger a continuous web job? Is a queue the only way to trigger a continuous web job? There are three ways of doing it. You can trigger a continuous web job on a queue, an Azure Storage queue, on a Service Bus queue, or on a blob. The blob one is a little bit more dicey. It means that you upload a blob to a blob storage account, and at some point the web job using the Azure Blob Storage statistics will see, is there a new file which is added later to this container than when I checked last. So it'll keep statistics on this, and it will execute your method based on incoming blobs. But I've had a problem with a customer scenario for this exact thing. They needed to make sure that the triggering was happening fast. And with the specific blob trigger, it can take a little time. It depends on how much traffic there is on your storage account and stuff like that. With the queues, you could set the number of seconds, how often do you pull? The default is to fall back and pull as few times as once every 30 seconds if there are no messages on the queue, but if there are messages, it's going to continuously just process them. But the blobs will take a little more time. That's a great question. Did they answer your question? Yeah, it was blobs. Yeah, blobs, it works. How to target it to allow the......time schedule? Yeah. How long can you go ahead and do it? What's the question? Yeah, so the question is, if I use a scheduled trigger on intervals called this web job method, how fast can I put that schedule? And I believe you can do something along the lines of once every second or something, but you'd have to pay for that scheduler. This is the Azure scheduler you're running at that point. You're running the scheduler which is in Azure. That's the thing which is going to be configured to call into your method on a given or called your web job and say, hey, dude, wake up, call this method, do it. And it's going to do that on the schedule that you set. So it's based on that feature. Okay? Still, it's a very valid way of doing it. Like, have the scheduler call frequently to your web job method and have your web job then do something. It doesn't even have to have any parameters at that point. Really only have to have an attribute saying, I'm a web job. Good question. All right? Yes, another question. What's the maximum... What's the maximum length of time a web job can last? Yes, what's the maximum length of time a web job can last? That is a great question. And it's not as long as I would like because I've had some web job methods go and say, never finished. And it gets sort of this yellow status. You can have red, failed, green, okay, and yellow, I didn't complete. And the reason why that happened to me was that I was starving my machine because I was running it really hot and it couldn't process everything so it stopped processing things after a while. So that happened to me and I was trying to do too much inside of a web job basically but at least I got information about it. So it'll shut it down. But the web job itself can run for a long time because Azure Storage, also the service bus queues, have the feature that you're able to go back to the message and update the lease time you have on the message. So for those of you who know how Azure Storage queues work, when you dequeue a message, it's hidden on the queue for you for a period of time. And if you don't return and say, delete message, which means I'm done with the message now, the message will reappear on the queue and you will get that dequeue count increase. And after 10 tries, I got poison messages, right? So that was built into the feature of the web jobs. But it's leaning on a feature of Azure Storage and you can go back to the queue and say I'd like to update the message and you can actually change the content of the message funny enough but you can also say I'd like to have the lease extended for another period of time and you can go back and do that however many times you like. So you can, in theory, keep a message forever but forever in Azure Storage queues is seven days. So a long time is the answer. But it's a valid question. It's one of those like, what is this? Yes, these are great questions. It means that you guys are paying attention. I love that. Any more questions? What are the maximum size of the message in the queue? The maximum size of the message in the queue is not a web job question. It's an Azure Storage queue question but I can answer that, absolutely. It's 64K and if you need bigger ones, the normal process is to put the message body in a blob in Azure Storage and put a reference to the blob in the queue. So that works but then you have to do two things but it works. Yeah, great question. So sometimes you have messages that are larger than 64K. It's actually 256 in service bus queues. So you can use those instead if you have messages that are not larger than 256. Great. I see that you guys are thinking about all the things you're going to build with this when you come home and that's basically the point of this talk is really to give you a tool that you didn't know about and then when you go back home it's like, oh, holy crap, we're going to throw some stuff out now. And this engine thing that we were having, we're maintaining, no. This background thread thing we're running, no, no, no, no, no. Don't do it that way, that's the wrong way of doing it. All right, we only have a few more minutes. I think most of this stuff I have talked about is sync-weight binding. Yeah, you saw me parameterizing bindings using parameters from the, using your names and stuff like that from the messages and things like that. It's really, really handy. You can get the DQ count if you want to do something with that inside of your code. You can get the DQ count saying, hey, have I processed this message before? Because sometimes that's something you need to know inside of your code. And streams are really cool. If you're reading off a blob trigger, you can get the input as a stream. You can get it as a text reader. You can even get it as a string. So all of these bindings just work out of the box depending on what you want to do. If it's an image file, getting a text reader or a string doesn't make any sense. You might want to get the stream instead. But, you know, you can even actually go and do a stream binder to bind to other types of objects. In this case, a web image is my parameter. But the blob, the job host doesn't know how to read a web image. So you can create your iCloud stream binder of web image and explain to web jobs how to change your stream into a web image and back. So it's actually quite handy and powerful. So your methods can have a really smart signature and you'll just have this conversion thing running in the background. So no automatic trigger means only manual triggering. Right. So basically that and then the service bus, I've told you that. I think I've told you all the features that I wanted to talk about. There are videos in my blog post that you can check if there are any specific ones you want to learn about and I have videos showing that. So are there any more questions at this point? Before I summarize. I think we may have emptied out all the questions. That's great. Thank you. So this is not a big cloud service. This is simple stuff. It's easier to use than and using storage direct because I just have to have an attribute and then I can use a string instead of doing add message or get message and delete message. And how do I handle these and all that stuff? You don't have to know that inside of your your your logic that runs the web job and all that monitoring and diagnostic stuff that you get included in the package. And again, like I don't want to sound like a cheap car salesman or anything, but you run this at no additional cost because it's it's you're still. If you are running your web apps, of course, I mean, if you're not running web apps, then it's going to cost you a web app. But other than that, but wait, there's more. Now, I can't actually run the debugging demo because I'm using Visual Studio RC and Windows 10 and stuff like that. I tried, but it's not working. But I can show you how it would be working if if I didn't run this RC version and stuff like that. You know about the service server explorer, you can go and look at your your Azure stuff. And if I go down to my web apps, we have two web apps running now the Hello World web job would be the one that I would connect to if I could. But unfortunately, me installing my my machine was not a smart thing to do. It goes out to Azure and checks do I have a web job running in this application I do indeed. And then I can right click on this. Am I running it? Oh, it's not. Oh, it's not. It's not running. It detected that. Yes, it's there, but it stopped running. So I might have to start it up first. But once I've started it up, I can attach. Well, in theory, I can attach the debugger to a running web job, which is running out in Azure. And I can debug from Visual Studio right into my code. And I think that's pretty sweet. I can't demo it today, unfortunately, but you'll have to trust me that it works. So that was, I guess that that's the summary. And whoops, let's get rid of the magnifier. Go away. I said go away. Ah, that was the presentation, ladies and gentlemen, I appreciate you taking the time. And again, this is my passion. I love doing this. I love talking about it, but I love doing it. And if there are any additional questions, do not hesitate to send me an email. That's not a problem at all. And you know, you should go and drink beer now. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you.
running any workloads in Azure at this time? specifics about it. If you have your very simple days. I'll go and add Microsoft Azure Web Jobs to script or a BAT file or whatever command line them in code as well if you like. But it's configuration file for your Web job. That's what something somebody else built. Let's build it that you want to run on a background thread. service has submitted the data. You're also going code, which is my implementation of an Azure that are interesting to look at, and the rest of you all the way. Again, this is built to be statistics on this, and it will execute your built into the feature of the web jobs. But it's the message and you can actually change the message in the queue? The maximum size of the handy and powerful. So your methods can have a that monitoring and diagnostic stuff that you get