Resonate TypeScript quickstart tutorial • Part 2
In Part 2 of the tutorial, you will connect your service to a Resonate Server to enable recovery from platform-level failures.
To simulate a platform-level failure, you will kill the HTTP server process in the middle of the execution of the downloadAndSummarize()
function.
Prerequisites
This part of the tutorial assumes you have NodeJS and npm installed and that you have completed Part 1 and already have the service built.
Install the Resonate Server
Follow the steps in the Resonate Server install guide to install and run the server on your machine.
By default, the Server runs on localhost port 8001.
After the server is running, you can update your service code.
Update your code
There are three places where you need to update your code for this nex part of the tutorial.
First, in your gateway.ts
file, update the new Resonate()
call and provide it with the URL of the server, in this case http://localhost:8001
.
docs/get-started/typescript-quickstart/part-2/code/src/gateway.ts
// Initialize a Resonate application.
const resonate = new Resonate({ url: "http://localhost:8001" });
Then, extend the top-level promise resolution timeout to a full minute.
docs/get-started/typescript-quickstart/part-2/code/src/gateway.ts
// Register a function as a Resonate function
resonate.register(
"downloadAndSummarize", // function name
downloadAndSummarize, // function pointer
resonate.options({ timeout: 60000 }) // set a total execution timeout of 1 minute
);
You are increasing the top-level promise resolution timeout to a full minute so that you have time to kill the service and bring it back up again.
And finally, in your app.ts
file add a 10 second sleep to the downloadAndSummarize()
function between download()
and summarize()
.
docs/get-started/typescript-quickstart/part-2/code/src/app.ts
export async function downloadAndSummarize(ctx: Context, url: string) {
console.log("Downloading and summarizing content from", url);
// Download the content from the provided URL
let content = await ctx.run(download, url);
// Sleep for 10 seconds
await ctx.sleep(10000);
// Summarize the downloaded content
let summary = await ctx.run(summarize, content);
// Return the summary of the content
return summary;
}
You are adding a 10 second sleep so that you have time between the download()
step and the summarize()
step so that you have time to kill the service before the summarize()
step starts.
Now that you have your code updated, it is time to simulate a service outage.
Simulate a crash
If you haven't already, restart your HTTP service with the updated code.
npm start
After your service is running with the updated code, send the POST
request to your service.
curl -X POST http://localhost:3000/summarize -H "Content-Type: application/json" -d '{"url": "http://example.com"}'
Let it run it until you see that the log "download successful", then kill (Ctrl-c) the service.
Because you are using cURL from another terminal, you will get "received". In Part 1 of the tutorial, killing the HTTP service would have resulted in the loss of the state of the executions. However, because the service is connected to the Resonate Server, when you bring the service back up, the execution sequence continues from where it left off.
Start the service again.
Assuming that you stopped the service after the download()
function ran, you should now see the summarize()
function logs and the application complete its execution.
Lets, look at the sequence diagram to understand what happened.
In the diagram above, you can map function 1 to downloadAndSummarize()
, function 2 to download()
, and function 3 to summarize()
.
Notice how function 1 gets the result of function 2 from the Durable Promise after the process restarts.
That is because the result of function 2 was stored in promise 2 before the process crashed.
This effectively resumes the execution of function 1 from where it left off.
Next, you will inspect the promise in the Resonate Server to see that it resolved successfully.
Inspect promises
You can inspect the promises stored in the Resonate Server via the Resonate CLI.
resonate promise get summarize-http://example.com
You should see output similar to the following:
Id: summarize-http://example.com
State: RESOLVED
Timeout: 9008909898871320
Idempotency Key (create): summarize-http://example.com
Idempotency Key (complete): summarize-http://example.com
Param:
Headers:
Data:
{"func":"downloadAndSummarize","args":["http://example.com"]}
Value:
Headers:
Data:
"This is a summary of the text"
Tags:
resonate:invocation: true
Try out your app again with another url (to create a new promise with a different ID). Then, kill the HTTP service halfway through execution. Query for the promise in the Resonate Server and check out the status.
You should see that the promise is marked PENDING
.
Bring your HTTP service back up and and then query for the promise again.
It should be marked RESOLVED
.
So, now you should have a good understanding of how to use the Resonate SDK and the Resonate Server to build a distributed async await applications!