Post

Azure Function Storage Queue Trigger Node.js Tutorial

Azure Functions are made up of a trigger, and may also include input and output bindings for reading and writing data.

In this tutorial, we will write an Azure Function using Node.js using an Azure Storage Queue as the trigger that uses Azure Blob Storage with input and output bindings to read in a file to copy it to a different location in an Azure Storage container.

We will make use of Terraform to automate the provisioning of the Azure Resources we need.

This content is available in video form on the Cloud Engineer Skills YouTube channel.

Terraform main.tf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# We strongly recommend using the required_providers block to set the
# Azure Provider source and version being used
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "=3.110.0"
    }
  }
}

# Configure the Microsoft Azure Provider
provider "azurerm" {
  features {
    resource_group {
      prevent_deletion_if_contains_resources = false
    }
  }
}

resource "azurerm_resource_group" "rg" {
  name     = "ces-af-terraform-rg"
  location = "West US 2"
  tags = {
    environment = "dev"
    source = "terraform"
    owner = "cloudengineerskills"
  }
}

resource "azurerm_storage_account" "func_storage" {
  name                     = "cloudengineerskillstfsa"
  resource_group_name      = azurerm_resource_group.rg.name
  location                 = azurerm_resource_group.rg.location
  account_tier             = "Standard"
  account_replication_type = "LRS"
    tags = {
    environment = "dev"
    source = "terraform"
    owner = "cloudengineerskills"
  }
}

resource "azurerm_storage_queue" "storage_queue" {
  name                 = "copyblobqueue"
  storage_account_name = azurerm_storage_account.func_storage.name
}

resource "azurerm_storage_container" "storage_container" {
  name                 = "helloworld"
  storage_account_name = azurerm_storage_account.func_storage.name
}

resource "azurerm_service_plan" "func_consumption_plan" {
  name                = "cloudengineerskillstfconsumptionplan"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location
  os_type             = "Linux"
  sku_name            = "Y1"
  tags = {
    environment = "dev"
    source = "terraform"
    owner = "cloudengineerskills"
  }
}

resource "azurerm_log_analytics_workspace" "logs" {
  name                = "workspace-test"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  sku                 = "PerGB2018"
  retention_in_days   = 30

  tags = {
    environment = "dev"
    source = "terraform"
    owner = "cloudengineerskills"
  }
}

resource "azurerm_application_insights" "insights" {
  name                = "tf-test-appinsights"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  workspace_id        = azurerm_log_analytics_workspace.logs.id
  application_type    = "Node.JS"

  tags = {
    environment = "dev"
    source = "terraform"
    owner = "cloudengineerskills"
  }
}

resource "azurerm_linux_function_app" "func_app" {
  name                = "cloudengineerskillstffuncapp"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location

  storage_account_name       = azurerm_storage_account.func_storage.name
  storage_account_access_key = azurerm_storage_account.func_storage.primary_access_key
  service_plan_id = azurerm_service_plan.func_consumption_plan.id

  site_config {
    application_stack {
      node_version = 20
    }

    application_insights_connection_string = azurerm_application_insights.insights.connection_string
    application_insights_key = azurerm_application_insights.insights.instrumentation_key
  }

  app_settings = {
    "STORAGE_ACCOUNT_CONNECTION_STRING" = azurerm_storage_account.func_storage.primary_connection_string
  }

  tags = {
    environment = "dev"
    source = "terraform"
    owner = "cloudengineerskills"
  }
}

Node.js Azure Function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const { app, input, output } = require("@azure/functions");

// input binding: message from the storage queue replaces {queueTrigger} text in the path
const blobInput = input.storageBlob({
  connection: "STORAGE_ACCOUNT_CONNECTION_STRING",
  path: "helloworld/{queueTrigger}",
});

// output binding: message from the storage queue replaces {queueTrigger} text in the path
const blobOutput = output.storageBlob({
  connection: "STORAGE_ACCOUNT_CONNECTION_STRING",
  path: "helloworld/{queueTrigger}-copy",
});

// trigger
app.storageQueue("storageQueueCopyBlob", {
  queueName: "copyblobqueue",
  connection: "STORAGE_ACCOUNT_CONNECTION_STRING",
  extraInputs: [blobInput],
  extraOutputs: [blobOutput],
  handler: (queueItem, context) => {
    context.log("Storage queue function processed work item:", queueItem);
    const blobInputValue = context.extraInputs.get(blobInput);
    context.extraOutputs.set(blobOutput, blobInputValue);
  },
});
This post is licensed under CC BY 4.0 by the author.