Hey there, this is Sebastian from 8base. Today, we're going to be walking through how you can detect, disconnect, reconnect and connect events in your 8base serverless functions. Cool. We're going to dive right into this and talk about what it means, what we're trying to accomplish and then relate it all together.
The first thing is, what does it mean to detect an event type or a trigger type in a serverless function? If I go over here to my PS code, and I open up my APIs or YAML file, this is just a server or functions directory that I initiated using the 8base Command Line tool.
I have trigger functions, so I can essentially create functions that run either before or after a certain database event, like a create update or delete event. Now, that said, we know that we can write a mutation in 8base, for example, mutation.
In this workspace, we have a table called tasks. For example, we can create a task, we can delete a task, we can update a task. These types of events are really easy for us to detect. We create a trigger that runs after or before a create event, and we have a very clear concept of when that's going to run.
However, what is unique or cool about the 8base API is that you can do relational based updates, creates, reconnects, disconnects, all these types of things. For example, if I want to create a task and give this task a title of... Let me go back here really quick, give it a title of My New Task.
In doing so, I can, while creating it, connect it to an existing list table, which is another table in my workspace, or create a whole new table, which is a list table as well. Now, in doing that, we may want to detect those events to trigger certain types of server side code. Essentially what we're going to show here is how you can accomplish that inside your projects.
With that laid out, we're going to jump back into my IDE here to just show a little bit of the set up I did to help demonstrate this point and see actually some of the tools that you have when working with 8base of investigating how things work.
I've created four trigger functions in this project. Essentially, they are trigger functions that run all of them after a update or create happens on the tasks table and the lists table. After a task is created, after a task is updated, after a list is created, after a list is updated.
All these functions pretty much have the exact same code in them. When they run, they essentially console log out a statement which says what they're doing, so after list create, and then they stringify, or they print out the JSON, which is passed to the function in the event argument.
I've already deployed these to the workspace. These functions are already live in this workspace here. However, they've never been run, so there's no logs yet. Why am I doing this? Doing this so that we are going to run an API request that demonstrates a connect. Yeah, we'll do a connect event and then we'll see the data that gets passed to that function.
Let's go into our data model here. We have lists and tasks, and a list has many tasks. Makes sense? What we're going to do is we're going to go look at these lists and get the ID of... Actually, we're just going to get the name of this list. Important work stuff, that's the list. What we're going to do now is we're going to create a new task.
We're going to write mutation which is a task create, and the data for this task is going to be... The title of it is going to be, edit the new videos, and the description for it's going to be, make sure the audio is clean in the new videos, all right. Now, that's the task.
Now, we want to connect it to this existing list. So we're going to open that up, the list relationship, and then say that we're going to do a connection, and we're going to connect it to a list which has the name, important work stuff. Cool.
Now, we are going to, in here, make sure that we get back the ID of the task, the title of the task, the description of the task, and then also the list ID and name. Awesome. We have this mutation written out, let's go ahead and run it. So that worked. We got a response back as expected and this new task was created and it was connected to the list.
Let's see now the data that actually got passed to our serverless function that runs after the task create event. If I go to my functions, we can look at the logs for each one. We see that list create didn't trigger, list update did not trigger, task update did not trigger, but when we go to task create, let's reload the page.
Awesome. That's still true for all those other ones that we've just walked through. Yeah, perfect. So task ran, and this was the data that was passed to that function. I'm going to open up a JSON Pretty, just so we can make this JSON look a little bit better. Make pretty. Cool. What I'll do is I'll actually just copy this, bring it in here, and create a... Whoa, I got a lot of files. I got to X out of there. Cool.
JSON and drop that in there. Awesome. This shows all the data that was passed to that after function as the event argument. Now, what's important about that is since it was passed to the function and we logged out, that means that any of this data is usable for any type of business logic that you want to write, or any type of script that you want to write.
We can see that it gave us I think four keys. Yeah, four keys in that object, so the data key, and for specifically an after trigger or a trigger function that runs on the after event, it's going to give you the whole record. We saw this is the whole task that was created.
It's going to give you the original data that was passed to the operation. This is the important one here. This is where we're actually seeing that it's giving us the list argument in the original data, which has the connect key in there. That's going to be our clue for detecting these events. Because if it was a reconnect, it would be the same thing and disconnect the same thing.
The original object, since it was a create operation, there was no original object. If it was an update, the object or the original task would have been there before it was updated, as well as then just a bunch of headers. They're not relevant to us right now, but it could be relevant to you. Cool.
Inside here, what's really important now is we know that, okay, well, if we submit a task create operation and we are connecting it or disconnecting it, or in this case you'd be connecting it or creating a list through that operation, we can look for original data list connect to detect that event. If I went back into my task, that was task create, right? Yeah, task create. Task create function here, I now know that inside of here, if I wanted to take that event, I could say, "Okay, well, if event.original data list."
First off, we just see if that's there. I forgot the fancy syntaxes like that or like that. I forgot how to write that. I don't like that syntax that much either, so I won't try. But if we drop that in there, and then we say connect, we can then update this to say, once again, console log. A connect happened. Inside of that connect event, we can see, as well, that we have the data, so it connected it to that list name or any other data that would have been supplied to the function.
Once again, we can repeat this pattern in here for each type of event that we're looking to detect, as well as in different functions or different events where we want to detect those events. This could be really valuable in the sense of, let's say that when a new user is connected to a new record in the database, you want to send them an email about something. This would be a really straightforward way of approaching that moment in time or that point in that lifecycle of the operation, that you need to trigger that email, that task, whatever it might be.
Now, the other thing that I wanted to point out here is that these functions also will... When you submit one operation, it will potentially trigger multiple functions. What do I mean by that? If we go back to our API Explorer here, we now know that we have this task here. Let's write a new mutation, where we're updating a list.
We're going to update one of our lists. Actually now I'm going to go and steal the ID of one of the lists. I'm just going to get the ID of the important work stuff list and go back to our API Explorer. Now let me list update data and in here, we're going to update that list. Okay, how are we going to update it?
Let's just update the name to be most important work stuff, and then after that, we are going to go into the tasks and we're actually going to run a disconnect on the tasks, and that disconnect operation, we're going to disconnect the record with the ID.
I'm going to run that and I don't think it will delete. I'm just going to save it on a notepad really quick. Cool. Just so I don't lose it in case it resets. We're going to go into here. We're going to go into our tasks and edit the new videos. Belongs to that right list. Cool. We're going to take that ID, API Explorer. It did delete it. Good thing I copied it over there. Got it. Cool.
We're going to disconnect the task that has this ID, and then we are going to, at the same time, create a new task which is called make important phone call, and the description is going to be, you know what you're talking about. Cool. Now for those, we then just want back the ID, the name of the list, and then the tasks, how many tasks there are. This isn't important but just throwing it all in there, and the title of these tasks. Okay, cool.
We're going to be running a list update event. That means that our after list update trigger will fire and we will go and then see what data has been passed to that one. However, we're also running a disconnect and we're also running a create. What will be cool to see is that this create input here after running the list update will actually be passed to the task create operation, and we'll see that reflected in the console statement.
The one thing I would do last here, I almost forgot, is say force equals true. The reason we're doing that is because in disconnecting the task, and there's a mandatory relationship between the tasks table and the list table, which means that no task cannot belong to a list. Actually what I'm going to do is I'm going to run it without the force flag and we'll see that it should give us an error.
Yeah. Attempted to destroy a required relationship, rerun the mutation with the force flag to try to force delete the related objects. By running with the force flag, I'm actually deleting that last task that we just generated, because it can't exist in the database without a list relationship. I run it like that. Boom. The update has been made, and then now we have our two tasks that are updated.
Now, I go back to my functions and we still haven't run a list create operation, so [inaudible 00:14:46] reload the logs. We're good there. After the list is updated, this one now ran for the first time. Once again, we're going to take the data here and throw it into this little print Pretty thing. Cool.
We see that the data of the list is being passed here. This is the most up to date list data. Now, the original data that we passed to the operation is the ID, the name, and then the disconnect operation as well as the create operation. Once again, we could detect whether or not we were creating a task through a update, as well as if we were disconnecting. The same way that we did it in task create, we could do it in after list update.
I'm just going to drop in. Once again, you get more sophisticated in the way that you approach your syntax of saying how you're detecting whether the event exists in there, but so if original data, tasks. I think it's tasks. Yep, tasks, and then inside of there, we are looking for if there's a disconnect, where we're looking for if there is a tasks create. These would be separate events. So if that do that, if that, let's say a connect happened, a disconnect happened and a create happened.
Once again, diving into the code and making sure that based on the incoming data, we are identifying what's going on and responding to it as we need to. Then finally here, the original object. Since we were updating the list, we can see that this is its old title under the original object, and this is its updated title. If we wanted to do some type of... Whatever you want to do using that information, you have that information to use, and that's the important part.
Once we know that, we then remember, oh, okay. Well, this data here, that was the create input, got passed to the task create operation, which now if we go to the after task create function, we can see that it was passed to here as well. Once again, we take this, we drop it in here, make it pretty. I'm going to pull it back into this code here. Cool.
Now, here we see, okay, well, this was the data that was passed to the function input, and the reason why there's this extra data here is because this is default data. On the schema, it said that by default the priorities is low in status to do those things.
The original data which we're seeing that, okay, well the original data was recreating a task and it's being connected to a list, and it was not a new list, so it's giving us a little bit more metadata in there, as well as the original object which there was none because there was a create event, and of course, the headers as well.
I hope that you found this video helpful in giving you a better understanding of some of the tools that you have at your disposal when developing serverless functions on 8base, and the different ways that you can play with the system to do this type of event detection.
It's in our roadmap to actually add some of these event types as native event triggers, similar to how in our function we were declaring, oh, after a create, update or delete event, you could actually just specify after a reconnect, disconnect or connect event, and so on and so forth.
In the meantime, and even actually when those events come out, it's still really important to understand the ways that you could navigate these things because so many different use cases pop up where things like this are relevant.
Also one more tip in here that you can do, is by deploying a function like the ones that we did that console log out an argument, you can then take that JSON or that event argument, and use that as your mock in your local functions. Some of these things I'm referencing I'm going to add description links in the video description so you can investigate them further. However, happy developing, and looking forward to seeing you in subsequent videos.