BrandGhost

Quartz.NET + SQLite Live Coding in C# - Principal Software Engineering Manager at Microsoft

July 17, 2024
• 660 views
Y'all want more live coding 🤨 Join me on Tuesday morning at 7:00 am PST for some C# fun! As always, AMA style so you can ask away as I'm coding. What do you want to see live-streamed?
View Transcript
let me make sure all the things are working before I get too far this one sorry I'm just making sure this stream set up in uh in different places here so uh that is the right one for today awesome okay I think we're good to go um this is going to be live coding in C you're going to get to see me fumble around which is always exciting um uh makes me nervous obviously but that's part of it so today I want to look at using quartz.net and quartz.net is a like a job scheduling Library we used it a little bit before um but I if I'm being totally transparent like not not super confident so I want to spend some time what better way what better way to to go learn something than to go do it live and uh embarrass yourself right so I'm going to do that um I actually have I just have it pulled up on my screen here I have uh one of my newsletter issues from like it's the 29th issue so that's almost half a year ago I wrote a little bit about using uh quartz.net uh but I I think the the thing that I really want to explore today about quarts . net is uh is like this persistent store so even when I used it before it was kind of just to to trigger things so you can set things up hey Vlad on LinkedIn um you can set a quartz.net up to basically be a a periodic trigger and I think that's all I was using it for and the context was that we were building a Blazer application and I needed something that could wake up periodically and and be a trigger so um that was sort of the extent that I used it and kind of struggled through there's some weird dependency injection things like the job itself couldn't have dependencies passed in you'd have to use like you have to pass them by par like this weird parameter collection thing so anyway I think I had that working a little bit um but the persistent store part was totally just neglected and I wanted to spend time on that today so um I do have a use case that I want to explore um in another project so I'm not going to pull that up we're going to start from scratch but I have a use case in another project where I want to have uh this idea of persistence for these jobs that I want to run so I figured okay like let's instead of trying to integrate it because I'd have to go refactor a lot of code instead of trying to go refactor all of it just to be in a position where I'm like okay how do I fit this in I'd much rather go okay how does this work let me go explore how this works and then I can go make a decision afterwards to go uh refactor the other code in the other project so that's the plan um I'll probably switch over to visual studio in just a second I want to have a little disclaimer though I was streaming last night on on Sunday I had to get another uh had to get another covid booster shot and honestly I thought the first 24 hours like I I know the first sleep is usually like I have a pretty rough uh pretty rough sleep like very feverish and I thought that last night I would be totally uh in the clear but I had the same issue last night so I really haven't slept well um and right now my fever's gone but I don't know if I start to stream if uh if I'm a little bit and if I'll have to drop because I'm uh feeling feverish so I just wanted to be transparent that if I have to end the stream a little bit early um it's entirely possible if my if my Advil and stuff is wearing off so let me um I'm just making a visual studio project you don't have to watch me do this part so I'm just going to keep blabbing as I do it but uh I want to make a visual studio project and I'm going to call it uh courtz net example um and I think I am going to make this an asp.net core just so that it's that's what it's going to be dropped into in the other place and I think if I'm not mistaken that there's I'm going to have to pull up the documentation but I think there's some uh some hookup that they have in courts.net for like specifically for uh asp.net core so we'll get that going thanks Jack I appreciate that it's funny I remember I woke up this morning and I think I set my alarm for 6 right in this stream is at 7 A.M my time so set my alarm for 6 and I just remember like I woke up at 6 and I must have just like snoozed my alarm because I woke up again at 6:30 and I was like uh oh like you got to get out of bed because you're going to be on a stream soon um and then I was like oh do I do it like you didn't sleep well and I figured okay like you feel okay right now like try it um and we'll see so just sucks I don't like uh I've had covid once before and it was pretty bad uh but the entire time like as long as I stayed on top of taking Advil my fever was was totally fine it was the only symptom I had just really bad fever but anytime I get a booster it's like it's just like having Co so it's it's pretty awful okay um I do have Visual Studio pulled up let me get my stuff switched over here so you can see my screen it should be this button right here so I do have an asp onic core web app here um like I said I'm going to pull the documentation up though so here's my blog where I had basically some of the stuff for being able to go um I'll zoom in a little bit what we were doing in the blog post was that um this was to go basically uh fetch social media statistics from the internet I don't think I never finished this project it might be fun to go back and and complete it but the idea was that we had plugins and for different social media providers um we needed a job that would be responsible for periodically polling fetching your your social media statistics like how many followers you have on Twitter that kind of thing so if we're looking at this code here the part that doesn't really matter for us is like this the 4 each Loop that's just you know that's just going to go grab the plugins but we don't we don't have those um and then I think this part in particular was just about scheduling jobs right so if we have a quick look at what's going on here hey Enzo on Twitter um we do have a look here I think this is the part where I was saying when you're doing dependenc well there is no dependency injection for the jobs themselves so you have to use this kind of parameter passing thing going on here so you set the job data and then you have to use this dictionary to go read them back out so kind of weird but that's how it works I guess hello on Kick from Turkey good to see you and then this trigger Builder this is going to be interesting because I don't know all the options um but we can figure out what we want for a trigger maybe I'll do like uh just to see it working we could do a schedule but or like a a what do they call it not like a fire and forget kind of thing but the the thing that I'm really interested in is I want to be able to have this go to persistent storage and I I didn't do any of that in my my blog article so um ps.net and then I think it's Ado Job Store example so they have a ram job store but the Ado one I think is what we want to play with here so they let me zoom in again sorry so to use Ado Job Store you must first create a set of database tables for quarts to use you can find table creation Scripts okay so interesting they come with the scripts but and they prefix all of them so they stand out so I'm going to use sqlite um why is sqlite why not something else um because I don't want to go set up a whole other database I I have um for my actual project where I do want to incorporate this I already have a mySQL database so I can make it work for SQL light I'll make it work for SQL light and then I'll Port it over after um but so this is interesting they have I'm going to have to see where the scripts actually are like are they just in the um what's it called sorry in the in the GitHub we'll have to see because if it's a nougat package I don't know if the nougat package like are they a resource embedded in the nougat package or something um it's kind of weird or I thought I saw saw someone I thought I I did a quick search for this last night I thought someone had like a nougat package that was basically uh like a provider almost for courts.net and they had uh the different databases so maybe there is like a another we'll check in a second but maybe there's a a nougat package that someone's put these scripts into code and we can pull them so but let's see so one more thing to not is these all the tables start with that so quartz trigger sure quartz job detail this prefix can be anything you'd like as long as you inform what the prefix is okay oh interesting using different prefixes may be useful for creating multiple sets of uh tables for multiple scheduler instances within the same database so I don't certainly for today we don't need that but I don't think in my own personal project I have uh that going on hello Emporium guy from twitch good to see you So currently the only [Music] option okay this is different from I I didn't realize this I I saw this the other day when I was going to look up quartz again but I didn't realize quartz is a Java thing big surprise right um so very cool I didn't realize that last piece of the puzzle setting up data source from which Ado Job Store can get connections to your database so this is something I remember reading and I was like I'm not a huge fan of having you do this but if we see this code like this isn't C code and I know it's not C code because of specifically this like that's not C syntax so I think we have to go set up a weird configuration file and like I'm not just I'm kind of against having to do that I want to just write that in code and not mess around with a config file so I'm I'm a little nervous that when we go to start doing this I'm going to have to be messing around with I don't like config files because I have to mess around with them so instead of just having something work in code and having the compiler tell me what's up it's like nope like you have the wrong syntax and like or you you go to run it and you don't realize it's not working because there was no validation on the syntax so I'm not looking forward to that part but we'll see so next selected I driver delegate okay this feels like it's like sort of complex just for for getting this to work but I wonder if it's a lot more simple when we go to do it courts onet will issue a warning if you if you're using the default STD Ado delegate it has poor performance when you have a lot of triggers so okay warns you but see like this is more like this just weird config file stuff so like I said I'm not looking forward to that part connection string okay um configuration reference 519 errors still Haun me so see this configuration reference like what do they have an example this is the thing like I need an example to go work from um I'm just kind of poking around to go see if this is the big bit yeah unfortunately right configuration this is the big bit very configurable Library I mean that's good but I think this is what I want like I want I want code to do it so maybe we are okay maybe this is the reference I want like I don't want SQL server but oh this is might be generic SQL so that's okay um so maybe that is fine maybe we can do it all in code and here's configuration files okay um and like this is what I don't like right like there's a whole separate config file no no thank you um it's just it's one more thing I don't want to mess around with so I'm hoping that we can do everything we need but it looks like not like job initialization plug-in handles or XML reading without it defaults required like and then it's telling you which files to load okay we'll see we'll we'll mess around with some code it's I don't read documentation a lot because I find that I'm like all the stuff I've already read it's already left my head I'd rather kind of dive into code and mess around um but I wanted to double check to see I'm hoping that we can like mostly use this kind of syntax here to set things up and the fact fact that I see use persistent store makes me think that we can hopefully get away with uh with doing this in code so let's let's jump back to visual studio pull that out of the way I haven't had caffeine yet this morning either that's unlike me um side note in my caffeine reduction journey I am down from like 12 to 1,500 Mill G that's yes that's up to a gram and a half of caffeine a day down to 400 Mig which is it's a big difference so we're happy about that okay so minimal API here in fact I don't really care about this I want to start trimming up some of this code just so I don't have distractions on my screen so well call it [Music] hello okay really simple application we'll zoom in there and now let's go check by the way I I'm realizing now usually like when I'm making YouTube videos I go to 1080P and all of the other text becomes a lot bigger um right now I'm using one quarter of my monitor to be able to show you what's on my screen so if some of the text is super small I apologize but hopefully it's the stuff that doesn't really matter for you to go looking at so quartz.net so here we go they have one there's a package specifically for dependency injection that's cool I'm just quickly having a scan nice Mass trans it how does this that's interesting how does this integrate with mass transit because and sorry that that's catching me off guard I I know that in my other project I'm going to get to the point where I need mass transit for being able to cue stuff up so very interesting I wonder if we can leverage mass transit to go like if we wanted to send add something to a queue that basically it's just back by Quartz which I mean that's exactly what I'm going to want but I don't think we're going to get to that today CU I want to focus on the on the persistent store part so let's get this installed I think I'm going to need to grab SQL light man that's a lot 244 million downloads I'm just double checking I want to make sure I grab one that has the unmanaged stuff as well this package does not provide an API which is friendly to app developers why what's going on here is this the one I want Microsoft data sqlite core this package does not include the copy of it so that's not what I want why is this hard to find I prob do I need to grab the PCL one and then so this one says does contain it it's why this why are there there's like no downloads of this one I mean sorry don't get me wrong it's like five almost 5 million downloads but the others have like over a 100 million but I think this one might be the one this batteries included bundle brings sqlite raw core and the necessary stuff but I've never so I've never used this one I've always used whatever like system data sqlite Microsoft data SQL light and what's this one core so I think okay I think this is the one I want if you if we look at the dependencies and and sorry the text is probably small and my stupid face is blocking it so you can't even see it one sec I just realized no not that okay let me move this over sorry I know the text is small but this is a bit of a pain in the butt when we're picking a SQL light provider but I just wanted to show you that I'm trying to find one that has the unmanaged dlls in it because sqlite is not written in C it's it has I think C++ DLS so if we look at the dependencies here we can see that the dependencies it has sqlite PCL raw bundle it literally has um this one here it has this one inside of it right and then it also has Microsoft data SQL like core so it's funny the first one I went to go pick was Microsoft data sqlite core that's the one I wanted to grab but but then it's not going to have the this the unmanaged Ells in it so this is the one I want because it has both so I think we found it let's go install that and again just to clarify it's going to give us the the managed API that we want but also it comes with the uh the sqlite dlls for uh the actual driver so I think we're good in this point let me go pull this back over there cool okay okay now we just go make it work right um I'm pulling this back up so you can see but what I want to do is basically take that code I don't think I want to grab the XML scheduling configuration no thanks so a lot of comments holy holy comments um okay so create but what are the properties do they say what properties were you you can have B oh I wonder interesting so that's if I'm reading this properly there's like this fluent API which is nice but then I think that I can probably have basically a key value pair setup for any of the properties that I want to work with so that would be very cool uh so I don't need to go mess around okay get rid of VAR because I know VAR bothers people how about folks in the chat that have access to chat if you're not watching the recorded version of this if you're a c developer do you like using VAR or do you stay away from using VAR curious to hear your thoughts I get all sorts of different answers on this usually when I ask so uh use persistent story this is the one I am curious about so the connection string that we want uh how does this work data source I think that's all we have to do for sqlite I love using VAR nice okay I don't want to bias anyone yet so I'm very curious to see what others have to say maybe because I'm lazy see run away from VAR looks like JavaScript everyone's everyone's got different opinions about VAR it's uh it's always interesting to see so where was this code schedu oh we have to call Schuler start but I haven't I haven't set it up to specifically use SQL light though like that didn't come up anywhere job stores let's go back to here okay [Music] um sqlite only shows up two times on this page and it's right here so it's supported so I think this is where I have to do if I go back up here these properties can I do this directly okay one sec that's co-pilot giving me a hint um right can I drop these types of things in whoa whoa whoa this is someone's co-pilot read someone's configuration look at that um data source provider see this is what I want here um but I I guess I can use the fluent API but see um there's no line number for it sorry but it says data source default provider SQL Server so I'm very curious why doesn't this work okay whatever on that um what's going on why did that like comment out this line why is it what's going on what sorry I don't know why it's uh it's freaking out I'm pretty sure I copied this code directly build scheduler needs to be at the end that's why okay it's weird it's uh scheduler start but it's not a it's not marked as a sync so I didn't even know that I had to await it but did they have an await on theirs oh they do okay good but okay uh data no ah look at that use sqlite so it looks like they have it built bu in so did I not not even need to add a package for sqlite maybe not well what happens if we go run this probably nothing exciting but that took far longer than it should have ah yes okay great that's what I was hoping to see um oh boy so I have to find system data SQL light and it's I grabbed whatever package I picked is not the okay one so that's a pain in the butt let's go back to here maybe it's just this one it's funny I'm I'm literally just live streaming this being like yeah must be this one like not even really paying attention yeah this is generally how I develop stuff and probably most of the time why I get caught up in things where I'm like why doesn't this work um that's because I'm not paying a lot of attention so I don't want Microsoft data sqlite I want system data sqlite now let's see if that works and it might complain again it might be a version thing at this point oh so we got further nice you must define object cizer using configuration key oh that was weird it was the tech was so big now it's tiny sorry if you can't read this I can't read this um out of the box supportive values are Json and binary Json doesn't suffer from versioning as much as binary serialization but you cannot use it if you already so why can't yeah okay that's what this line was why can't I use this oops it's like it's they they offer it but it's like oh I didn't read that before there you go right it's right here and again apparently I'm demonstrating to all of you that my uh my skill set doesn't include actually reading but there is a whole nougat package for it so oh wild only 93 down loads really that's weird I have like personal Nate packages that have more downloads than that and I thought those are just being counted because my like build systems were pulling them down and using them 93 is not a lot at all okay does this work let's see and when I say work by the way I'm just like I want it to Not Crash um seate cannot be used as clustered mode okay I don't care um let me turn this off oh my goodness I'm really hoping this is one of those things that once it's configured and working I never have to think about it again but this is like this is like pretty infuriating I get that it's a configurable library but oh man okay database schem team Val validation failed make sure you've created the database tables aha so I was hoping that we would get it to create them for us but apparently not there's no like create schema so we do want I want to like explicitly say this cuz I think that that's important um that it should do that Wonder sorry I see this one up here I know it's unrelated I'm just very curious what this is ah the time span in which a trigger must have interesting that's the default anyway I was just really curious what it meant by misfire like when does that actually happen what does it mean okay so we got go get those um those scripts and I'm going to read this time uh where where were those scripts database DB tables directory database I guess it was this one table sqlite look at that nice wow cool okay um let's get the raw version of that I don't know what cheap viewers is about but that sounds like it's probably spam uh I probably wouldn't click that yeah anyway sorry I'm I'm blocking that person from chat I don't have moderators and that seemed like a sketchy link so I apologize if I just totally blew you out of the chat but seemed kind of weird I'd rather be uh more aggressive and kick people out um okay so what did I want to do I have a sqlite script what I want to do is man do I want to do this sorry I'm trying to make a decision here I I was about to make it so that when I start the application it goes and runs this but like uh that's probably not what I want cuz every we're going to lose the persistence every time we start it up it's going to go uh blow it away so uh um I don't even have a SQL light viewer do I no I don't what's a good way to run this let's see oh I've never even noticed that they have a create file method I was like what's going on here um connection string and that just going to be ah yes I never talked about I never finished my thoughts on VAR I use VAR all the time I have never found that VAR makes it harder for me to read and understand code at all um I get that if you're like it makes it hard for me to read and understand code then yeah like don't don't use it like I get it um but I don't have that issue I've never I never have and then people go well I can't tell what the type is and I'm like or one of the big arguments I hear is oh well yeah in Visual Studio you can tell but if I have to look at it in like a a poll request or in a code review like I can't tell what the type is and I'm like well I don't I don't understand why that matters to you like you can see how it's being used or not so like why does knowing the type matter at that point I don't know I've I just find it kind of fascinating it's never been an issue for me however what I've started doing is you'll notice uh like this now that we can have this kind of taxs I like doing this I get rid of VAR Al together because I can put the type on the left here and just say new instead of having it be redundant and say new sqlite connection equals sorry instead of sqlite connection equals new sqlite connection like you already know what the type is why are we repeating it so I like this but you'll notice when I call stuff like up here it's far I don't I don't care it doesn't really bother me so anyway that's my that's my snance I'm sticking to it um okay this is going to be uh what we call disgusting there we go there's a bunch of sqlite why doesn't it like it oh we'll hide that nice today I'm migrating a reactjs project over to typescript cool well lurk away thanks for joining um this is me just kind of putting around trying to figure stuff out so thanks for checking it out so what I'm GNA I'm going to comment this code out after we're going to run it once and see if it is Happy um because once we have it with the data source we don't have to go rerun this so let's uh go find out should put a using oh nice so it worked and what I was saying earlier was by it worked I mean it doesn't crash when it starts up so that's cool okay oh not what I wanted to see let's uh use a different commenting type here then I can collapse that gross okay so we have we have quartz so look at your brain go yeah it's it's doing something it's doing something that's for sure so let's go see if we can make a a job actually you know what maybe we can check out what they have going on here oh they actually had more stuff there tutorials jobs and triggers I'm not sure if other folks that are on stream have used uh CS before um I found some of the stuff a little bit confusing the first time I went through it like if we again there's answers to this stuff and we can figure them out but when I read this code here trigger Builder create so I I like the fluent syntax and everything but with identity group I'm like there's already two names there that I'm like I don't really know for job job name job group I have four names that I have to go Define and like that makes me like nervous they talk here about why jobs and triggers like I think the idea of a trigger and a job makes sense to decouple them I I like that logic but this whole thing of like um I don't know like I don't know what the right values need to be for this kind of stuff like what is a group that's I think the part that's throwing me off it's like okay maybe this this is again me not reading things so the keys of jobs and triggers allow them to be Place into groups which can be useful for organizing your jobs and triggers into categories okay so it's just uh it truly just is as you might expect a group so if we wanted to say this is like how do you name a trigger like that seems kind of like this part right here just seems weird that I have to go name the trigger but if we wanted to call it test jobs this is a simple schedule I don't know if I want to schedule is there anything else with calendar interval so you can see this one's like repeat count with interval and maybe I do want a oops it's entirely possible that I might want a simple schedule I don't know yet I just want to like basically cue something and fire it off at some point in time so that might be what I want oh start at okay I think that's actually what I want I'm going to start it 10 seconds but here's the the weird thing like what where do I def find the job I don't know what this does um like where's the body of the job let me go back to my my blog article here so job detail let me okay let me this stuff soer this is the job trigger I'm going to get rid of this code job Builder okay uh maybe what we can do is something like this oops so what I'm thinking is I'm going to I think I have to go make a job class which is fine um so we'll do sealed class our test job I job detail I guess it's a job details what we want and what goes into this I don't I really don't think that's what we want that seems uh suspicious that seems like a lot of code to go do that ah just I job and then I okay so I think what I needed to do this getting a little confused I think here this is making a job detail out of a job so and I if I'm not mistaken I think that these don't work with dependency injection and stuff like that I think they're they end up getting serialized I think or maybe not maybe what they're doing is they're serializing the type information and that way they can go use reflection to go look them up or something but I think this information this job detail stuff gets uh this part gets written to the database as my guess with identity job key so I think I think if I need to do that this job key is Hello World well here's what I don't know like is it is the job key both I don't know like this is what I I I don't like this stuff it's making me like I feel like I'm going to use the wrong thing here set the identity for the job which should be fired by the produced trigger job key will be produced with a type name and group okay but how do they get combined like is it a dash I think I had it in my blog post but let's see yeah Dash trigger but that's to name the trigger so no so I have no idea if that's what it wants kind of annoying CU like what I'm nervous about is I'm going to go set this up and then i' I've somehow configured the thing to be the wrong name and then it doesn't go fire so but this one here I didn't even have for a job on it right it doesn't it doesn't have that at all and maybe I don't need that either if you go to schedule the job like this this is what I had in my previous code that was working and I wonder if that makes it okay but then I don't I lose the job group it's annoying I don't know how do they schedule stuff they don't they just build these very interesting I sorry if I'm maybe I'm not uh doing as good of a job with my my stream of Consciousness here but the part that's bothering me is this line I had from my like a Blog article I wrote where we would schedule the job this way okay so they don't even have that in theirs they're just making a job trigger and they say for job like this like they have this up here but this is their example basically they don't they don't call a scheduler to go schedule it so I don't know did I I must have accidentally deleted some code yeah I accidentally deleted the start at oops okay let me put that back so if we don't have the scheduled job it makes me wonder like do I need to have there's an overload oh man [Laughter] okay okay Nick uh and I bet you up here there's an overload I can use a job key I bet you and there is so all of this time I'm getting frustrated with this it's like it's not actually um it's not their fault it's just me being dumb which is okay at least I'm doing it live in front of all of you so let me just kind of reiterate what was throwing me off and and why this is way better now previously when we were looking at the code on line 227 for job this was taking in two parameters it was taking in a name and a group and then down here we were just taking in this job key and the job key was just defined with a name so I'm going how the heck can we have that like don't we need a group like by definition don't we also need a group but it turns out you can change the job key to be defined with both the name in the group which is good and then we can actually use the job key in both spots so now if we think about their code right their code did not call theuer at all and that might be totally fine maybe this before was an explicit way to combine those things and we don't have to do it because if we do this and we build these things maybe it will just go work so now I think uh context can we key in how do we get stuff out apparently not that way get um this is the weird part that I was saying there's no dependency injection right so we'll do that and then console right line message oh sure we don't have any asynchronous code so it doesn't really matter for us but I'm going to put a break point here let's change uh this to be 5 seconds so I'm really hoping that again if I just do this I I'm I I feel like it's not going to work I feel like there's no way that without calling this line it's going to work but we'll find out so if we wait 5 Seconds we should hit this break point we might as well try it and see okay one 2 3 4 nope but if we go put this in now one two three oh it works very cool um okay that's interesting now here's the funny part I haven't I haven't verified any of the persistent storage stuff and I realize I don't have a sqlite viewer on my computer um and maybe couple options maybe I go get one uh sqlite expert is that what it's called this one at the digital forensics company I used to work at we use this one a lot sqlite expert and it's funny because it's called sqlite expert but there's like a personal in professional version which is funny just because the name I always thought was uh interesting like you're downloading sqlite expert but it's like SQL expert professional or personal right it's a trial this one's a freear I think the expert throws it off for me it's expert and personal so we'll get that um what I'm thinking about doing just to explain my thought process again is I'm going to set this trigger to be like whatever a couple minutes out and then we'll go check the sqlite tables um the other thing I was thinking of doing if if I wasn't going to go download that was to basically um go write sqlite code and just do a query but I don't want to then I have to go read what the table schemas are and I'd rather just poke around so let's do that no no start menu actually do want start menu I don't want yeah expert and professional is redundant thank you uh that's uh always what I thought oh and sorry Mr buttons I didn't realize I didn't see your question right before that uh what I'm working on is integrating quartz.net and SQL light oh man this window is very big and bright um and the context is that I have an application that I want to build in I want to build in job scheduling with persistence and I've used courts.net before but basically only to set up like kind of fire and forget or like scheduling jobs that fire like a craon interval but not um not something where I could uh persist it so my idea is that I instead of going to refactor that application and go build it all in I said let me go make sure I can understand how this works let me go see if I can make it happen and if so and I'm happy with it then I'll go refactor the application to bring in quartz.net so that's been the thought process open database I always feel weird like navigate not not that I have anything secret but weird navigating my file folder structure and and sharing my screen so okay job details fire triggers interesting if we go look at this oh man I'm so used to using my SQL workbench um is there no way to go oh data right there nice That's funny though I I cancelled the um or I stopped running the application sorry if the text is really small and I realized it might be cut off so let me move this over um I stopped asp.net core while the job was running so if we look at the state here it says executing still that's peculiar um let's go um I have it said to be 60 seconds let's go run it again it's running now what okay well that's that's not good that's definitely not good um why is that happening oh wait am I going crazy didn't I have it set to 60 ah I was reading up here sorry there we go come on Nick get it together I thought we were waiting 60 seconds so my apologies now we have 60 seconds let's go see what's up so it cleared the fired triggers job details scheduler State there's our list of triggers but interesting the fired triggers go away yeah application so fast as 60 seconds and five that's what I thought was happening but it turns out um in in typical Nick Fashion I'm just really bad at reading [Laughter] so so we're waiting the full 60 seconds here sorry folks I was just wanted to poke around and see what we have um in here right so the simple triggers table does have our test trigger so that's cool um this has all of them nothing's paused okay so the job is executing currently so that means if we go to job details do we see anything interesting I don't think that this one's going to show anything interesting but I think kind of as I was speculating there's the type name information written out fired triggers so this is while it's running job name is called hello world right it's executing we can see that so if I go continue the application now and we let this run now the fired triggers part is cleared again job details this is what I wanted to see right I wanted to kind of prove that uh when we cue up a job that we see it inside of the job details and I wanted to see the behavior between or I guess the relationship and behavior with these two tables so job details is empty now because we we don't have a scheduled job and really that means like now I understand the use case for this tables once we schedule a job it shows up in here I mean that's kind of what I expected but I I I just wanted to kind of see it happen and the fired triggers one is not a I think the way that I need to look at this is that it's not some type of History if that makes sense it's not a history because it's cleared again and I don't know if there is like a an overall history one it kind of seems like not like as I go through these tables like the whole database is empty now which is probably fine but again the whole context here is I need to think about the application I'm building let me go back to full camera so I can talk with my hands hey thanks Mr buttons um work I get it I got to work in an hour so I still got a little bit of time good to see you though thanks so the application that I'm building I will need some type of uh like history I guess I do need to make sure that I can uh like keep track of everything that's going on over time so I'm I'm saying this out loud because it means that I can't purely rely on on quartz for that quartz is going to be it looks like it's going to be very helpful for me getting the job set up it's going to be persisted that means I can kill off the app um and maybe that's a good experiment we can try next is I'm going to start it I'm going to start up courtz it's going to have a 60-second um time window I'm going to stop it once it's queued and then what I'm going to do is comment out the code that schedules another J job and we should see that it runs again so that's the next one uh oh so I did see a similar Project based on Ms Orleans for scheduling tasks I completely forgot about courts I actually haven't used uh Orleans at all I keep hearing the name and I just like never haven't spent time looking into it or anything like that it's it's unfortunate it's like uh there's there's so many things like even Aspire is something in our uh so the project I should just speak transparent the project I'm talking about is when I'm building this product called brand ghost so if you're interested in in kind of seeing that it's uh I'll just put a link in the chat oops I can't can't type so this is the thing that I'm building and I need scheduling put into it so um I'm going to be using quartz for it but yeah uh even for brand ghost like we're using a spire and it was like I've been hearing about Aspire I've been seeing uh uh David Fowler talk about it it's like it seems really cool but like I haven't haven't had a use for it and we kind of retroactively fit it into brand ghost and I can what's a weird what's a good way to put this I it's almost like I couldn't see the value until we started to do some stuff in Azure where um the the one guy on our team that's like really good with Aspire and and sort of uh like Cloud architecture and things like that he was he was pointing out to me like hey go run this uh you know command line stuff for for Aspire uh and it's like some Azure command line stuff and basically I wish I would have started this way but it was like running one command on the on the command line and from there it went and set up all the Azure resources and I was like that's the value I see it now I've been I've been trying to figure out like why it's valuable how it's helpful uh don't get me wrong um I'm sold when someone says you don't have to go use uh yaml files like yep sign me up I hate hate hate hate yo files um so it makes sense if I can do it on C that's cool but I didn't get to see how it all came together until I ran that stuff on the command line and then and then watched it printing out like hey I'm setting up these resources and I was like oh man like there it is so yeah Ms orans I've not looked at but there's all this cool stuff like I just wish I had more time for it because my day job I I mean I'm an engineering manager so I'm not coding at work but the my day job doesn't afford me the opportunity to see some of these things so I kind of have to you know do it in my spare time which is totally fine cuz I like like coding in my spare time but now that I'm building like so brand ghost is the thing I'm building outside of work and like if brand ghost doesn't need msor leans I'm never going to see msor leans it's the exact reason I haven't had a chance to go into Maui I haven't had to build anything you know that would leverage Maui so I just am not getting to use it but I really want to go try it out so um only got so much time in the day let's go back to the code here what I'm going to do is what I said where I'm going to this is set for 60 seconds so once we hit or once we see the the window pop up so you can see right I'm going to stop it comment this out and because that job is supposed to be persistent to the database we we see it's running again we should be able to see that it's in here right we have this job detail here simple trigger here and I know I said it for 60 seconds you got to bear with me for 60 seconds but I'm I'm thinking we should see this and it's really cool because it it proves that the job was persistent it's going to execute after this is what I need to be able to do uh again context here is for brand ghost brand ghost is helping to schedule social media content and the issue that I want to work around there we go perfect it works is if I need to schedule something and our server has to go down because we're deploying or something uh I don't want to lose that state so this is perfect um that's a exactly what I wanted to see that we can basically tear down the app right it doesn't have to run uh we can stop it and I guess that's why the misfire thing comes up too right so if we're thinking about the misfire part what could be very interesting is that let's take the ex I'm going to go back to here I like talking with my hands so um if we're thinking about the scenario I just gave so let's say I needed to go post something on social media and I'm using a job for that it's now written into the persisted store and it's scheduled to be 5 seconds from now 10 seconds a minute from now whatever if during that time I go hey like because I I'm not looking at all these schedule things like I'm developing more stuff and I need to go push a new buildup and it's deploying if that job was scheduled let's pick something right in the middle of everything I said it's 30 seconds from now and within that 30 second window I start a new deployment and it's going to take me just make up a number it's going to take five minutes to go deploy and sorry that's kind maybe kind of confusing because the whole deployment time might take five minutes from the start to finish but the time that the application is like torn down and stood back up if that window was overlapping the uh the period the misfire period right so we go from being 30 seconds out maybe by the time it's restored it's like it's 2 minutes after it was supposed to run I think that's when the misfire thing is going to is going to say like and I don't know where that's going to go is that like a table I'm not sharing my screen so sorry um I don't know where that gets logged or recorded and it's the the tool tip says and thus have the misfire instruction applied so maybe I'm just going to go I I haven't shared my screen yet I just want to search for misfire on their on their docks to see if it's there their their documentation doesn't have the word misfire anywhere oh come on did did we all see that it went from having no results and then it showed up as soon as I said that now I look like a now I look like a jerk okay so I'm it's funny the the stream's a little bit delayed on some of the other screens I have and I got to watch it so yeah it said there was no results but now now we do see it so that's good symbol trigger so I want to understand more about this these instructions are to find is constant on misfire a documentation for Syle trigger when building you specify the misfire instructions as part of the simple schedule with misfire handling instruction next with existing count what that seems very confusing um okay another important property of a trigger is its misfire instruction a misfire occurs a trigger misses its firing time okay so that makes sense or because there's no available threads sure by default they use a Smart policy instruction which has Dynamic Behavior based on the trigger typing configuration okay so when the scheduler starts it searches for any persistent triggers that have misfired right so it's looking for ones that are like hey like we're out of basically like their SLA for firing like we didn't get to go and then updates each of them based on their individually configured misfire instruction so when you start using cor at night you should make yourself familiar with the misfire instructions but I get it man but like tell me more okay let's see um I wonder if on here on the trigger was it on the trigger or on the job really okay um I thought yeah Tri it's on the trigger it has a misfire instruction so that's weird simple trigger missfire instructions okay interesting is anyone else looking at this documentation and feeling like it's leaving a lot to be desired oneoff job you can run the simplest job this way tip Mis fire mode smart what what does what does any of this that I just read mean I get it it could just be me here but like come on um how do we make a simple a simple trigger that's not what I searched yeah okay simple trigger how do I do it this feels gross oh trigger Builder creates simple trigger by default actually an ey trigger is returned sorry this is uh my head is cutting it off this is a kind of a gross API though so it apparently is a simple trigger behind the scenes but how do we do the misfire part it so I think you need with this so do you only have misfire stuff with a schedule because I don't have that ability with this so if we're looking at with a simple schedule right as an example oh sorry let me move this back there's not a lot of screen real estate okay so what I'm wondering is there we go there's all the Mis uh Miss fire stuff this tool tip is way off my screen and it's like hiding behind my camera so it's interesting these uh the tool tips on these are pretty bad or I guess it's like the HTML documentation XML documentation my goodness the um the tip here says if the trigger misfires use this uh simple trigger fire now instruction but like what tell me what it does tell me what it does I need to understand them I I think I under like I could guess at that one I'm assuming if it misfires and the scheduler starts back up it will just go refire it enormous fires that's interesting um the next with existing count next with remaining count like I don't know what these ones mean um but maybe they're more advanced I think for me I have to consider fire now or ignore misfires but also I don't have a schedule so I'm very curious what the misfire behaviors for something like this right we could try it how do I do this I got to let's do this okay with misfire threshold this is going to be it's going to be something um let's do we'll have five seconds and I have yeah this should work I'm going to set this to go fire off in 5 seconds but I'm going to stop the application and then as long as I wait 10 seconds before starting it again we should see what the misfire behavior is so let me start it come on you can do it okay so now I have to wait 10 seconds and what I'll do in the meantime is comment out this and what I'm hoping to see here is that I should explain this a little bit further right so I said I want to fire this thing off in 5 seconds and it's going to be longer than 5 Seconds by the time I go restart this app uh if we go check the database right we can see that there's a job in there let's refresh us to prove it all right so we have this job in here why is this trigger here that's weird oh acquired interesting okay so we have this job detail in here it's been far more than 10 seconds now so when we start the app is it just going to go fire because it's it's outside of that threshold or is it going to have some weird behavior let's find out so it fires right away which is interesting now if we check the the scheduled fire time sorry I'm kind of exploring this for the first time I was curious to see if it would tell us like when it was supposed to be run versus when it's actually running and I don't know if we get to see that because the time stamps are the same the fire time and the scheduled uh or was it scheduled fire time I thought the scheduled fire time would be a different number that's interesting oh okay well I mean it's good like I need to understand this Behavior right so again context is if I have to schedule a post and it's supposed to go a certain time do I I'm assuming I probably trying to think if there's a scenario where I don't want it to actually post it's like hey you missed the time window don't uh and it seems like if I need to be able to say that I'm not getting that um built in here at least for these uh these ones that are like go run them in uh in 5 seconds from now now if we change how that looks though so instead of saying start at with simple schedule what are the options here so with repeat count if I don't want to repeat so no so you can give it a cron expression come on and there's some misfiring here here as well so I'm trying to see if there's a a different way that I can Define these um I saw calendar that's interesting calendar interval schedule wow lot of options there so my point is that like I was trying to see if if instead of saying you know 5 seconds from now that I could say like run it at this time but I guess that's what's happening that's what this was I'm again this is Nick not reading properly this always was started at a certain time and I was hyperfocused on 5 seconds from now but it's because it is giving it a solid time so I think this is this is what I want um which is good um I feel pretty confident about how I'm going to go implement this I'm super curious about the mass transit part so that might be something I want to follow up with um but yeah I might I might wrap up the stream there because I can start to feel the fever a little bit I'm getting a little bit bit glisteny and I think it's because not just the lights that are on me but I think it's because my Advil is probably wearing off um but yeah no this for me this was super productive I I I'm glad you got to see me struggle through looking at the quartz documentation um you know this part I think this job key was probably the most sort of confusing part but I'm I didn't realize the overloads that we had available so that was really good um this part ended up being way better than I thought I thought I was going to get stuck having to use XML configuration like these or not even XML like some weird config file that seem to be key value pairs whole custom file um so I'm glad we didn't have to do that and no problem Jack like uh I try to do these on Tuesday mornings and I like for me it's good I get to kind of practice uh forces me to code some stuff so that's good and uh the other thing that kind of fun is that well two things one is that it's kind of like pair programming right sometimes in chat people are like hey like you're obviously missing this thing like go go do this and it's like thank you thank you so much and the other thing too is like you get to kind of see like this this is real right um I've been programming for 21 years and I know there's like on LinkedIn where there's more Junior folks that are you know they're trying to break into industry and stuff and I just want to be able to demonstrate St that even as someone who's been programming for a long time like I mess up all of the time all the time it's totally normal um you still get stuff done uh it's especially helpful if you can read though apparently um I'm not great at that so yeah I think it's it's good for me to be able to do uh I enjoy it so kind of cool but I do think that I am going to get ready to go with uh with quarts and my application I I can see how it's going to tie in nicely now and I'm excited for that so thanks folks sorry for ending a little bit shorter I like to go for about two hours but I think I got to be uh realistic with myself here so um thanks again we'll see you next time take care

Frequently Asked Questions

What is Quartz.NET and how is it used in the video?

Quartz.NET is a job scheduling library that I used to set up periodic triggers for tasks in my application. In this video, I explore its persistent store feature, which allows jobs to be scheduled and stored in a database, specifically using SQLite.

Why did you choose SQLite for this project instead of another database?

I chose SQLite because I wanted a lightweight solution that didn't require setting up a full database server. Since I already have a MySQL database for my main project, I figured using SQLite would be simpler for testing and development.

What challenges did you face while integrating Quartz.NET with SQLite?

One of the main challenges was understanding the configuration and setup process, especially since I had to deal with some complex dependency injection issues and the need for specific database tables. I also found the documentation a bit lacking in clarity, which made it harder to implement the features I wanted.

These FAQs were generated by AI from the video transcript.
An error has occurred. This application may no longer respond until reloaded. Reload