0:00 All right, so in this lecture, we wanna create our last service for use 0:03 inside 0:04 of our order workflow, and that is going to be the mail 0:07 service. We're gonna use this service to actually 0:11 email the 0:11 user at the end of our workflow once the order has actually 0:15 been delivered. And this is gonna be a really nice example because 0:19 we're gonna see how we can actually have the workflow wait 0:23 up until the order is delivered to actually invoke this 0:27 email. 0:27 So we'll go ahead and create the new mail service, 0:30 which will just 0:31 be a NestJS injectable class. Go 0:35 ahead and export class MailService. 0:38 And normally, we would use a external email 0:42 provider, an SMTP server, to actually send the email. 0:45 In this example, we are going to just insert a record into the 0:49 database to represent the email being sent, which will also 0:53 utilize our idempotency. So for this, we need to add our 0:57 constructor where we use our injectDrizzle 1:00 decorator 1:02 to go ahead and inject the database 1:06 instance. Next up, we'll have the async 1:09 sendReviewRequest method. 1:13 This will get passed in the underlying order that we're trying to send a 1:16 review request for. So after the order gets delivered, 1:20 that's when 1:20 we wanna mail the user and ask them to review the product. 1:24 So let's go ahead and import the order type, as well 1:28 as the idempotency key, just like any other step as part of our 1:32 workflow. This can be retried if it did fail. 1:36 And we'll return promise void. Now, I wanna also add 1:40 a logger to our mail service, so we can log out when it is invoked. 1:45 So we'll give this a mail prefix. And now let's go ahead 1:49 and insert into the database 1:52 this.db.insert into the emails table that we 1:56 created from our schema. Make sure we import Type 2:00 Emails and Type Database again. Make sure we import 2:04 our Type Order and Type Database to work with Bun as well. 2:09 And now we're going to use .values and 2:12 output the data for the email we're inserting. 2:16 So for the ID, we're gonna pass through the idempotency 2:19 key, just like we've used 2:20 this pattern before. Remember, inside of the actual order 2:24 schema, we are marking the ID for the emails table 2:28 as the primary key, so there can only ever be one of these, 2:31 and that's 2:31 why we can use the idempotency key here. 2:34 If one already exists, this will not succeed. 2:38 And so we'll mark the two as the order.userId, 2:41 and the subject will say, 2:44 just say, "How was order," 2:47 pass through the order ID, 2:49 and ask them to leave a review as an example. 2:53 So now we've inserted the new email into the database. 2:56 This can also be where you would reach out to an external email 3:00 provider to actually email the user. 3:03 We will use onConflictDoNothing to respond to 3:07 any duplicates. If we've already emailed the user, 3:09 we don't have to do it again. 3:12 And finally, return back the inserted email. 3:16 We'll check to see if inserted.length is greater than zero. 3:20 This means we did send the email. And we'll log to 3:23 the local logger and say, "Sent review 3:28 request for order order.id 3:33 to order.userId." 3:36 And now we have the ability to send a review request, which is excellent, and 3:40 it's ready for use inside of the workflow. 3:43 I'll add this to the providers array as well, the mail 3:46 service. Our server is still up and running, and now we're ready to 3:50 finally use all of these services inside of our order workflow and 3:54 see how this works end-to-end. Let's go ahead and create the order 3:57 workflow 3:58 next.