User-Defined Functions in Fauna (with Rob Sutter) — Learn With Jason

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hello everyone and welcome to another episode of learn with jason today on the show we have rob sutter rob thank you so much for being here thanks for having me jason hey everybody happy new year i'm super excited to have you on the show uh we are going to be doing some really really fun stuff but before we talk about what we're going to be doing let's talk a little bit about you so for folks who aren't familiar with your work do you want to give us a little bit of a background sure so i am a big fan of serverless i'm currently the head of developer advocacy here at fauna the serverless database don't call it that it's the data api for modern applications it's a serverless database i'm gonna get in trouble if the ceo hears me say that but i'm pretty confident he's not on twitch um let's hope i'm right prior to that uh i was with the serverless team at aws so of course all the such serverless classics is aws step functions aws lambda amazon eventbridge all of those things um and i just love to build i love to build in public i've done all manner of stuff outside of tech as well worked for the government i worked i was in the military so you know here and there all over the world just an all-around all-around guy all-around all-around guy i like it uh so i yeah so fauna i think is is kind of well let's set some context before we talk about fauna specifically right so i think that um a lot of the folks who watch the show are front-end developers i'm a front-end developer over the course of my career we come in contact with the need for storing data and what i found consistently is that a lot of times i am more willing to talk myself out of an idea than deal with the process of starting up and hosting and figuring out how to deploy a database right and so i feel like as as front-end developers we get we get kind of sold this idea that we should be full stack and and being a full stack developer is completely infeasible right like there's just so many things you got to know you can't really become an expert in all the things that you need so then fauna kind of comes in and it's offering something that you call it a serverless database but it's it's part of this kind of new class of of database systems that is really interesting to me as a front-end developer because i don't have to think about how to stand it up how to deploy it how to how to get it out there right so do you want to talk a little bit about kind of what what is spawn how does it how does it work for us yeah so i'll get to fauna i want to hit on a couple things you said as well first off i'm like i'm glad you came out there with the opinion on being a full stack developer there's just so much to learn i'm a back end developer and so everything that all of you all do on the front end just mystifies and amazes me i don't get it i'm like i can't you know we all make the joke about not being able to center a div that's not a joke that's not a joke i can't do it much less make something look feasible so everything we do on the back end y'all a have been doing on the front end and b making it look good at the same time so i think it's i think it's fantastic what front end developers do and it mystifies and amazes me um the i also think like a lot of the points you said about fauna i think fauna is a great match for front-end developers because you're already consuming apis elsewhere like you want to process a payment in your app you're going to stripe you want to send an sms you're going to twilio that you you know you want to embed search you look at something like algolia so you already know how to do all of these things you know how to get an api key and store it securely in your application you know how to handle user authentication or roles maybe you're doing that with off zero like all all of these concepts that you're doing you're just doing the same thing with fauna right so you create a query just like with graphql right it's either a query or a mutation you send it to fauna and that's it like stop thinking about the rest because you hit on it's so difficult to manage it's even if you do it cloud first you've got to create a virtual private cloud what's that that's a whole category of problems we can talk about for a day you've got to get all the security groups right oops that's wide open now all my stuff is out there for everybody there's just all of these things that you have to go through just to get it functional and that doesn't even begin to get out what do you have to do to get it correct and perform it right and fault tolerant and all of these other like back end things that now i start to become in my element and and nerd out on so that you don't have to it's just another service put your api key in your app authenticate your users send your call store and retrieve your data yep yeah i mean that's and that's really the the magic of this stuff right is that where we start talking about like as front-end developers the the thing that attracts me to this this kind of jam stack decoupled paradigm is that we're getting to the point where everything we're doing is building a front end and then sending api calls to do everything else so if i can form a json object and send a fetch i'm able to do almost everything that i need to do to interact with different backend platforms and that feels like what you know when we start looking at at fauna that is kind of what's happening here right we're not we're no longer like i don't have to figure out how do i how do i do like a special connection i don't have to set up like you know connects or open a a raw my sequel connection or any of those sorts of things i don't have to think about what that actually means i'm just i have a database and i'm going to send a request to the graphql endpoint or to the you know the other fauna database endpoints and i'm going to get a response back and that's my data i'm done i've built a custom database as far as i need to care right and i think that's what really makes this such a powerful idea is that i as a front-end developer want to be able to build things i don't want to have to think about how to deploy and scale things and there are companies out there that do this for us you know as you said stripe just handles payments so that i don't have to think about the security and the compliance and all of the infinite things that can go wrong with payment and with databases same thing if i you know a database for me on my local machine cool whatever it takes me 10 seconds a database that needs to work here and in australia that's a whole different set of problems right and and fauna's just making that go away and i think that's what's exciting um it is exciting it's it's hard to talk about fauna because there's so much and you know like i'm i'm a back-end centric person but our engineers are just on a whole other level for me and there's there's all this world-class engineering that's going into fauna and there's all these firsts in there and you really want to talk about them all the time but quite frankly nobody cares like what you want is a place to put your data and to get your data when it's there so it's like it's an interesting thing to try and to try and not talk about so often when we're working with it but yeah just like you said the fact is you put data into fauna you define your graphql schema you perform a mutation and boom that record is available in multiple locations for you to either read it or for resiliency right and you know tons of tech stuff you can go into but really that's all you need to know about it is that it's it's there and working yeah i mean and that's you know i think like when you when you start dreaming about this idea of full stack developers like that's what unlocks that promise if you're a front-end developer and you can do the the web stack the website stuff and then you have services like fauna and stripe and and you know all the other me the headless cmss all these other myriad services you can pull up and use you are now a full stack developer because you've got these platforms filling in all of those scalability and dependability and reliability gaps that you know you would have to build a whole team around but because these services are there and providing you with apis you as a front-end developer can now kind of build incredibly complex apps without having to build that whole extra set of skills and it really is like it's like gaining superpowers when you really start to put together what serverless and these platforms unlock for you yeah it's i think front end development is the most valuable part of the stack don't get mad at me everybody else because it's it touches the customer it it defines the customer experience for the customer and it's the most differentiated it's always going to be the most differentiated which means all the work that you're doing there is creating some sort of value value for the customer value for the company differentiating you from your competition and i you know i like talking about do you understand power systems theory do you understand supply chain economics and diversification of fuel sources because these are things that are still happening underneath your app but you're not considering them right now right your app's running somewhere in a data center and that data center has to have power from multiple types and those have to be fueled from other these are all things that have been commoditized and stripped away from you so why would you go learn how to manage a database if you want to deliver customer impact any more than you would go learn mining you know i love i love that you bring that up because it's it's kind of funny where we draw these arbitrary lines for like what needs to be built in-house versus what shouldn't be because i i always laugh when somebody's like well but you know if you don't understand how your tools work you can't really be good with your tools and it's like man i don't know how to get down to my motherboard and flip a bit from one to zero so i have zero understanding of how my tools work i know how the baseline abstraction of javascript works i sort of understand what happens under that and then it's a mystery i don't know my tools at all i am absolutely using somebody's abstraction of an abstraction of an abstraction that makes rocks think and that's we do have the smartest rocks we do smartest rocks in the galaxy here on planet earth but i mean you don't even have to get out of software for that man like name every register in your cpu oh you just upgraded to an apple silicon m1 arm name all the new registers in your cpu right and you don't have to go down to that level either i mean it's it you can't you can't know all this stuff it's folly to suggest otherwise so yeah right and so so really where where we have to be as as developers as honestly just as humans we're here to solve problems we're not here to know everything and so we should choose the abstractions that enable us to solve problems and i can't i don't have the time to learn every single thing but right i do have enough time to learn this one common abstraction which is an api and because everybody's starts really starting to to coalesce around this idea of you know you have an api endpoint you have graphql or rest or however you want to send these queries you are able to send and receive data through a common interface and that means that i as a front-end developer only have to learn that that's the boundary i have to learn up to everything else is an abstraction i don't care how stripe processes payments i don't care how fauna processes data i just care that when i send it some data i get a response back and that response is what i need right exactly right and the differentiation in there is you know stripe handles fraud detection and alerting and things like that so you don't have to run massive machine learning models and learn machine learning and learn theory behind broad detect and all this it's not it's not only storage right like there's so much specialization that they do similarly you don't have to you know worry about learning uh you know distributed consensus algorithms and multi-phase commit versus single phase locks and i don't even want to learn what those words mean why yeah yeah i probably in fact i made one of those up and uh some savvy user out there can tell can tell which one it is we have two algorithms and a lie with rob sutter that's right that's right my favorite distributed consensus algorithms raft and sesame street one of those is a lie i'm actually worried that it's not sesame street that's july uh that that term was used without authentication or permission from the sesame street broadcasting company i apologize and i regret the error we're going to get it that was that was my mistake not the show's mistake all right y'all so uh so okay knowing all of that talking about that let's let's talk a little bit about specifically what we're going to try to accomplish today so we've got uh we've got some content of like how to get up and running with fauna on learn with jason already but we're not talking about that today we're instead talking about something that's even a little more is advanced the right word i guess just customized which is user-defined functions and i'm really interested to hear about this so can you talk a little bit about what this means yeah let's let's not call it advanced or customize let's call this a growth session okay this is uh you know you've you've gotten logged in you've gotten a basic graphql schema and you're eventually you're going to run it to a point where you want to do something that's not supported or you want to enforce something um at the at the data layer a user defined function is exactly what it sounds like right it's user defined so you create the definition it's a function so it's compute yes thank you indifferent ghost thank you welcome to the booth jason's behalf yeah we don't have any boobs yet i'm kind of i know i know i know we haven't we haven't gotten the chat going sometimes you just gotta you just gotta yeah you gotta put the quarter in right so we've got a new subscriber you've got to abuse that new boot that you've got there it is here we go there it is there we go there we go thank you i appreciate it um and the last point is it's a function right and so that means that it's compute that's running the thing about this you talked about duality of data or something earlier that i thought was really appropriate where this is happening on your data in the fauna data centers and this is different even from something like if you run say aws lambda and dynamodb you've still got to load that data into your function do some processing on it store the result and send it back this is happening they're co-located your compute and your data are co-located on the same instances so it's it's right there if you want to think about it conceptually on the same machine so it's really performant um and you know there's there's several use cases for it some are just simple quote unquote custom business logic and we'll walk through some simple examples but you can also do really advanced stuff here and it's you know maybe beyond what we'll show today but you can do fault injection so you know like chaos engineering fault tolerance where you intentionally insert errors on a certain frequency in order to determine if your overall system handles that error you can do unit testing of your functions with that you can do very advanced abac or attribute based access control for your functions to ensure that you know all of these conditions are met before a write or read occurs and user defined functions are just really powerful ways of encapsulating that logic and hiding it from the user so you can do that with guards or you know they may not even know that they're calling all of this logic it's just you create a create boop function and all the user knows is i want to boot and they request it and if all the right conditions are met they get a boot and if those conditions aren't met including intentionally injected failure they don't get a boot and that's all they need to worry about so it gets reused among different components of your application as well that's that's slick okay so i feel like at this point we're starting to talk about things in more concrete terms so let's uh let's switch over into pair programming view here and uh and let's talk for a minute about the live captioning so this show like all of our shows is being live captioned we've got rachel here with us today thank you so much rachel and that is being done by white coat captioning um the captioning is made possible by our sponsors netlify fauna thank you rob uh off zero all of whom are kicking in to make the show more accessible to more people it means a lot to us uh and i should cal i should call out this is not a like a sponsored episode fauna is a sponsor of the show and this is a show about fauna but it's not i don't know how to i don't know how to differentiate yeah exactly right like this episode is not like uh like fauna was like you have to do this or else no i can be kicked off at any time if i underperform very important that you all know like i'm skating skating on the razor's edge right now um yes so yes all right so now uh make sure you go and follow rob on twitter rts underscore rob and we are today talking about fauna so if you want to go check out fauna that's where you want to start it so i want to do some data i'm ready how do i get started with this hey can we sidebar i want to i want to i want to show 15 seconds sure you said this is not a getting started with fauna episode but if you click that sign up button can you show them how easy it is to get started with fauna we won't go through the whole thing but look at that you got a github account you can get started with fauna you got a netify account you can get started with fauna boom account free tier don't have to provide any payment information drop you right in there ready to go so the free time that i've run my mouth you all could have created fauna accounts well and the free tier is good too right so we get um you get quite a like 100k reads per month 50k rights per month uh 500k compute now that's what we're building today right is the computer and we're going to talk about those too yeah uh and 100 megabytes of storage so this is something where like i as a developer i'm able to run a handful of things on fauna and i don't even get close to these free limits so this is very much like you can start here and you'll be able to use it to get your business up to the point where it makes sense to pay for things i that's that's a model that's pretty near and dear to my heart like i at uh at nutlify we do the same thing we want you to be able to use it for free until you make money from it and when you start to make money from it then it makes sense to pay for your services right so uh it's kind of like we want to start with you and grow with you and and uh and make all that work so side note before we go off of that hard limits and force and that's a decision that we made so that you can play in there safely get a hard limit means that when i hit my i do 100 0001 it just says now you're done right rather than starting to know you and you getting a surprise bill and then the other plans allow you to you know manage overages and things like that so yeah yeah yeah cool cool cool all right so let me log in i already have an account so i'm just going to log in with my nutify account here yeah while you're doing that you've got a question in the chat how does a company provide such a generous free tier always baffles me uh there's a whole lot of pricing theory around this and it's customer acquisition cost right the hope here is that you'll do like what jason and i have done and go out and build with fauna and then when it comes time at your work that you'll say hey i've built with this database it's really awesome all you got to do is just put your data in it get it out it handles everything for you we should use it for this project yeah and then that becomes like we grow that way and your company will need to pay for it because of the scale and size of data that it has right um but you as an individual can learn for free and side note i pay for netlify as well because the analytics are so valuable for me yeah and and i think that's the other thing too is when you start thinking about like software as a service if you're if you're trying to build out something and you're considering a free tier the the way that the the pricing is shaped it is significantly more expensive to try and support like tens of thousands of five dollar a month customers than it is to do a free tier with like forum based support that doesn't require active headcount and have like paid enterprise customers because enterprise customers you know if you look at what a company like ibm or amazon is paying for their monthly contracts it's in the like tens or hundreds of thousands of dollars a month for for a given service so enterprise contracts totally make up the difference that's that's why companies are able to do free tiers is because when they when you know when you as an individual developer go sell this to your boss and you work at facebook it absolutely pays for all the free services that you got like many many times over um that's right and you know again we don't want to monetize individuals we want you to build things and have and like learn and have fun we want uh we want companies that make money from services to pay for services that's where it makes sense that's right cool okay so i'm i'm i'm here i'm in i've uh this is my i've done 1820 readops over the last seven days on fauna um 998 181 to go let's not use them all on this uh on this episode yeah let's see how aggressive the chat gets here but uh yeah let's so let's get started here i'm just gonna start a new database is that right yeah let's do it new database so we're gonna call this one user defined functions and do i wanna pre-populate yeah let's do it let's pre-populate it because it's not a ton of data um gives you something to to work against query against and just sort of gives everybody the same pre-populated data so that you can take the functions we write today put them in your own database and off we go and so now all right so i've got some some data in here let's pop one of these open and look at it uh so we've got you know customer first name last name address phone number credit card okay yep all these things good uh real credit card i hope not well um that just in case anybody's not super familiar with fauna a collection is a collection of documents you probably think about that like a table if you're coming from a relational database background a document is an item or a row if you're coming from other other platforms we call it collections and documents and fun fact that informs a lot of theory everything is a document in fauna and these are like unstructured right like i can put whatever i want in here it's uh i guess the term that you would hear use is nosql is that is that how you would describe fauna uh would say schema-less fauna is sort of it is a it's a next-generation nosql database if you want to pigeon-hole it that way but it works with both schema oriented and schema-less models so if you're building with graphql and you upload your graphql schema then you're going to have that defined schema in there because graphql requires it but it's enforced by the graphql layer not the underlying database layer so you could in theory migrate away from that and start doing naughty things um but then you'll get drift off of your graphql schema which will cause problems for you with graphql yeah gives you the flexibility to do it yeah and i think that's always the trade-off right about going with like something structured versus unstructured you can you can do whatever you want with unstructured which makes it flexible you could you get a lot of freedom also you can do whatever you want with it that's a huge foot gun yeah it is it is but one foot gun that it isn't is single table so you still model everything the way you think about it single table design is fascinating if your access patterns are fixed it you've got to you've got to break your brain to get to it fauna allows you to think about things the way you've always thought about them you do an erd or entity relationship diagram to define the structure and relationships of your data that's exactly what your collections are going to look like inside fauna as well so that helps smooth the learning curve a little bit yeah it definitely does because i uh i like i feel like just looking at tables in general if you're not super familiar with with data can be a little like okay so i've got these tape and i can just create a new one whenever i want yeah you sure can you can just do whatever you want um and so having to figure out how you would fit all of that into a single mental model where it's like okay so i'm putting it into data and then i gotta make it into a data customer or a data product and it's like okay i can get there but that's that's that's more than i want to do um but okay so we so we've got this this data this uh this kind of general setup of different places you can go and buy things uh the products uh orders for things and the customers who made those orders yep what should we do next well not go to functions but let's go to functions anyway so if you go to functions you'll see that there's one that's been created for you oh interesting okay that's not uh that's not gonna help you learn today it's a it's a more realistic but far more complex than how we want to start okay so let's go over to the shell instead oh i've never been to this tab you've never been to the show the show's my friend i pretty much only use the graphql tab this is like this is where i live in fauna i've never used fql either oh well boy is today gonna be a treat for you because user defined functions are written exclusively in fql although they can be consumed in graphql and we can do some uh what i call stupid graphql tricks later the stupid is a modifier for the tricks not for graphql um where you don't even have to define types you can only define queries with resolvers that are functions and then in graphql you're consuming your underlying fql structure that's a little uh that's a little advanced we won't we won't start from there the first thing we should do is let's start here let's start with yeah let's let's do hello world okay go i'm into it yeah go easy on me so we got to do we got to do hello world all right what you see here is the code editor right everybody can figure that part out so the bottom is where you're going to write your code and the top is where you're going to get some results so we can maybe adjust that balance a little bit we would need to add code um adjusting oh cool look at that a little drag up like that there and just real quick you know you can real click real quick you can clear that you can download it save it for later uh you can upload files um you know maybe you've got a repository with some sample user-defined functions that have been written by some cunning fauna das and you want to upload those yourself then this would be a good place to do that okay speaking you know um but so you can you can just go ahead and click clear if you want to jump ahead and see what he's hinting at this is uh this is a a repo full of um of examples that we may we may fall back on if i can't figure this out myself we may we may because you know there's always syntax and the syntax is going to be new because it's fql but it is um it is learnable i have learned it that is how i know it is learnable i've learned parts of it i've never tried to master anything all right but so we'll get rid of all those paginate calls there at the bottom get rid of them yeah and we want to create a function so me i like this type of stuff out type create see what happens hey create function create function there we go uh yup we use parentheses go ahead and hit enter to split those and now if we go to the docs it's going to give us a very complex example but let's just uh functions everything and fauna takes objects as input those objects aren't strictly json objects but they're similar so go ahead and give us some curly braces here curly braces yeah and split those and a function has two components a name and a body so name colon is the separator for key values and then quotes in hello world here we go now naming conventions you can't have spaces in there so oh right so this is the this is like the actual function name yeah this is going to be the actual name of the function okay then the body that can be whatever i want well it's not going to be in quotes it's going to be an fql oh okay ql is not a string based language uh without getting too deep into it if you've ever heard of a sql injection that's why fql is not a string based language okay so it it's composed if you're familiar with the functional sides of javascript which again is why i think front-end developers are way out ahead of the rest of us on the back end if you can think functionally in javascript or typescript you're gonna you're on your way to thinking in fql always always be functioning the abcs of fql so the first thing we need here is hackers you you dirty hackers okay so we got a query yep and all calls uh again yeah they're functions so put some parentheses there and then we're gonna use what's called a lambda lambda is exactly what it sounds like everywhere else right it's an anonymous function defined right there lambdas take two parameters if you want if you want you can split these out if you don't that's okay too i always split mine out so that i know where i am on the line um yeah and so then we know that it's going to take two parameters so you can put a little comma there and a return and you got like parameter one and parameter two right okay parameter one is an array of arguments yes that is the array designator in fql so let's call that first argument name because it's hello world so we want to pass it some function or some name right to say hello to uh arguments need quotes okay yep and yes it is functions all the way down according from the chat that is true it is functions all the way down functional turtles functional turtles so here what we're gonna do is use the concat function concat yeah see that completion there is really helpful concat does exactly what you think it does it takes some arguments is it like that or do i need to put it in as like separate so if you did that it might actually work but it wouldn't concatenate anything with anything so i guess we're going to like step one b by not just doing a static string we're taking the string parameter with one yeah you're running off ahead of me but it's okay the concat takes one or optionally two arguments the first is an array is an array of strings to concatenate oh i understand okay so we we got our array yep and i'm gonna do one of these actually let's let's talk to the chat how about that what's up chad hello jen is the this is the the glue that's right that's the separator okay all right so this is like the this is i mean you know anytime you're learning something new there's no way that i would have just intuited this but it is kind of nice that the autocomplete here starts solving a lot of the initial problems um i'm pretty fond of that so is this work done i gotta count my parentheses but that looks good to me do run query and let's see hey it created it before we go off this oh sorry you can go back up if you want what it shows you is the command that it just ran and then the output of that command so it's essentially the same as if you use the sdk and you create a query and send it that's the response object that you get back and what you see there is the the ref which is a unique identifier right the time stamp and then some other information about the function the name and the body yeah now it just collapsed it did not execute this function though that's right what it did was it created that function or again if you want to get really technical it created a document [Applause] in the functions category that you can now invoke right is that going to be in my collections or or i guess it would be in the functions it's going to be in functions we can go over there now and see here's my hello world yep cool you didn't give it a roll so of course it doesn't have one and then there's the body of your function so that's what we did here because we ran create function yeah yeah yeah i got you now when you want to call your function you run call call yep call takes two arguments first one is the name of the function you would expect the first one is a reference to the function because that function name can actually change so you d reference this is like a pointer you you use function can use ref that's a separate thing for another time function right there and then the name is a little bit of sugar to give you the reference okay and then a comma and then an array of parameters if you only have one you can simplify this to a single parameter they are ordered not named so it's not like keyword args in python you just give it the name that you want it to run it's really not going to matter for us here because we didn't use that parameter right in our definition so anything you give it it should send back hello chat okay so let's let's modify this then to actually use that parameter so can i edit right in the functions tab if i want to change my function you can in fact i recommend that you do okay so i've defined a parameter but we don't use it so instead of this i want to use the name how would one do so right so the way you get a parameter is with the var keyword var so you can take out chat there var like everything else is a function it's all functions all the way down functions functions functions bar name there you go that's that okay so then i need to do a little a little bit a little bit of sugar here to make that work save it yep come back out here run it again yeah now you're gonna have a little hey nice okay all right and so so this uh i saw a question that i want to answer before we move forward um ricardo asked uh do you know of any cms using fauna out of the box um i was hoping that was gonna scroll right off the chat because i do know of one and i can't remember the name of it off the top now right now so they do they do exist but yeah we gotta google for them yeah we gotta search let me see if i can get somebody to help me out um i've asked for the reference i am extremely embarrassed that i cannot remember it it looks like uh like databreck in the chat did link to a forum post let me grab that link oh yeah and uh oh no there's okay sorry i should answer this in two ways what i was thinking of is a customer who has built a cms powered by fauna that is not if you're asking for a cms for your data in that is a different thing and the dashboard gives you some uh yeah there you go this is more of that like bruno that you're showing on the screen now this is more of a cms to access your data in fauna pretty effectively it's really it's pretty intuitive i've uh i've gone into it it's a i like it nice there is also a cms for building static site generator right like putting the content into your hugo or gatsby site generator right like bill oh on top of fauna there is that as a customer use case as well that's the one that was slipping my mind for sure yeah i think there's and i think there's even like if you look at gatsby and fauna there's a source to pull in your your fauna data and stuff like that so there's there's definitely ways to to kind of make it a first class sort of deal um and it looks like uh we have ajc web dev in the chat sharing more links as well here's a dev2 post about building headless cms um but yeah so lots and lots and lots of options there for for getting stuff done um okay basic editing sorry if you want to show real quick just on collections you can do basic editing in the console in the dashboard the way that you just edited the function you can edit those documents the same way with your little uh you got your little pencil icon over there ooh so i could just come in here so you can yeah nice for one offs that's that's not as robust as the other solutions that we just pointed out but um to get you started you make quick edits there thanks for the uh thanks for the tips everybody cool okay so so we've got ourselves a a basic function um right it's it's running it's working and i guess the question that i have when we when we start looking at something like this is how would somebody like use this so if i you know if i'm um if i'm actually like storing data right like i'm probably going to be working in some other application and i'm going to be sending data in how how do we add these into our workflow what's the you know what's what's the kind of practical use case of a function like this right um without getting into too much theory i'd say the first place i would start is by wrapping your primitives what do i mean uh don't create get update delete with those calls in fauna do it through a function even if the only thing that function does is call create get update delete because it allows you to evolve it over time inside the database without modifying your client calls right so that's the first use case the way the way you do this with fql is you structure your queries and and javascript is a really easy example because you can import those different keywords that we used bar query body etc and use them directly okay to define a query in your javascript and then you use a fona client that you instantiate to send that query and then you handle the results when they come back okay that's one path there's also the graphql path where you use user-defined functions as resolvers for queries and then it's you would literally specify the at resolver and the name hello world and then in the query definition for the types you would have to list a name in this case the names don't have to match but you would have to list name as a string it would accept one string return another string using this user defined function so that way you can get it straight through graphql okay we can show that if you want to create another database that's just completely empty yeah let's do it up to you i'm going to create a new database i'm not going to user defined functions graphql node no database so it's an empty collection now yeah which is actually just a document of type database oh look at that um do i need to write do i need to like define a schema now to do this um you will but first you need to get that function in or actually you don't so yeah let's open up a file and we can define a graphql schema really quickly okay so let me um there's nothing in this so let's just open this up and we can uh we can mess with we can mess with some things so i have an empty uh empty repo here yeah and i'm going to create schema.graphql and i will say that for data research purposes i observed to see whether you would type gql or type out graphql all the way i don't know where i developed this habit but i picked it up from some framework um so then let's see if i remember we get our type query sorry and then in here we would want like get uh say hello say hello okay boops i mean whatever and then in here we would get uh we'd do like name string yep if i can type it out properly yep require that would return back a string yep and that's a simple that is a simple graphql schema yes but what we haven't done is wire up the resolver it doesn't know that we have a udf named hello world that's going to implement it okay yep you're right to do that all you need to do is on the same line just add a space at resolver i had i had a theory and then name hello world that's it that's it oh okay i understand that's that's nice so now what i'm what we're able to do then is i am not actually going to implement any data i am going this is this is effectively me saying hey fauna this one is basically an echo loop i don't need to store anything for this to function i just need you to call this function and spit back a processed piece of data correct cool so you can you can add you can upload this schema okay without creating any types any other mutations anything right just that as is and what's going to happen here is going to show us a couple concepts one let's just stop and talk yeah i need to get back into here's graphql how hard it is yeah and then i'm going to import import this schema and we're going to drag this one onto this one there it is and let's open it oh i screwed something up what did i screw up expected field definition so i can't help you are you still here there we go type crap did i screw some what did i do chat what do y'all see type query say hello name string string at resolver hello world this is correct invalid input string string resolver does it it's weird that it didn't highlight them the same but do you have some kind of weird space in there uh what am i what am i doing wrong here that looks exactly like how oh resolver name hello world that's what it is sorry computer oops resolver name colon yes okay let's sorry that's all good all good we're gonna try this one more time yeah hey look at it go all right so now if i go into the docs i've got this say hello takes a string perfect okay that's that's everything that i expect my guess is this explodes right now right well it's not exploding but it's not going to give you what you want for what you expect but go ahead and run it like i said it'll be it'll be instructive for a couple reasons function hello world was not implemented yet this is a good error message i was really worried that it was going to give us one of those kind of generic like unable to determine you know invocation at line whatever instead of just uh instead of just you know doing what i want which is to tell me that i haven't done my job yet um this is really slick though i mean i'd be lying i'd be lying if i said we didn't have some of those but this isn't one of them i think we all i mean we all end up with those at some point in the code base but it is nice that this one at least you know when i'm coming straight out of the gate right because i feel like as a beginner that's when instructive errors are the most important because otherwise i'm just going to throw my hands up be like i don't have time for this um so this is this is wonderful so now i need to to implement this function which i will do by well let's let's see what happened here let's go over to functions let's see how it managed to get that response to us wow look at that holy crap so when you imported a graphql schema with a custom resolver it realized that that resolver isn't there yet and so what it did was it went out and created that function for you with this error message in it excellently call it you hey you didn't do that yet but i'm still with you because my video is frozen you froze up there for a second um yeah audio is good yep audio's all good uh okay so now we've got a query that's a lambda and so then i can just start implementing things right i can go back and do our thing and it's gonna be a concat right and it's gonna concat uh hello name okay i think i've done that i'm gonna save it yeah let's go try this again i'm gonna go back to graphql i'm gonna run it again string expected array provided yeah um this one if you go back to the function definition it's one of our uh is it because i did this you need to there's a it's hard for me to see is that a regular parentheses followed by a bracket my screen is like gone out yeah that's that's what it was the lambda expects an array of arguments and then the local function to apply it can cat yeah does that and then remember we said that that second argument in concat is optional you've actually specified the optional the default value oh so if i if i leave that out it'll just work right okay let's go back and try that again hey there we go look at that everyone so another point that we sort of glossed over here that i think is pretty important um belongs to a database and when hey thanks that adrian guy thank you for the sub when you even when you create a child database that's now the scope that you're working in right and this gives you isolation guarantees right so if you if you want you can create a new database for each customer and that maybe makes sense if you're doing like some b2b kind of sas thing or you can isolate environments production staging testing et cetera and then you can upside you can modify and have different versions of those functions in each environment downside you have to manage them and keep them in sync and we have tools for doing that but that's probably outside of the scope of today's lesson sure it's just something to be aware of you did define hello world but you defined it in the database user defined functions and now we're playing in user defined functions graphql so the graphql layer defined it for you and now we've defined it and now everybody's happy yeah yeah and this all makes i mean this and this makes sense so what i'm what i'm kind of imagining from here is that i would probably want this to be like i could do some kind of data pre-processing on query or a uh pre-processing before saving so that i could like if i'm gonna i think the the saving a customer order one was a good example where it looked like i didn't actually look at what the the function did but my guess is that we're doing some kind of validation like the order comes in and we're checking to make sure that required fields are there or we're breaking a full name into a first and last name or or something like that right so how would we uh how would we do that where let's let's maybe add another function here um that would let me pre-process some data so that we could like send a mutation here and uh and save some data but like mutate it in a way like we'll pre-process a little bit uh do you have a yeah like it's like you're reading my mind and i know that you haven't actually seen this function in the repo which is why it's even more impressive um example number two for those of you following at home in the repo is a limited sum or a limited adder and basically this this is just like a contrived example but it works for what you're describing it lets you add two variables with a limit okay and if it exceeds the limit it aborts and throws an error and if it doesn't it returns the sum of those two and this is an example of that pre-processing right let's say you have an account limit where somebody can they want to order 500 of x but they only have a limit of 50 right so you want to fail the order you don't trust the input from whatever client right even if you control that client you can still treat all input as untrusted and unvalidated do that validation in your database layer and by the way you can make that a function so that your create order function calls the validator which calls something else etc right so it's all composition now where it just asks for validation without knowing what the validate rules are and your validation team can begin applying increasingly complex logic uh feature flags i didn't mention but that's an also also an excellent use case for this is feature flags where if you want to compare releases or turn things on for other customers or not so let's let's create a new function here let's go back um if we want to do it i'll leave it up to you we can either add it again in the graphql schema and show updating the schema which will merge those changes and create let's do that skeleton force i feel like this is in terms of my standard workflow uh i'm probably going to use graphql for my my day-to-day so showing how to kind of set this up for for graphql seems like it's uh immediately practically applicable for me so let's do it let's follow my preference everyone show [Music] um so yeah just copy and paste that inside the query block there create a new one you said this is called limited sum uh if you want to make it match the repo yeah and then calls it limit adder but it doesn't matter oh they're wrong and now we're going to give it two arguments right two operands yeah num one num2 it's for simplicity and this is going to give us back another turn it and we'll make a function called limited sum there you go all right so now how much easier could it get really so i'm going to merge schema by uploading this again and what this should do is uh it just doesn't break anything that was already there and had i done something destructive it would have failed right it would have been like now you can't do that because it's not mergeable right and that if you there's the two question mark uh helpers like tool tips right there next to merge schema and override schema that show you the different behaviors and what's going to happen on each right so it aborts if the indexes are not compatible with the current schema this one is like for my for my sql people that's drop database recreate including your data your data is going away if you use that button don't use that button unless you know what it does and then you'll know that it's okay to use it all right so again if we if we call limited adder and give it two arguments sorry limited sum then what we want back is six but what we're going to get back is you have not finished doing these things okay right so then i'm going to go here and we're going to detail this button yes we're gonna get back num1 num2 and then down here we're now out of my out of my depth on fql i don't know what happens here what if i just type add is that the right thing oh wait but we want to do math you know what let's let's let's start this iterate right like let's just return the sum without any limits and look at you you got it yes i think i just said this is the fql way you're doing it you're doing it peter all right let's try this again i'm gonna go back out here let's run this uh hey look at that i just fql yeah okay so now there's no limit on that so you can do weird things like arbitrarily two large integers in there and get unexpected weird javascripty results out of it um yeah value too big to fit in it just uh you know just just javascript things just drop some trailing characters it's basically the same number handle yeah that's how i do math too it's a we call that y2k map just roll it over right that's right that's the 386. well that was a pentium that had that bug wasn't it i'm old y'all i'm sorry i figured that probably made sense to like five people that will ever see this but once upon a time there was a thing that didn't work all right so once upon a time there was a thing that didn't work the never-ending story of web development um okay so now wait i'm looking at the wrong thing let's look at this one yeah i appreciate your uh your attention to formatting i mean this is this is a self-preservation instinct honestly uh which is fair all right so here's our formatting and we are now adding but we want to make sure that these numbers are below a cert i guess we want to make sure that this is below a certain value yeah let's do this in two phases okay i'm going to walk you through a simple way that works and then we're going to expand that to something that does the same thing but is more realistic and you can expand it to a lot more use cases so first let's just make it work right so really our condition is if the sum of these numbers is less than or equal to some limit return the sum otherwise throw an error that sounds very much like an if statement conveniently fql has an if statement equally conveniently equally conveniently rob can freeze right before we get it we we lost you right as you uh started saying equally conveniently about an if statement okay i still hear you so hopefully you know like i said i'll just get into i'll get in there i'm still here oh we can hear you we're good wasn't that that joaquin phoenix uh autobiography yeah yeah or something anyway was that one autobiographical i thought that was a publicity stunt anyways this is not film this is not uh film criticism with jason's so all of my references are tangential and off topic so if takes three arguments if takes a condition and it takes a statement to perform if that condition evaluates to true okay and it takes a statement to perform if that condition evaluates to false right so we're gonna we're gonna repeat ourselves we're gonna violate the the dry principle here and repeat ourselves but our condition is if that sum that you have there is greater than or equal to some number or is greater than some number okay so let's let's order it the other way let's make it less than or e less than or equal to the limit so in this case we have lte is the less than or equal to function all this stuff is in the docs of course that's one that you kind of like you need to know it's there otherwise you won't find it um less than or equal takes two arguments exactly less than or equal takes two arguments a number and a number and if the first number is less than or equal to the second number it returns true and let's do it let's do an easy one we'll do less than 100. so if if this is less than or equal to this or is it the other way around if that is less than or equal to 100 it evaluates to okay all right good good good if it's strictly greater than it evaluates to false so if it's less than or equal to 100 we return that value that you've already got there we know what to do there if not we want to throw an error abort is the key word for doing this an abort will break you out of the transaction that you're in all the way out in the call with an error message that you specify and that's like a little aggressive of an error message but it's not wrong so we can keep that that's fine that's fine okay so let's give this a shot then um it didn't it didn't fail that's always good news uh so let's make sure that it still does that math didn't hard code numbers okay no now let's make it way too big there you go and i've successfully entertained myself thanks for coming everybody that's what it's all about no this is i mean this is great so we we now have an actual limited sum now you said this can be better right if we go back to that function definition and we look at it um you know i'm not crazy about seeing that add var num1 var num2 in there twice right like that here we can talk about compute ops every 50 fql verbs is one compute up okay so when we do add var var that's three when we do it twice that's six now three and six are both less than 50 so that's one compute op in this case it's it's sort of trivial right but when you have realistic workloads with much bigger query much bigger guards and gates you you don't want to do things more than once right you don't you don't want to recalculate the same result so what would be great would be if we could store like calculate that result sort of store it somewhere and then do the comparison against the stored value if so return the stored value if not return the error right yep that's what the let keyword does for us in fauna okay so i'm gonna make a guess that i wrap everything with a let so that it's defined in that scope that is correct okay let takes two arguments let takes an object or a map key value pairs and then it takes an expression that we call in but it's it's just the thing to do with those variables defined right so in this case that entire if you don't know you don't call it in there sorry oh okay yeah it's that entire if statement is the second argument the entire if statement is the second argument right okay and then the first one is gonna be i assume i need to pull this out right okay where does this go it goes inside that map of uh variables or values that you're pre-calculating and declaring for this context right so we can just do like this right okay and so then when i use this i am going to wha i assume there's a key word for this or do i just write it out it's another variable so you need to wrap it with the variable call less than or equal to var sum got okay so we're just defining basically we're creating local scope right so there there are three variables here right two that are parameters that are passed in and one that is created by the let statement so this this simple function here is actually showing a lot of different pieces of functionality of udfs nope i missed something i missed it where one you're missing it on the sum line you're missing a closing parenthesis line six yeah got it okay great so then if i come back out here same thing works yep you should see the same results here does not work perfect actually i mean this is slick right and i can see i see where the value in this really starts to show up here because you know it it first of all this just makes my life easier to not have to copy paste these values in over and over again um and you can also see how like you would be able to calculate something like i can i can take you know this this could be some derivative of any of the input uh and and you know i could do something like if the name that comes in is rob we could change the greeting based on that using this right this kind of structure so that yeah that's really cool like i can see that being um when we talk about like the you i saw that the functions could have roles um these are also really cool things that we could do where like i'm i'm kind of imagining right now uh i have some logic built that triggers a function only if you have certain access permissions like if you're a moderator on twitch or something like that where these could actually just be built in just like this uh and then it would it would happen on the data side instead of me having to write like javascript that then calls a database that then does more evaluation to see if you're allowed to use the data that came back which is honestly a huge security problem right yeah it would just refuse to return it and you can get really dialed in on that with abac too right like not only are you logged in and authenticated and authorized to access the data but is it working hours can you access only certain sensitive data from inside for you know from monday to friday nine to five or whatever or is some other person logged in like a like a two two person control on it you can anything that you can calculate inside a query yeah you can use as an attribute so let's go let's go one step further here which uh i i want to actually let me add one thing before you please screen though that that let statement in there any query can go in there too so sum could actually be some value that we retrieve from the database and this is where like the feature flag example that we talked about right you can look up based on the user's id are they enrolled for this feature did they subscribe for this feature are they you know paying for it however you want to use feature flags for dark deploys or whatever that's one aspect of it reads are pretty good here be careful about rights there in particular if they're going to cause contention because all of these transactions all of these are transactions they're all acid compliant right so they're they're all all or none it's going to either is going to happen or it isn't reads are much less problematic but but any query that you do there can go in there and this is also where you would do your determining whether to intentionally fail or whatever else if you're doing chaos engineering on this okay so what i want to do then is i want to take i want to go one step further and i want to save some data um okay and so i'm i'm thinking about something like this and what i want to return back is a user uh and so let's create our type user and our type user is gonna have a name which will be a string and a um a status which will be a status and then let's do an enum i'm just gonna do something does that enums work in fauna uh i believe so yes it's um did i lose you i'm here no okay uh so yeah this is my this is my thinking did i do that right that's i think that's correct front end man you you're outside of my uh okay my comfort zone with graphql goes very quickly let's do this let's uh let's not use an enum just so that we don't introduce any kind of chaos but here's what i want to do i want to have a save user call a function and that function is going to be determine coolness uh and that's going so we're gonna pass in a name and the function is gonna determine uh let's let's call it coolness instead um all right so i'm ready you're gonna have to pass it a user though right or are you gonna oh no i see what you're saying yeah so this is this is like randomly calculated yeah yeah yeah so let's uh uh because we would need to go further with this if we were gonna make it like more professional but we've also only got like 10 minutes left before we need to start tearing down so i want to be uh realistic about what we're what we're trying to accomplish here but so now what i want to be able to do is in here i want to be able to uh sit wait did it just create a whole bunch of stuff for me wow look at that yeah that's super cool okay so now we've got um wait which is the one that i wanted did it oh here's my yeah here's my my mine is save user yeah so i'm going to say yours because you defined it is going to be overwritten so the others are implicit i'm gonna do this and then what we'll get back is a name and a coolness and when i run it right now it's gonna say you don't have a function but we can go over here and now i'm going to get a name and then we want to do a let and in my let i need some data and then i have more stuff that we're going to do so i want to let's see what i can figure out here i'm going to get name well actually i don't even need this because we're not going to calculate anything here are we so i can just calculate the coolness right that's this is a place where you would generate the coolness that's true yeah i was actually just going to do a hard string comparison and say that anybody who's not json is cool but i guess we can do that right into the world you don't have to put up with this so we can let's do that let's do uh let's set coolness here and we'll calculate it once and that would be uh an if their name or wait i need to do like an equal what's a string comparison here is there like an equals equals yes then cool otherwise not oh wait i did that backwards okay so if then i don't need an if here anymore so instead i want to do a right now and this i'm completely at c here because i we haven't done this yet but i want to write to my users collection which has not been created do i need to create that first oh it has been created because you created it in the graphql scheme that's right i did there's a user's collection over there for you okay so then i need to write to that collection and i don't know how to do that i am here for you man um create create create the power of create create takes two arguments okay one is a reference and but well don't don't try to type on this one yet and then the second is the data um the this is um i think enough document is am i so as long as we got audio we're good um you're going to create in the users that was created right oh no okay we're back users that were created am i back you're back i'm a back but back yeah create collection collection and then uh users i think was what you named it right what did you name it it's case sensitive too so whatever you named it in the schema excellent uh what did i name it in the schema i called it user so user so create user okay and then an object right so an object with name var name and oh sorry no not on that line on the next line so the first line is the reference which is just collection user that's where you're going to go to create a document you're going to create a document in that collection and then you give the body of the document which in this case i understand okay so my coolness name and coolness spark coolness cool okay so i i kind of i think i maybe slightly over complicated this one given the um the straightforwardness of this but still i mean but it's a yeah it's a placeholder for you to go out and calculate all the things that you need to do inside your function yeah so let's uh let's try this i think no i screwed it up what did i do ec win caught it in the chat it needs to be data because the top level object contains the ref and the data and so we have to give it yeah got it so that that'll work that should work yes okay so let's say you want that try it again i always use couching language it should work yes okay so saved me not cool oh no rob cool and then yeah if i if i get another one out here let's uh let's query uh users find user oh no they're like a get all users there's not but that's okay we can go look at our collections and set try lists is there not a list users i don't remember what it generates exactly i don't i i'm pretty sure with the graphql you have to actually define the all users but we can go look at it here and we can see yep here are our collections and so we get ref timestamp data and the calculated coolness so this is i mean i can see a million ways that i would be able to use this and i think that's um what i find exciting about this is that it is nice to know that things that i've heard that you should do like hey if you've got a database you should set up stored procedures so that you can do all these safe things i understand that in theory you know what i mean like i i i'm like yes i agree with you but i have no idea how so i write javascript and this starts to pick away at that and says okay so i don't i can do these sorts of things on the database side and and really if if i'm is this a gross miscalculate or a misrepresentation to say that what we're doing here is effectively creating a stored procedure that's exactly what it is okay exactly perfect um and so this is i mean this is great because now without having to become a dba without having to figure out how to actually manage this stuff i'm able to do these more like you know this is this is pretty powerful stuff that's not going to happen client-side or in a serverless function it's going to happen right during the query so the and and how does this affect speed like doing it here versus doing it somewhere else yeah so this is one thing that i'm working on getting hard numbers around the soft answer is minimally like my i talked about the wrappers for like write a gated create or guarded create versus a primitive create minimal meaning like five percent is what i'm observing and when you think about that compared to round trip on the network it's essentially not different and there's also the fact that like the way that we've configured this one this work will happen exactly one time when you store the thing if if you were doing it like ways that i have implemented things like this ways that i've seen things like this implemented would be i would store the name in the database and every time i query the database i would run that coolness calculation as part of my client-side code that is and again you know i would do that because it's like oh well that's flexible i can change it in the future and and i know how to do that but we can do that here on like a query calcula if we needed to we could do some kind of like a data migration thing where we could run this function with a with a different set right and and recalculate these values yeah you i mean functions can be routers where you can check the version sent in from the client and if it's an old version you mangle the data to the new format call the new function mangle the result send that back right without say you have like embedded code right embedded devices that are notoriously difficult to update and you have to assume that those updates will fail and they're out there the way they are you always have to support that api version you can do that in a function you can't do that if you're calling a primitive right because create is going to take what you give it and put it in there yeah a guarded create type function is going to allow you to modify that and modify it and modify it so it's really really powerful for that that migration use case as well that's super cool okay so if we are uh if we're kind of look i think this is probably about all we have time for to build today so for somebody who's interested in going deeper on this what are what are next steps where where can we go to learn yeah so check out the repo there's two more examples in there that add roles um as well as versions of what you and i have built today um those roles allow you to do more with permissions where okay hey look nobody can call create update delete only this function can and you have to go through this function which itself enforces the abac right so you can see how that becomes a powerful pattern um the do not use that function it's oh that's the role sorry yeah that role just gives access to do those operations on the uh on the stores collection from the sample data everything in the repo is built to work with the uh sample data the pre-populate with demo data option so that's the first step the next step would be go back to funnel labs and click around um one of our da's wrecked who has been in the chat here doing some answering so where's great questions uh sorry at the the organization where that repo was if you go oh has created a number of fauna blueprints here which are more fql and they're also in javascript so it shows you both ways of like implementing this directly as well as implementing it in your code those pinned repositories there the fauna schema migrate tool allows you to create these functions as infrastructure as code and apply those migrations so this is like really you're starting to get into the deep cuts here when you're when you're using functions with versioning and then that twitter application is a rewrite of twitter using fauna which all these concepts that we've explored are right there inside that code in an application that you can download run modify etc and begin to really understand how all of these things work together so those are the ones that i would i would start with right there those three pinned repositories will really get you a long way and of course docs are your friends blogs are your friend um questions hit me up on twitter you've got my twitter and here so this is like if we want to do functions we're going to need this uh this fql setup right this is this is where we're gonna find all of those um functions and all the pieces that we did there that's correct but if you go back to the repo at the bottom of it hopefully i'm not making a liar out of myself i'm pretty sure i added in next steps hey hey look at that this is a series of tutorials for fql that was done by pierre bover who i don't feel like i'm doxing him by saying this but he said on twitter today very publicly that it's his birthday so happy birthday pierre really appreciate everything that you do for fauna and all the help that you provide to builders it's awesome and i hope you have a great day uh he's built this wonderful series of tutorials that really take you through a deep dive of fql including user-defined functions but also including other concepts like indexes and roles and things that you'll need to really build effectively with fauna on a big scale very cool well that's i mean that's that sounds super exciting so uh i mean this is like i can see a huge amount of application for this i i can see this being something that that really lets us make good decisions about our data without adding a lot of complexity to the way that we are actually managing it um i you know i'm i'm really excited to see what folks are gonna build with this um i i feel like i'm seeing more and more advanced applications the fact that you've got a twitter clone built is very very cool and you know i'm i'm seeing more and more people who would would typically call themselves front-end developers building these very advanced like serverless applications with custom databases and all these api integrations all stuff that you know 10 15 years ago there's no chance that you would have been able to build all of the things that you're able to build now yeah especially if you were to call yourself like i'm a front-end developer but the front has extended quite a ways deeper into the stack than than you would have maybe but you know there's there's a huge there's a whole world of possibilities out there so even if you think that you are only a front-end developer like i can i couldn't do this data stuff i couldn't do that dig into this a little bit look at what serverless unlocks look at what these platforms unlock and and see how far you can get because i bet you can get further than you think yeah um so rob i'm gonna i'm gonna kick everybody over to your twitter again where else should people go if they want to keep up with you um i once upon a time streamed a lot and hope to start doing so again i'm on twitch.tv slash rob sutter oops that's the wrong um here we go uh my github is far less interesting than the fauna labs repo so go there if you want to email me if you're that kind if that's how you roll rob fauna.com that's a pretty straightforward uh here i'll dox myself in the chat there um but i'm always happy to hear from users help answer questions where i can there's the fauna forums are great places to look for help i'm not trying to push you away from me i'm saying maybe your question's already answered and then the final forms are a great place to find that um but yeah i'm very active on twitter my dms are open so uh if if you hit me up there i'll get back to you great uh forums.fauna.com that's what we're talking about actually i'm just going to link to this this community page because it looks like there's also a slack channel there is so get in there and check that out all right well with that i think we're going to call this one a success as always we have had rachel here from white coat captioning live live captioning this whole process thank you so much for being here um and that's made possible by netlify fauna auth0 and hasura all of whom are kicking in to make this show more accessible to more people uh while you're over on the website make sure you check out the schedule we've got a lot of really fun stuff coming up and apparently my styles didn't kick in there we go there they are uh very large picture of my head we've got uh mark erickson is coming in later this week we're going to learn modern redux he's been working really hard on this to make redux more approachable a little bit less boilerplate a little more understandable and i'm super excited to see how all that has been going i have a bunch of episodes that i haven't added yet so i'm going to get on that and actually make that happen but we've got all sorts of fun things coming up so make sure you go and check out that schedule and and click this add on google calendar button so that you can see what's coming and uh you know get a little little heads up when we're about to go live with that rob thank you so much for hanging out with us today thank you for having me thanks for joining everybody yeah it's been an absolute blast chat stay tuned we're gonna go find somebody to raid we will see you next time you
Info
Channel: Learn With Jason
Views: 1,042
Rating: undefined out of 5
Keywords: Fauna, Learn With Jason, Rob Sutter, custom business logic, data, database
Id: eFj_evCul-M
Channel Id: undefined
Length: 87min 5sec (5225 seconds)
Published: Wed May 26 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.