{"id":761,"date":"2020-12-14T17:30:03","date_gmt":"2020-12-15T01:30:03","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/azure-sql\/?p=761"},"modified":"2020-12-14T17:43:25","modified_gmt":"2020-12-15T01:43:25","slug":"seasons-of-serverless-challenge-3-azure-typescript-functions-and-azure-sql-database-serverless","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/azure-sql\/seasons-of-serverless-challenge-3-azure-typescript-functions-and-azure-sql-database-serverless\/","title":{"rendered":"Seasons of Serverless Challenge 3: Azure TypeScript Functions and Azure SQL Database serverless"},"content":{"rendered":"<p><a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/banner-3.png\"><img decoding=\"async\" class=\"alignnone size-full wp-image-762\" src=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/banner-3.png\" alt=\"week 3 banner\" width=\"2134\" height=\"771\" srcset=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/banner-3.png 2134w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/banner-3-300x108.png 300w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/banner-3-1024x370.png 1024w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/banner-3-768x277.png 768w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/banner-3-1536x555.png 1536w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/banner-3-2048x740.png 2048w\" sizes=\"(max-width: 2134px) 100vw, 2134px\" \/><\/a><\/p>\n<p>Have you heard about the Seasons of Serverless challenge? Join the <a href=\"https:\/\/dev.to\/azure\/azure-advocates-seasons-of-serverless-join-our-virtual-festive-potluck-53m6\" target=\"_blank\" rel=\"noopener noreferrer\">festive virtual potluck<\/a> by creating solutions to challenges leveraging Azure serverless computing. Throughout the next seven weeks we&#8217;ll be sharing a solution to the week&#8217;s challenge that integrates <a href=\"https:\/\/docs.microsoft.com\/azure\/azure-sql\/database\/serverless-tier-overview\" target=\"_blank\" rel=\"noopener noreferrer\">Azure SQL Database serverless<\/a> with Azure serverless compute.<\/p>\n<h2>Challenge 3: The Longest Kebab \ud83d\udccf<\/h2>\n<p>The third week features the traditional &#8220;kebab&#8221; from Turkey.\u00a0 The challenge calls for quickly calculating a recipe for the kebab based on an input weight of meat. In addition to returning the recipe, we&#8217;re also interested in how many people the kebab will feed as well as how long it will be. Below is a high level view of the solution we created, utilizing an Azure Function and Azure SQL Database serverless. While the components are similar to <a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/seasons-of-serverless-challenge-1-azure-functions-and-azure-sql-database-serverless\/\">Challenge 1<\/a> where Azure Functions and Azure SQL Database serverless was leveraged to solve the challenge, we decided to write the Azure Functions for Challenge 3 in TypeScript.\u00a0 The completed example can be found on <a href=\"https:\/\/github.com\/dzsquared\/seasons-of-serverless-week3\" target=\"_blank\" rel=\"noopener noreferrer\">GitHub<\/a>.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/week3-outline.png\"><img decoding=\"async\" class=\"alignnone size-full wp-image-763\" src=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/week3-outline.png\" alt=\"Image week3 outline\" width=\"2236\" height=\"1194\" srcset=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/week3-outline.png 2236w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/week3-outline-300x160.png 300w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/week3-outline-1024x547.png 1024w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/week3-outline-768x410.png 768w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/week3-outline-1536x820.png 1536w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/week3-outline-2048x1094.png 2048w\" sizes=\"(max-width: 2236px) 100vw, 2236px\" \/><\/a><\/p>\n<hr \/>\n<h3>Azure SQL Database and Indexes for Performance<\/h3>\n<p>In challenge 1, we created an Azure SQL database with the serverless compute tier.\u00a0 In this challenge we are going to create another database in the <a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/seasons-of-serverless-challenge-1-azure-functions-and-azure-sql-database-serverless\/#creating-and-building-the-azure-sql-database\" target=\"_blank\" rel=\"noopener noreferrer\">same manner<\/a>, providing us with a serverless SQL database hosted in Azure that automatically starts, pauses and scales with our workload.\u00a0 Through the <a href=\"https:\/\/aka.ms\/azuredatastudio-sqlprojects\" target=\"_blank\" rel=\"noopener noreferrer\">SQL Database projects extension<\/a> in Azure Data Studio we are able to create a new SQL database project and the handful of database structures we need to store recipes and return the maximum length recorded.<\/p>\n<p>The table\u00a0<strong>dbo.Recipes<\/strong> will store each recipe generated and our Azure Functions will call two stored procedures:\u00a0<strong>dbo.saveRecipe\u00a0<\/strong>and\u00a0<strong>dbo.getRecord.\u00a0\u00a0<\/strong>In\u00a0<strong>dbo.getRecord<\/strong>, we will retrieve only a single record from the table\u00a0<strong>dbo.Recipes\u00a0<\/strong>after ordering the recipes by kebab lengths.<\/p>\n<pre class=\"prettyprint\">CREATE PROCEDURE [dbo].[getRecord]\r\nAS\r\nBEGIN\r\n  SELECT TOP 1 LambKilos, Onions, GarlicCloves, CuminTeaspoons, SumacTeaspoons, SaltTeaspoons,\r\n      BlackPepperTeaspoons, RedPepperTeaspoons, LengthCm, FeedsPeople\r\n  FROM Recipes\r\n  ORDER BY LengthCm DESC, Id ASC\r\nEND<\/pre>\n<p>One way to improve performance of sorting the kebab recipes and returning the longest one is to store a presorted copy of all the recipe Id&#8217;s and their lengths in our database. This is an\u00a0<em>INDEX<\/em>, and we add it to the definition of our table and specify which column(s) should be used to look up a record in the index.\u00a0 There is a great depth of information on indexes in T-SQL available, one overview of the functionality is the <a href=\"https:\/\/docs.microsoft.com\/sql\/t-sql\/statements\/create-index-transact-sql\" target=\"_blank\" rel=\"noopener noreferrer\">documentation<\/a>.<\/p>\n<pre class=\"prettyprint\">CREATE TABLE [dbo].[Recipes]\r\n(\r\n  [Id] INT NOT NULL IDENTITY(1,1) PRIMARY KEY,\r\n  LambKilos DECIMAL(14,2) NOT NULL,\r\n  Onions DECIMAL(14,2) NOT NULL,\r\n  GarlicCloves DECIMAL(14,2) NOT NULL,\r\n  CuminTeaspoons DECIMAL(14,2) NOT NULL,\r\n  SumacTeaspoons DECIMAL(14,2) NOT NULL,\r\n  SaltTeaspoons DECIMAL(14,2) NOT NULL,\r\n  BlackPepperTeaspoons DECIMAL(14,2) NOT NULL,\r\n  RedPepperTeaspoons DECIMAL(14,2) NOT NULL,\r\n  LengthCm INT NOT NULL,\r\n  FeedsPeople INT NOT NULL,\r\n  INDEX IX_Length (LengthCm DESC)\r\n)<\/pre>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/index-queryplan-light.png\"><img decoding=\"async\" class=\"alignright wp-image-775\" src=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/index-queryplan-light.png\" alt=\"Image index queryplan light\" width=\"400\" height=\"249\" srcset=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/index-queryplan-light.png 690w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/index-queryplan-light-300x187.png 300w\" sizes=\"(max-width: 400px) 100vw, 400px\" \/><\/a><\/p>\n<p>After deploying our database project in Azure Data Studio, we can check that our index is being used in the <strong>dbo<\/strong>.<strong>getRecord<\/strong> procedure by using the command &#8220;Run Query with Actual Plan&#8221; instead of &#8220;Execute Query&#8221; on a query editor with the statement <em style=\"font-size: 1rem\">EXEC dbo.getRecord<\/em>.\u00a0 The query plan shows our index, <strong style=\"font-size: 1rem\">IX_Length<\/strong>, reading a single row with an &#8220;Index Scan&#8221; and doing an inner join between the Id of that row and a key lookup (Id) of our primary key. We could have two, 200, or 2,000,000 rows in our Recipes table and the query would be reading a single row from the index and a single row from the table.\u00a0 Without the index our query would have to read every row in the Recipes table to determine which has the longest length.<\/p>\n<p>We manually created an index in our database project for this week&#8217;s challenge, but with Azure SQL database, the database engine can make and apply index recommendations for you. The serverless tier of Azure SQL database includes intelligent performance features, including Query Performance Insight and Automatic tuning.\u00a0 With <a href=\"https:\/\/docs.microsoft.com\/azure\/azure-sql\/database\/query-performance-insight-use\" target=\"_blank\" rel=\"noopener noreferrer\">Query Performance Insight<\/a> you can quickly identify and drill into the details of long-running or resource-intensive queries on your database.\u00a0 With <a href=\"https:\/\/docs.microsoft.com\/azure\/azure-sql\/database\/automatic-tuning-overview\" target=\"_blank\" rel=\"noopener noreferrer\">Automatic tuning<\/a> your database can have performance changes automatically applied, including index creation.<\/p>\n<hr \/>\n<h3>Creating TypeScript Azure Functions<\/h3>\n<p>Using the VS Code Azure Functions extension and the &#8220;Azure Functions: Create New Project&#8221; command, we&#8217;re creating a new Azure Function locally in VS Code in TypeScript with the HTTP trigger template.\u00a0 This function will receive HTTP GET requests with an amount of lamb in kilograms (kg) through a query string parameter. The body of the function is defined in the <strong>httpTrigger(context: Context, req: HttpRequest)<\/strong> function in the file <strong>index.ts<\/strong>.\u00a0 Dependencies for our function that need to be installed to run the function are detailed in the file\u00a0<strong>package.json<\/strong>, where we want to begin by adding a line for <em>mssql<\/em> under dependencies by running <em>npm install mssql<\/em> from the terminal. <a href=\"https:\/\/github.com\/tediousjs\/node-mssql\" target=\"_blank\" rel=\"noopener noreferrer\">mssql<\/a> is the package name for the open source Nodejs driver for MSSQL that enables connecting our TypeScript functions to Azure SQL Database serverless.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/function1.png\"><img decoding=\"async\" class=\"alignright wp-image-764\" src=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/function1-1024x625.png\" alt=\"Image function1\" width=\"400\" height=\"244\" srcset=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/function1-1024x625.png 1024w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/function1-300x183.png 300w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/function1-768x468.png 768w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/function1-1536x937.png 1536w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/function1.png 1600w\" sizes=\"(max-width: 400px) 100vw, 400px\" \/><\/a>We want to create 2 functions in our folder,\u00a0<strong>1<\/strong> for receiving a querystring for an amount of lamb meat and returning the recipe and another (<strong>2<\/strong>) for checking the current longest recipe recorded.\u00a0 In both functions, we are going to leverage TypeScript&#8217;s namesake &#8211; types &#8211;\u00a0 in defining classes to assist in working with the kebab recipes and length record.<\/p>\n<p>For function <strong>#1<\/strong>, the recipe calculator, we want to return a response to the user\u00a0<em>as fast as possible<\/em>. We&#8217;ll do this in 3 steps: by creating a new instance of a\u00a0<strong>KebabRecipe<\/strong>, returning this to the user in the <strong>HTTP Response<\/strong>, and finally saving the KebabRecipe to the database with the <strong>RecordRecipe<\/strong> function. By declaring a custom constructor function for the KebabRecipe class, we are able to create an instance of the recipe with a single line of code in\u00a0<em>index.ts\u00a0<\/em>and leave all the calculation of the other attributes in the class declaration in <em>recipe.ts<\/em>. The following is the custom constructor for our KebabRecipe class:<\/p>\n<pre class=\"prettyprint\">constructor(lambKilos: number) {\r\n        this.lambKilos = lambKilos;\r\n        this.onions = lambKilos \/ 2;\r\n        this.garlicCloves = lambKilos * 2;\r\n        this.cuminTeaspons = lambKilos * (3 \/ 4);\r\n        this.sumacTeaspoons = lambKilos * (3 \/ 4);\r\n        this.saltTeaspoons = lambKilos \/ 4;\r\n        this.blackPepperTeaspoons = lambKilos \/ 8;\r\n        this.redPepperTeaspoons = lambKilos \/ 8;\r\n        this.lengthCm = Math.round(lambKilos * (2.2\/4) * 12);\r\n        this.feedsPeople = Math.round(lambKilos * (2.2\/4));\r\n    }<\/pre>\n<p>We are able to set the HTTP response and call the function that sends the recipe to our serverless Azure SQL database. The key to ensuring that our user experience is a fast response on the recipe every time, regardless of how long the database access takes, is\u00a0<em>not<\/em> waiting for the\u00a0<strong>RecordRecipe()\u00a0<\/strong>function to complete before reaching the end of the\u00a0<strong>httpTrigger()<\/strong> function. Although Azure SQL is fast &#8211; there may be times when our serverless database is unpausing and we want to return the recipe to the user while the function retries the connection after the database is ready. In the screenshot of our application logs below, we see the log call for &#8220;End of function&#8221; on the 2nd line and the function&#8217;s service reports that the execution took 53ms. On the last line, timestamped 5ms later, we see the log call from the <strong>RecordRecipe()<\/strong> function.\u00a0 \u26a1<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/execution_logs.png\"><img decoding=\"async\" class=\"alignright size-full wp-image-768\" src=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/execution_logs.png\" alt=\"execution logs\" width=\"2360\" height=\"266\" srcset=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/execution_logs.png 2360w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/execution_logs-300x34.png 300w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/execution_logs-1024x115.png 1024w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/execution_logs-768x87.png 768w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/execution_logs-1536x173.png 1536w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/execution_logs-2048x231.png 2048w\" sizes=\"(max-width: 2360px) 100vw, 2360px\" \/><\/a><\/p>\n<p><em>Note: Should the storage of a generated recipe be critical information, we would consider connecting our Azure Function to a <a href=\"https:\/\/docs.microsoft.com\/azure\/architecture\/guide\/technology-choices\/messaging\" target=\"_blank\" rel=\"noopener noreferrer\">messaging service layer<\/a> as a producer, allowing data storage requests to be safely queued as subscribers.<\/em><\/p>\n<p>The full code for the Azure Function, including index.ts and recipe.ts, are available <a href=\"https:\/\/github.com\/dzsquared\/seasons-of-serverless-week3\" target=\"_blank\" rel=\"noopener noreferrer\">here<\/a>.<\/p>\n<hr \/>\n<h3>await: Retrieving the recipe for the longest kebab<\/h3>\n<p><a style=\"color: #006f94\" href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/function2.png\"><img decoding=\"async\" class=\"alignright wp-image-769\" src=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/function2.png\" alt=\"Image function2\" width=\"400\" height=\"241\" srcset=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/function2.png 761w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/function2-300x181.png 300w\" sizes=\"(max-width: 400px) 100vw, 400px\" \/><\/a><\/p>\n<p>While the Recipe function needed to return a recipe as fast as possible, we also want a user to be able to find out what is the longest Kebab Recipe generated via our application.\u00a0 Using the &#8220;Azure Functions: Create Function&#8221; command we can add another function to our project, allowing the functions to share the same Function host and application settings (like database connection details).\u00a0 The 2nd function is also a TypeScript function with an HTTP request trigger but the program flow in index.ts is more straight forward. The function cannot return results to the user until it hears back from the database what the longest kebab recipe is.\u00a0 Enter\u00a0<em>await<\/em>, which suspends subsequent execution until the called function fulfills the Promise and returns. (<a href=\"https:\/\/developer.mozilla.org\/docs\/Web\/JavaScript\/Reference\/Statements\/async_function\" target=\"_blank\" rel=\"noopener noreferrer\">async\/await<\/a> is functionality from JavaScript and <a href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/release-notes\/typescript-1-7.html#asyncawait-support-in-es6-targets-node-v4\" target=\"_blank\" rel=\"noopener noreferrer\">is available in TypeScript<\/a> as well)<\/p>\n<p>The root level function\u00a0<strong>httpTrigger<\/strong> is an\u00a0<em>async\u00a0<\/em>function, permitting utilization of the <em>await <\/em>keyword within it. We can apply the <em>await<\/em> keyword to\u00a0the <strong>KebabRecord.getRecord()<\/strong> function, where we will connect to the serverless Azure SQL database and update the KebabRecord object. In doing so, we force the function to wait for the response from the database before returning an HTTP response to the user.\u00a0 The\u00a0<strong>getRecord()\u00a0<\/strong>function is a public function in the KebabRecord class, exposing it to other modules (such as index.ts) via an import statement. There is a\u00a0<em>private<\/em> function within the KebabRecord class, a function named\u00a0<strong>connectToSQL()<\/strong> that assists our class in connecting to the Azure SQL database.<\/p>\n<pre class=\"prettyprint\">private async connectToSQL(retryCount) {\r\n    if (retryCount &lt; 10) {\r\n        try {\r\n            let pool = await mssql.connect(sqlConfig);\r\n            return pool;\r\n        } catch (err) {\r\n            console.log('retrying sql connection');\r\n            console.log(retryCount);\r\n            retryCount = retryCount + 1;\r\n            console.error(err);\r\n            await sleep(10000);\r\n            return await this.connectToSQL(retryCount);\r\n        }\r\n    }\r\n}<\/pre>\n<p>After connecting to the Azure SQL database, we can access the first (and only) row returned with the first item in the array <em>recordset.<\/em>\u00a0<em>this<\/em> refers to the calling KebabRecord object, allowing us to update its attributes (such as number of onions).\u00a0 When the function completes, it resolves the Promise and returns execution to the primary function in index.ts.<\/p>\n<pre class=\"prettyprint\">public async getRecord() {\r\n    try {\r\n        let pool = await this.connectToSQL(0);\r\n        let resultSet = await pool.request().execute('getRecord');\r\n        let outputRecord = resultSet.recordset[0];\r\n\r\n        this.lambKilos = outputRecord.LambKilos;\r\n        this.onions = outputRecord.Onions;\r\n        this.garlicCloves = outputRecord.GarlicCloves;\r\n        this.cuminTeaspons = outputRecord.CuminTeaspoons;\r\n        this.sumacTeaspoons = outputRecord.SumacTeaspoons;\r\n        this.saltTeaspoons = outputRecord.SaltTeaspoons;\r\n        this.blackPepperTeaspoons = outputRecord.BlackPepperTeaspoons;\r\n        this.redPepperTeaspoons = outputRecord.RedPepperTeaspoons;\r\n        this.lengthCm = outputRecord.LengthCm;\r\n        this.feedsPeople = outputRecord.FeedsPeople;\r\n    } catch (err) {\r\n        console.error('Failed to retrieve record from SQL database.');\r\n        console.error(err);\r\n    }\r\n}\r\n\r\n<\/pre>\n<hr \/>\n<h3>Wrapping Up<\/h3>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/application-settings.png\"><img decoding=\"async\" class=\"alignleft size-medium wp-image-777\" src=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/application-settings-300x208.png\" alt=\"Image application settings\" width=\"300\" height=\"208\" srcset=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/application-settings-300x208.png 300w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2020\/12\/application-settings.png 496w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a>We will deploy our Azure Functions into a single serverless Function App.\u00a0 This can be accomplished by the same <a href=\"https:\/\/github.com\/marketplace\/actions\/azure-functions-action\" target=\"_blank\" rel=\"noopener noreferrer\">GitHub action<\/a> for Azure Functions utilized in Challenge 1.\u00a0 One last thing &#8211; application settings.\u00a0 The connection details for our Azure SQL database were stored in the <em>local.settings.json<\/em> file in our Azure Function project and need to be input in the application settings under\u00a0<em>Configuration<\/em> on our function app.\u00a0 We have 4 individual settings, the server address, the database name, the SQL username, and the SQL password.<\/p>\n<p>&nbsp;<\/p>\n<p>With the secrets in place and the functions deployed to Azure, we are ready to test our functions from public URLs.\u00a0 The full source code from this example is available here: <a href=\"https:\/\/github.com\/dzsquared\/seasons-of-serverless-week3\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/github.com\/dzsquared\/seasons-of-serverless-week3<\/a><\/p>\n<p>For a limited time, the longest kebab API test URL is: <a href=\"https:\/\/kebab.azurewebsites.net\/api\/RecordAPI?code=3LwapFdF8mCNGOg0yXAIhvpiyqnNCdIYPN8Au28fkHTzMMnLcJ8F1Q==\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/kebab.azurewebsites.net\/api\/RecordAPI?code=3LwapFdF8mCNGOg0yXAIhvpiyqnNCdIYPN8Au28fkHTzMMnLcJ8F1Q==<\/a><\/p>\n<p>For a limited time, the URL to generate your own kebab recipe is: <a href=\"https:\/\/kebab.azurewebsites.net\/api\/RecipeAPI?code=3LwapFdF8mCNGOg0yXAIhvpiyqnNCdIYPN8Au28fkHTzMMnLcJ8F1Q==&amp;lamb=2\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/kebab.azurewebsites.net\/api\/RecipeAPI?code=3LwapFdF8mCNGOg0yXAIhvpiyqnNCdIYPN8Au28fkHTzMMnLcJ8F1Q==&amp;lamb=2<\/a> (don&#8217;t forget to update the query string to the amount of lamb you have available in kilograms)<\/p>\n<p>Just a reminder&#8230; <strong>Since both our compute and database are serverless, our costs are minimized when there is no workload.\u00a0 For the database, we are only charged for storage when the database is paused.\u00a0 Next time you need a database for your serverless architecture, consider Azure SQL database serverless.\u00a0 <\/strong><\/p>\n<p>See you next week for our solution to <a href=\"https:\/\/github.com\/microsoft\/Seasons-of-Serverless\/blob\/main\/Dec-14-2020.md\" target=\"_blank\" rel=\"noopener noreferrer\">Challenge 4: A Big Barbecue<\/a>!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Throughout the next seven weeks we&#8217;ll be sharing a solution to the week&#8217;s Seasons of Serverless challenge that integrates Azure SQL Database serverless with Azure serverless compute. Learn how to develop an Azure Function that leverages Azure SQL database serverless and TypeScript with Challenge 3 of the Seasons of Serverless challenge.<\/p>\n","protected":false},"author":46830,"featured_media":762,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1,430],"tags":[],"class_list":["post-761","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure-sql","category-javascript"],"acf":[],"blog_post_summary":"<p>Throughout the next seven weeks we&#8217;ll be sharing a solution to the week&#8217;s Seasons of Serverless challenge that integrates Azure SQL Database serverless with Azure serverless compute. Learn how to develop an Azure Function that leverages Azure SQL database serverless and TypeScript with Challenge 3 of the Seasons of Serverless challenge.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts\/761","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/users\/46830"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/comments?post=761"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts\/761\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/media\/762"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/media?parent=761"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/categories?post=761"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/tags?post=761"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}