 Hello, everyone. As you have mentioned, I'm Patrick. I'm one of the organizers for this Europe Python and also Python Italia. I have a slide at the end if you're interested in the dates for next year. But my main job is a developer part of the project that Apollo GraphQL. We build tooling for GraphQL. If you use GraphQL, you might be familiar with Apollo Client or maybe with Apollo Federation. But today we're probably not going to see any of that. We're actually going to see another project from my which is Strawberry, which is something I created about maybe five years ago, which is an open source GraphQL library for Python. And this is something I do on the side with some friends. And it's being used by quite a few companies now. So before talking about WebSocket, I kind of wanted to do a quick introduction of what's GraphQL because I want people to be on the same page when we talk about some of these things. And GraphQL is a technology that allows you to create APIs. So you can think of it as an alternative to REST, even if it may be a different use case. And GraphQL works by having a schema. And this schema defines all the things that you can do with your API as types. For example, here there's a poll type, which has an ID and a title. And as a type called query. The query type is actually special because it's basically saying these are all the fields that you can fetch from when you do a query operation. And we're going to see more about the operation in a second. But the interesting thing of GraphQL is that everything is typed. So you can see there is colon ID as commission mark. And that means that that field has an ID and that field is never going to be null. For example, the poll is going to return an optional poll because the poll with that ID might not exist. And when you use GraphQL, you can do queries like this. And this is basically something that's called an operation. And the operation type is query. And you're basically here telling I want to fetch the poll with ID 1 and I want to get the ID and the title for that specific poll. And instead of having multiple endpoints in GraphQL, you only have one where you send a document like this. And then that document is actually going to go and basically call the function that you define for fetching the poll. So I just wanted to quickly show you a demo of this because I think it's like seeing in action is probably easier to understand. So I do have a small server using serverry. And I'm also using fast API as the application server. So this should run here. When you open this, these GraphQL endpoint, by default, you get, if you open in the browser, you get an interface that's called graphical. And it's a graphical interface to GraphQL. And it allows you to basically explore your GraphQL schema and also try it. So for example, here, if I move all of this, I can do an operation called query. And then I can get, for example, a poll. And you can see everything is auto-completing because there's a schema. And all this information are coming from that specific schema. And you can see here, I can pass that ID. And here, you can also see all the fields that we can get for this specific object type. So for example, you can get the question. And then we can also get a list of answers. And for every single answer, I can get the text and maybe the votes. This, if I run this, this is going to go to the server. It's going to fetch the data. And let me check if I'm on the right branch. Yes. Okay. That's working. So we can see that the shape of the result is exactly the same shape of what I'm basically asking here. So if I remove for example, answer, and I run this again, it's only going to return me the question. And there's also different types here that we're going to see those later in a second. Let me just switch this. Cool. So let's see how we can implement that schema that we've seen using a server. And this is a graphical schema. And it defines everything that you have there. And if you kind of screen your eyes a bit, this kind of looks like Python data classes. So if we change type to class, it's already starting looking more like Python. And if we remove the curly braces, it's almost exactly Python, with a couple of exceptions. We're using types that don't exist in Python, like ID and string. We're also using the exclamation mark that doesn't exist. And finally, there's a bit of weird syntax there for defining the arguments. So let's fix those. So we change the types to be the ID string for the string. And then for the poll, you're actually saying it's poll or none because the default is kind of the opposite. Like in GraphQL, everything is nullable by default. And I removed the ID for now because that would make this slide a bit more complex. But we basically need to attach a Python function and it's going to read the arguments from the function. But I'll show you the code in a bit. So that's going to make more sense. And finally, we use the server type decorator to convert this class into a graphical type. And this is almost like doing a data class. If you're familiar with that, it's going to create constructors. It's going to create equality methods and things like that. But it's also going to add some metadata to the class so we can create a schema from the query. Cool. But we are here for subscription. So let me kind of talk about that. And I think it's important to mention that GraphQL supports multiple operation type. We've seen out of the query which is like this. So we have a query on the right which is, you know, I'm saying I want to fetch the poll with ID 1. And then on the left is like the schema that you would write to make this query happen. And if you're familiar with REST, queries are basically the replacement for get request. But then you also have mutations which are basically a way to do anything that side effects like creating a poll, deleting a poll and so on. Like in HTTP, you would have delete, post, put and patch. And one thing to notice here is that the syntax is basically the same. Like there is not a lot of difference. Like the main difference is the fact that on the right you're doing mutation instead of query. So I can see query here and mutation here. And this is basically telling the GraphQL server which one of the entry points you want to fetch. So instead of going from the type query, you're going through the type mutation. And this is, the fact that there is two entry points, like two operation types is because like this is telling the developers that this operation is going to do side effects. But there's also some bit of semantic differences in the actual execution of GraphQL which we're not going to go into details today. But yeah, the most interesting operation type is actually subscription, at least for this talk. And again, this is very, very similar to what we had before. So we define a field where in this case we're saying I want to fetch, I want to again update for a poll based on that ID. And then the subscription looks the same. The main difference of this is that this doesn't really return just one value. It basically returns a, I guess you can think of as a stream of values. So every time there is an update, the server is going to ping you the update back to you. Yeah. So now that we know how subscription work or at least how to implement the schema for this, let's actually think about what we should use subscription for. So there's quite a few use cases which are very interesting. There's probably more than the one I'm going to mention here. But there's also some of these use cases might be solved by other features of GraphQL that are coming soon. So we're also going to talk about the alternatives. So when you talk about WebSockets, you cannot really talk about chat apps. It's always about that. There is always a demo with chat. And yeah, WebSockets are really good. All subscriptions are really good for that because you basically need to send a, you know, sending a message and then receiving a message back. And there's this communication that's constantly happening between your client and your server. Then there's also social media feeds. For example, Twitter, if you scroll down at some point, you're going to get a bubble at the top and say, oh, there is new tweets, and that could be implemented with subscriptions. Another one is in-app notification. So you can have an app running and you can receive messages every time there is something happening somewhere else. And then the one I think it's quite cool is live data. And probably it might also be not the right thing for subscription, but we'll see that in a moment. And live data you can think of, for example, if you're watching a game, you can have the results of the game updating real time using a subscription, for example. And finally, collaborative application. This is probably, I never implemented this, but something you can definitely do with subscription. It's probably going to get complicated because you have to do conflict resolution if there's multiple people adding the same thing at the same time. Cool. Now that we know some of the use cases, and it would be interesting also to chat with you about some of the other use cases, let's see an example of subscription. So I'm going to change screen again. I've implemented a front end to this API. So you can see here I was doing some operations to create a poll, to get a poll, to vote, and also to do the subscription. And we could see all of that here, but it gets a bit boring, so I'm just going to spin up the front end and show you that. The front end is built using Next.js and React, but it doesn't matter too much because the clients, there's clients for almost any framework on like any modern front end framework. Cool. Let me refresh this. You can see I'm going to localhost 3000 slash the poll ID, and this is basically the output. It's telling the title of the question, and then it's giving you the total votes and the answers. So once I click on one of this, this is going to update, and I'm going to click multiple times so you can see that the numbers are changing. This is already quite interesting of the way it works. There's not really a line of code that's actually updating this data here. It's all done by using GraphQL, but I don't know if we will have time to see that. I think the more interesting part is to actually see a subscription in action. So this page, once it loads, is actually going to do a subscription to the server, and when there is an update, it's going to update the page automatically. So you can see here that once I click, I wait a bit of time, and it's actually updating the other page and vice versa. There's one thing to note here, you've probably seen it, that the update is actually taking a couple of seconds, and this is because I implemented this in a no optimal way, mostly because I wanted to show you how you could do polling on the server, which could be useful in some cases if you have an API that doesn't give you hooks to send messages between things. Let me show you that. As I mentioned, I'm using first API, but first API, like this is the first API is pretty limited. There's only this. I'm just setting the GraphQL up here, and then, of course, that's pretty much it. One more thing, I'm using it as DB because I wanted to try it, so if you see anything weird with how I fetch data, it's because of that, because I don't know how to use it yet. But yeah, all the important things are happening inside the schema here, so we can see that there is things that are similar to what we were discussing before, so there is a bunch of types, a query, there's also an input type, which is like an object type for receiving data, but then this is where everything actually happens, so we have a schema here, which is basically saying I'm creating a GraphQL schema with these three root types, query, mutation, and subscription. Let me start with maybe, I'll show you the poll quickly, but this is basically what we've seen at the beginning with just a couple of additional fields. The store bearer is using the type ints to basically understand what type this GraphQL field should be. This is some utility method I'm using to convert from a database result to a poll type, but that, again, doesn't matter for this one. Yeah, and then we have the query here, like you can see where things, the reason why I didn't put that into the slide because it was getting a bit messy. I'm using a different syntax than just declaring the field, I'm using the subarray field decorator on this method, which is basically saying create me a field from this method and put a, use this name and this return type as the types of the field and then use the arguments to create the GraphQL field. So if we go back to our schema here, we can see when I click on query, there is a poll with this ID, and this is very similar to what we have in Python, with the exception of self and info. Info, it's basically something that contains requests and some information about the GraphQL operation that's happening. But yeah, then I'm getting the poll from database. If there is one, I'm returning, otherwise I'm returning none. And that's pretty much what I'm doing in here. Mutation is pretty much the same. Create poll accepts an input and then it creates a poll with that input and then it returns it to our front end. And here where things get more interesting. So this is the vote function. This is what I'm calling when I click on a answer. And you can see here, apart from some weirdness I'm doing for storing the data, I'm just incrementing one counter on database and then I'm returning the poll here. And as you can see, there's nothing here really telling my server that there's been a vote happening. It's not really telling that the poll has been updated. And this is why I wanted to show you how to do a subscription using kind of polling mechanism. So here we have the subscription. The code is similar to what we've seen before. So it's accept an ID and then it returns an async generator. Async generator basically tells the server that this subscription is going to return a stream of poll. And then I'm basically doing an infinite loop and I'm trying to return a poll every two seconds. And I think this kind of pattern is quite powerful if you have something that you know it's going to update quite often but you don't have a mechanism to receive the updates. For example, we did a demo with Spotify and we were using the playback status like the song that you were playing in the current time and we didn't have a way to receive that so we were just polling the API like this. But I do have a better demo of this so let me actually switch that. So I've done a demo using Broadcaster which is a PubSub library, I think from Tom Christie if I remember correctly. And it has a very nice API and allows you to do communication between multiple things in just a few lines of code. And in this case I'm using Redis as the message queue. So it's going to when I do a vote, I'm going to send the message to Redis and then I'm going to listen for the message from Redis. So let me start that. Okay, so Redis is running. I'm going to refresh this page here while both of them. So okay. So now you can see when I click that's updating almost in real time which is much better. And it's why I guess we usually do when you work with subscription. So there is always going to be some sort of PubSub so something happens somewhere and then it sends a message to a queue and then a listener or subscriber receives that message. And in terms of the code, let me fold everything here, the mutation is almost the same with the exception of I'm getting this broadcast object from the context. And then before returning the poll, I'm actually going to publish a message to the channel saying oh, there's been an update to this poll. And the way I'm identifying the poll is just by putting the ID inside the channel. So you can only, you have subscribed or subscribed only to a specific poll change so you don't get a lot of messages. And finally in the subscription, I'm changing things a bit and I'm using again broadcast to basically subscribe to this channel and then listen to messages on the channel. And once there is a message, I'm just going to fetch the poll from the database and then return it. And this could be also optimized. Maybe I could send the whole poll via the channel but this was a quick way of doing it. Cool. And finally, the last thing I wanted to show you, how this actually works in practice. So when I go in my network tab, if I refresh this, you can see that there is a WebSocket connection being done by GraphQL. I'm going to make this a bit smaller. And you can see there are some messages here. Or maybe I put this at the bottom. It's probably easier to read. So the first thing I'm doing when I connect to a GraphQL server, I'm sending an unit to say I want to connect. Then the server responds, okay, that's fine. And finally I send the actual subscription. So here you can see I'm sending the variables and I'm sending the query which is the subscription I want to do. So this is how the server is going to know what to do. And if I click here, you can see that there is some messages coming in for the update. So you can see that there is all the data that will be asked to fetch. So this is going to happen every time there is a new update. Cool. Yeah, before talking about some other things, I think it's important to think, to talk about schema design. And schema design is something that's very important in GraphQL. Usually you wouldn't really do an API that reflects exactly what you have on your database. GraphQL is really, it really should be done as a kind of feature case driven. So if you need to do some specific thing on your front end or your client, you should create a operation dedicated to that. Because that's going to make your schema a bit more useful for your clients. And this is also quite important with subscription because subscriptions are a bit heavy on your server because they're using WebSockets. And that's the answer. If you do subscription WebSockets, there's going to be a connection to your back end. And that's going to stay alive until either the back end crashes or the front end closes the page. And that makes things a bit more difficult to scale because you cannot even use things like serverless because you have to have a connection always open. There's some kind of solution to this, like some gateways that you could use. But playing Python is not the best thing at the moment. But hopefully we can make it better. But on top of that, I think we should make sure that we have a good use case for them. For example, this poll that I showed you, does it really need to have real-time data updates? It's not a poll that a lot of people are going to work with. Or for example, like a common thing to say, well, I can make sure that on my blog post, I'm going to subscribe to every new comment. And so I get new comments immediately. But unless your blog post is quite viral, you don't really need to update things in real-time. So it definitely needs to think about, does it make sense to do a subscription for my specific use case? And I want to spend a bit of time on the alternatives. Because one thing that you could do that's a cheap way of doing real-time data or updates is having maybe polling. This is very easy to implement on the client. Because most of the libraries have just like a flag where you can say, oh, refresh this data every second. And that's going to update everything. Which is quite nice. And it works in most of the cases. But again, be careful with this, because if you have a lot of users, you're doing a lot of requests, which is not ideal in some cases. And then there is service and events. So this is an alternative protocol to WebSocket, which is a lighter weight. But unfortunately, it's not available in any Python library. So this is something I wanted to implement for this talk, but I got quite busy with other things. And I think it's going to be too difficult to implement. And this is going to make things a bit better, because you have a protocol that's lighter weight. It's going to feed more use cases, because usually when you do a subscription, you don't want to send message back and forth. You just need to have information from the server. So yeah, if you're interested in this, I'm hosting a sprint. We could chat about working on some of this. And then as an alternative, there's also defer and stream. These are quite different, a bit different from subscription, but they also are in the realm of incremental data delivery. So let's take a look at defer first. If you're not familiar with directives or GraphQL in general, the add defer is a directive. It's basically changing how the this operation should kind of behave on the server. And so what I'm saying here, I want to fetch the poll with that ID, with the ID and title. And I also want to fetch the answer, but I don't really care about the answer being present on the first response. So the server is going to send you a first response like this, and then it's going to give you the answer as soon as they're ready. And this works with using multipart and transform. So it's going to send you a stream until there's any updates. And I think this is really powerful and really useful, because this is something that you would do, maybe with two queries instead of one in your page. For example, like if you talk about the blog post, like if you have a blog post, we also want to show the comments, but the comments are less important because you usually read from the top, you read the content. And so you could say, I want to fetch the content of the blog post and the comments, but the comments can come later, so you can defer them. And then there's also the stream directive, which works in a similar way by actually saying, I want to receive a stream of these comments. So for example here, this would be the first response, and then the stream is going to keep streaming date until it's over. I haven't seen many use cases of this, like most people that I talk with are pretty excited about defer. I've seen a good use case for stream, which is creating like chat application, like chat GPT, where you send a message and then it's streaming a bunch of characters one of the time. But other than that, I haven't seen people working with this at the moment. And also one of the reasons is that this is not available in the official graphical spec, and I feel like I'm giving you bad news now. But this is being going on for, like the implementation of this in the spec has been going on for like two years, I think, or even more. But luckily, like people are starting working on this. And there is an alpha in GraphQL core, which is the library that all the Python implementation of GraphQL are using. And we did an experiment with this, and it's actually working with Strawberry, you just need to do a couple of changes. And so if you want to take a look at that, if you want to contribute it, I'll be at this point again. But yeah, this should be coming soon, which I'm really excited. And then finally, we have this other directive. I'm going to tell you already, it's not in the spec yet. But I think this is what people want its subscription to be. So this is a directive that's basically telling, I want to do this query, also when I receive updates. And so a server that's implementing this is basically going to essentially maybe a server send event stream, and it's going to give you updates every time there is an update on the pool. And I think the mechanism for sending the update is going to be the similar to what we've done with subscription, but just with a much nicer API. And again, this is not available in the spec. But it will be interesting to try and implement this and see what we can do. I haven't read the conversation on why this is not yet in the spec. There's probably something related to probably performance, because listening to a lot of things is going to be expensive. So I wanted to do a quick recap of this of how you implement the subscription using server and the broadcast library. So as we've seen before, basically when I create a subscription, I actually subscribe into a channel from this library. And then every time there's a new event, I send the data back to the user. And then in the vote, so every time there's an update, I basically publish a message on that channel. And that's going to be received by the subscription that we've seen there. And the architecture looks like this. So in my case, I'm using Redis. There's a GraphQL server that's going to receive a message from Redis sending back to the post application I've seen. And I'm using Postgres as my database, or well, HDB in this case. That's pretty much like the standard architecture of this. There's definitely some different ways of implementing this also. I do have some ideas of making some of these things better, because you could have a subscription that doesn't really have any code, because I can imagine if you do something like this quite often, we can have maybe like a different decorator that say, give me a subscription updates on this channel and return this information, for example. That's something we think I'm going to experiment next. And even here, for example, instead of having the publisher, I could have a parameter on the mutation and send a message when the mutation is done. But yeah, hopefully we get that soon. So we don't have a lot of time, exactly. We don't have a lot of time. So do you have any questions? Happy to take them. I'm going to be in the sprints as well. I'm going to be around. So definitely happy to chat about this and GraphQL in general. So thank you. Thank you, Patrick. Does anyone have any questions? No? Thanks, Patrick, for the talk. And great to see that the demo goals were with you today. Yeah, thank you. And yeah, Paikon, oh, there's a question there. Thanks for the talk, really informative. I don't know much about GraphQL, but I was wondering if you can combine queries in mutations, or do you need some sort of a client code to, for example, do a mutation for a query, or like many mutations at once, basically? Yeah, that's a very good question. So the question is if you can combine query mutation and also if you can do multiple mutations at once, right? Yes. So this is where the spec, well, there's some semantic differences between queries and the subscription. So queries, definitely you can do as many as you want. You can even fetch the same thing multiple times, maybe with an alias. And the server is going to actually execute them in parallel, while in the mutation case, it's actually going to execute one after the other, because if one fails, you probably don't want the other ones to continue happening. So you can do multiple things at once. And in terms of doing like a mutation in a query at the same time, you cannot do that. But there is a pattern of, I've seen some people doing query like this here, and this would allow you to actually also do a query while you do the mutation. I don't know if I like, but usually why you do with remutation and queries, like you return exactly the data that's needed to update the page. And especially if you use clients like Apollo client, Oracle, the fact that you use an ID and the type of the this operation, for example, let me show you this. Oh, okay. Yeah, we can chat about this in a second now. Thank you again. Right off time, we don't have time for more questions. Thank you again, Patrick.