Примеры Azure Functions

Примеры Azure Functions бессерверных вычислений с HTTP-триггерами, таймерами и интеграциями

💻 Функция HTTP Trigger javascript

🟢 simple

Базовая Azure Function с HTTP trigger для REST API endpoints

⏱️ 10 min 🏷️ azure, functions, serverless, http, api
Prerequisites: Azure account, Azure Functions Core Tools, Node.js basics
// Azure Functions HTTP Trigger Example
// JavaScript (Node.js) - function.json + index.js

// function.json - Function configuration
{
  "scriptFile": "index.js",
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    }
  ]
}

// index.js - Function implementation
module.exports = async function (context, req) {
    context.log('HTTP trigger function processed a request.');

    const name = req.query.name || (req.body && req.body.name);
    const responseMessage = name
        ? "Hello, " + name + ". This HTTP triggered function executed successfully."
        : "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.";

    context.res = {
        status: 200,
        body: responseMessage
    };
};

// TypeScript version
// index.ts
import { AzureFunction, Context, HttpRequest } from "@azure/functions"

const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
    context.log('HTTP trigger function processed a request.');

    const name = req.query.name || (req.body && req.body.name);
    const responseMessage = name
        ? "Hello, " + name + ". This HTTP triggered function executed successfully."
        : "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.";

    context.res = {
        status: 200,
        body: responseMessage
    };
};

export default httpTrigger;

💻 Функция Timer Trigger csharp

🟢 simple ⭐⭐

Запланированная Azure Function, запускаемая таймером для фоновых задач

⏱️ 15 min 🏷️ azure, functions, timer, scheduler, durable
Prerequisites: Azure account, C# basics, Understanding of cron expressions
// Azure Functions Timer Trigger Example
// C# - TimerTrigger.cs

using System;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Extensions.Logging;

public static class TimerTriggerFunction
{
    [FunctionName("TimerTriggerFunction")]
    public static void Run(
        [TimerTrigger("0 */5 * * * *")] TimerInfo myTimer,
        ILogger log,
        [DurableClient] IDurableClient starter)
    {
        log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");

        if (myTimer.IsPastDue)
        {
            log.LogInformation("Timer is past due!");
        }

        // Start a new orchestration for cleanup task
        string instanceId = starter.StartNewAsync("CleanupOrchestration", null).Result;
        log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
    }
}

[FunctionName("CleanupOrchestration")]
public static async Task RunOrchestrator(
    [OrchestrationTrigger] IDurableOrchestrationContext context,
    ILogger log)
{
    log.LogInformation("Starting cleanup orchestration...");

    // Clean up old files
    await context.CallActivityAsync<string>("DeleteOldFiles", null);

    // Send notification
    await context.CallActivityAsync<string>("SendCleanupNotification", null);

    log.LogInformation("Cleanup orchestration completed.");
}

[FunctionName("DeleteOldFiles")]
public static string DeleteOldFiles([ActivityTrigger] string input, ILogger log)
{
    log.LogInformation("Deleting old files...");
    // Implementation for file cleanup
    return "Old files deleted successfully";
}

[FunctionName("SendCleanupNotification")]
public static string SendCleanupNotification([ActivityTrigger] string input, ILogger log)
{
    log.LogInformation("Sending cleanup notification...");
    // Implementation for notification
    return "Notification sent successfully";
}

💻 Функция Queue Trigger python

🟡 intermediate ⭐⭐⭐

Azure Function, запускаемая сообщениями Azure Queue Storage

⏱️ 20 min 🏷️ azure, functions, queue, storage, python
Prerequisites: Azure Storage account, Python basics, Understanding of message queues
# Azure Functions Queue Trigger Example
# Python - __init__.py + function.json

# function.json
{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "name": "msg",
      "type": "queueTrigger",
      "direction": "in",
      "queueName": "myqueue-items",
      "connection": "MyStorageConnectionAppSetting"
    },
    {
      "name": "outputQueueItem",
      "type": "queue",
      "direction": "out",
      "queueName": "outqueue",
      "connection": "MyStorageConnectionAppSetting"
    }
  ]
}

# __init__.py
import logging
import json
import azure.functions as func
from azure.storage.blob import BlobServiceClient

def main(msg: func.QueueMessage, outputQueueItem: func.Out[func.QueueMessage]) -> None:
    """Process queue message and store result in blob storage."""

    logging.info('Python queue trigger function processed a queue item.')

    # Parse incoming message
    try:
        message_body = json.loads(msg.get_body())
        order_id = message_body.get('orderId')
        customer_email = message_body.get('customerEmail')

        logging.info(f'Processing order {order_id} for customer {customer_email}')

        # Process the order (business logic)
        processed_order = process_order(message_body)

        # Store result in blob storage
        blob_client = get_blob_client()
        blob_name = f"orders/{order_id}.json"
        blob_client.upload_blob(blob_name, json.dumps(processed_order), overwrite=True)

        # Send output message
        output_message = {
            'orderId': order_id,
            'status': 'processed',
            'processedAt': datetime.now().isoformat(),
            'blobUrl': f"https://yourstorage.blob.core.windows.net/yourcontainer/{blob_name}"
        }

        outputQueueItem.set(json.dumps(output_message))

        logging.info(f'Successfully processed order {order_id}')

    except Exception as e:
        logging.error(f'Error processing message: {str(e)}')
        raise

def process_order(order_data):
    """Example order processing logic."""
    # Add processing timestamp
    order_data['processedAt'] = datetime.now().isoformat()
    order_data['status'] = 'processed'

    # Calculate total with tax
    subtotal = order_data.get('subtotal', 0)
    tax_rate = 0.08
    tax = subtotal * tax_rate
    total = subtotal + tax

    order_data.update({
        'tax': round(tax, 2),
        'total': round(total, 2)
    })

    return order_data

def get_blob_client():
    """Initialize blob service client."""
    # In production, use connection string from environment variables
    connection_string = os.environ['AzureWebJobsStorage']
    blob_service_client = BlobServiceClient.from_connection_string(connection_string)

    container_name = "processed-orders"
    # Create container if it doesn't exist
    blob_service_client.create_container(container_name)

    return blob_service_client.get_blob_client(container=container_name)

💻 Интеграция Cosmos DB javascript

🟡 intermediate ⭐⭐⭐

Azure Function с привязками ввода и вывода Cosmos DB

⏱️ 25 min 🏷️ azure, functions, cosmosdb, database, nosql
Prerequisites: Azure Cosmos DB account, JavaScript basics, Understanding of NoSQL databases
// Azure Functions Cosmos DB Integration
// JavaScript - function.json + index.js

// function.json
{
  "scriptFile": "index.js",
  "bindings": [
    {
      "authLevel": "function",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    },
    {
      "type": "cosmosDB",
      "direction": "out",
      "name": "outputDocument",
      "databaseName": "Tasks",
      "collectionName": "Items",
      "createIfNotExists": true,
      "partitionKey": "/id",
      "connectionStringSetting": "CosmosDBConnection"
    },
    {
      "type": "cosmosDB",
      "direction": "in",
      "name": "inputDocuments",
      "databaseName": "Tasks",
      "collectionName": "Items",
      "sqlQuery": "SELECT * FROM c WHERE c.status = 'pending' ORDER BY c.createdAt DESC",
      "connectionStringSetting": "CosmosDBConnection"
    }
  ]
}

// index.js
const { v4: uuidv4 } = require('uuid');

module.exports = async function (context, req) {
    context.log('JavaScript HTTP trigger with Cosmos DB bindings processed a request.');

    try {
        const task = {
            id: uuidv4(),
            title: req.body.title,
            description: req.body.description,
            status: 'new',
            priority: req.body.priority || 'medium',
            createdAt: new Date().toISOString(),
            createdBy: req.body.userId || 'anonymous'
        };

        // Set the output document to be saved to Cosmos DB
        context.bindings.outputDocument = task;

        // Get pending tasks from input binding
        const pendingTasks = context.bindings.inputDocuments || [];

        const response = {
            success: true,
            message: "Task created successfully!",
            createdTask: task,
            pendingTasksCount: pendingTasks.length,
            pendingTasks: pendingTasks.slice(0, 5) // Return first 5 pending tasks
        };

        context.res = {
            status: 201,
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(response)
        };

    } catch (error) {
        context.log.error('Error creating task:', error);

        context.res = {
            status: 500,
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                success: false,
                error: "Failed to create task",
                message: error.message
            })
        };
    }
};

// Additional functions for task management

// Update task function
{
  "scriptFile": "updateTask.js",
  "bindings": [
    {
      "authLevel": "function",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": ["put"],
      "route": "tasks/{id}"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    },
    {
      "type": "cosmosDB",
      "direction": "in",
      "name": "existingTask",
      "databaseName": "Tasks",
      "collectionName": "Items",
      "id": "{id}",
      "partitionKey": "{id}",
      "connectionStringSetting": "CosmosDBConnection"
    },
    {
      "type": "cosmosDB",
      "direction": "out",
      "name": "updatedTask",
      "databaseName": "Tasks",
      "collectionName": "Items",
      "createIfNotExists": false,
      "partitionKey": "/id",
      "connectionStringSetting": "CosmosDBConnection"
    }
  ]
}

// updateTask.js
module.exports = async function (context, req) {
    context.log('Updating task:', req.params.id);

    const existingTask = context.bindings.existingTask;

    if (!existingTask) {
        return {
            status: 404,
            body: { error: "Task not found" }
        };
    }

    // Update task properties
    const updates = {
        ...existingTask,
        ...req.body,
        updatedAt: new Date().toISOString(),
        updatedBy: req.body.userId || 'anonymous'
    };

    context.bindings.updatedTask = updates;

    return {
        status: 200,
        body: {
            success: true,
            message: "Task updated successfully!",
            task: updates
        }
    };
};

💻 Оркестрация Durable Functions csharp

🔴 complex ⭐⭐⭐⭐⭐

Сложный бизнес-процесс с использованием Azure Durable Functions для рабочих процессов с состоянием

⏱️ 45 min 🏷️ azure, functions, durable, orchestration, workflow, complex
Prerequisites: Advanced Azure Functions knowledge, C# async/await patterns, Understanding of compensation patterns
// Azure Durable Functions Orchestration Example
// C# - Order Processing Workflow

using System;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Extensions.Logging;

namespace OrderProcessing
{
    // Orchestrator function - Coordinates the entire workflow
    public static class OrderProcessingOrchestration
    {
        [FunctionName("ProcessOrder")]
        public static async Task<OrderResult> RunOrchestrator(
            [OrchestrationTrigger] IDurableOrchestrationContext context,
            ILogger log)
        {
            var order = context.GetInput<OrderRequest>();
            log.LogInformation($"Starting order processing for Order ID: {order.OrderId}");

            // Step 1: Validate order
            var validationResult = await context.CallActivityAsync<ValidationResult>(
                "ValidateOrder", order);

            if (!validationResult.IsValid)
            {
                return new OrderResult
                {
                    OrderId = order.OrderId,
                    Status = "Failed",
                    ErrorMessage = validationResult.ErrorMessage
                };
            }

            // Step 2: Check inventory
            var inventoryCheck = await context.CallActivityAsync<InventoryCheckResult>(
                "CheckInventory", order);

            if (!inventoryCheck.IsAvailable)
            {
                return new OrderResult
                {
                    OrderId = order.OrderId,
                    Status = "Failed",
                    ErrorMessage = "Insufficient inventory"
                };
            }

            // Step 3: Reserve inventory (with compensation)
            await context.CallActivityAsync<string>("ReserveInventory", order);

            try
            {
                // Step 4: Process payment (with retry and compensation)
                var paymentResult = await context.CallActivityWithRetryAsync<PaymentResult>(
                    "ProcessPayment",
                    new RetryOptions(TimeSpan.FromSeconds(30), 3)
                    {
                        BackoffCoefficient = 2,
                        Handle = ex => ex is PaymentException
                    },
                    order);

                // Step 5: Create shipping order
                var shippingInfo = await context.CallActivityAsync<ShippingInfo>(
                    "CreateShipment", new ShipmentRequest
                    {
                        OrderId = order.OrderId,
                        CustomerAddress = order.CustomerAddress,
                        Items = order.Items
                    });

                // Step 6: Send confirmation email (in parallel with updating customer)
                var parallelTasks = new[]
                {
                    context.CallActivityAsync<string>("SendConfirmationEmail",
                        new EmailRequest
                        {
                            CustomerEmail = order.CustomerEmail,
                            OrderId = order.OrderId,
                            ShippingInfo = shippingInfo
                        }),
                    context.CallActivityAsync<string>("UpdateCustomerOrderStatus",
                        new CustomerUpdateRequest
                        {
                            CustomerId = order.CustomerId,
                            OrderId = order.OrderId,
                            Status = "Processed"
                        })
                };

                await Task.WhenAll(parallelTasks);

                return new OrderResult
                {
                    OrderId = order.OrderId,
                    Status = "Completed",
                    ShippingInfo = shippingInfo,
                    ProcessedAt = context.CurrentUtcDateTime
                };
            }
            catch (Exception ex)
            {
                // Compensation: Release reserved inventory
                await context.CallActivityAsync<string>("ReleaseInventory", order);

                log.LogError($"Order processing failed: {ex.Message}");

                return new OrderResult
                {
                    OrderId = order.OrderId,
                    Status = "Failed",
                    ErrorMessage = ex.Message
                };
            }
        }
    }

    // Activity functions
    public static class OrderActivities
    {
        [FunctionName("ValidateOrder")]
        public static ValidationResult ValidateOrder(
            [ActivityTrigger] OrderRequest order,
            ILogger log)
        {
            log.LogInformation($"Validating order {order.OrderId}");

            if (string.IsNullOrEmpty(order.CustomerId) ||
                order.Items == null || order.Items.Count == 0)
            {
                return new ValidationResult
                {
                    IsValid = false,
                    ErrorMessage = "Invalid order: Missing customer or items"
                };
            }

            return new ValidationResult { IsValid = true };
        }

        [FunctionName("CheckInventory")]
        public static InventoryCheckResult CheckInventory(
            [ActivityTrigger] OrderRequest order,
            ILogger log)
        {
            log.LogInformation($"Checking inventory for order {order.OrderId}");

            // Simulate inventory check
            foreach (var item in order.Items)
            {
                var availableQuantity = GetAvailableQuantity(item.ProductId);
                if (availableQuantity < item.Quantity)
                {
                    return new InventoryCheckResult
                    {
                        IsAvailable = false,
                        UnavailableProduct = item.ProductId,
                        AvailableQuantity = availableQuantity
                    };
                }
            }

            return new InventoryCheckResult { IsAvailable = true };
        }

        [FunctionName("ReserveInventory")]
        public static string ReserveInventory(
            [ActivityTrigger] OrderRequest order,
            ILogger log)
        {
            log.LogInformation($"Reserving inventory for order {order.OrderId}");

            // Reserve inventory logic here
            return $"Inventory reserved for order {order.OrderId}";
        }

        [FunctionName("ProcessPayment")]
        public static PaymentResult ProcessPayment(
            [ActivityTrigger] OrderRequest order,
            ILogger log)
        {
            log.LogInformation($"Processing payment for order {order.OrderId}");

            // Simulate payment processing
            var totalAmount = order.Items.Sum(item => item.Price * item.Quantity);

            // Simulate occasional payment failures
            if (DateTime.Now.Second % 10 == 0)
            {
                throw new PaymentException("Payment gateway temporarily unavailable");
            }

            return new PaymentResult
            {
                TransactionId = Guid.NewGuid().ToString(),
                Amount = totalAmount,
                Currency = "USD",
                Status = "Completed"
            };
        }

        [FunctionName("CreateShipment")]
        public static ShippingInfo CreateShipment(
            [ActivityTrigger] ShipmentRequest request,
            ILogger log)
        {
            log.LogInformation($"Creating shipment for order {request.OrderId}");

            return new ShippingInfo
            {
                ShipmentId = Guid.NewGuid().ToString(),
                TrackingNumber = $"TRACK-{DateTime.Now.Ticks}",
                EstimatedDelivery = DateTime.Now.AddDays(3),
                ShippingMethod = "Standard"
            };
        }

        [FunctionName("SendConfirmationEmail")]
        public static string SendConfirmationEmail(
            [ActivityTrigger] EmailRequest request,
            ILogger log)
        {
            log.LogInformation($"Sending confirmation email for order {request.OrderId}");

            // Email sending logic here
            return $"Email sent to {request.CustomerEmail}";
        }

        [FunctionName("UpdateCustomerOrderStatus")]
        public static string UpdateCustomerOrderStatus(
            [ActivityTrigger] CustomerUpdateRequest request,
            ILogger log)
        {
            log.LogInformation($"Updating customer {request.CustomerId} order status");

            // Database update logic here
            return $"Customer order status updated to {request.Status}";
        }

        [FunctionName("ReleaseInventory")]
        public static string ReleaseInventory(
            [ActivityTrigger] OrderRequest order,
            ILogger log)
        {
            log.LogInformation($"Releasing inventory for order {order.OrderId}");

            // Inventory release logic here
            return $"Inventory released for order {order.OrderId}";
        }

        private static int GetAvailableQuantity(string productId)
        {
            // Simulate inventory lookup
            return new Random().Next(0, 100);
        }
    }

    // Data models
    public class OrderRequest
    {
        public string OrderId { get; set; }
        public string CustomerId { get; set; }
        public string CustomerEmail { get; set; }
        public Address CustomerAddress { get; set; }
        public List<OrderItem> Items { get; set; }
    }

    public class OrderItem
    {
        public string ProductId { get; set; }
        public string ProductName { get; set; }
        public int Quantity { get; set; }
        public decimal Price { get; set; }
    }

    public class Address
    {
        public string Street { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string ZipCode { get; set; }
        public string Country { get; set; }
    }

    public class ValidationResult
    {
        public bool IsValid { get; set; }
        public string ErrorMessage { get; set; }
    }

    public class InventoryCheckResult
    {
        public bool IsAvailable { get; set; }
        public string UnavailableProduct { get; set; }
        public int AvailableQuantity { get; set; }
    }

    public class PaymentResult
    {
        public string TransactionId { get; set; }
        public decimal Amount { get; set; }
        public string Currency { get; set; }
        public string Status { get; set; }
    }

    public class ShippingInfo
    {
        public string ShipmentId { get; set; }
        public string TrackingNumber { get; set; }
        public DateTime EstimatedDelivery { get; set; }
        public string ShippingMethod { get; set; }
    }

    public class EmailRequest
    {
        public string CustomerEmail { get; set; }
        public string OrderId { get; set; }
        public ShippingInfo ShippingInfo { get; set; }
    }

    public class CustomerUpdateRequest
    {
        public string CustomerId { get; set; }
        public string OrderId { get; set; }
        public string Status { get; set; }
    }

    public class ShipmentRequest
    {
        public string OrderId { get; set; }
        public Address CustomerAddress { get; set; }
        public List<OrderItem> Items { get; set; }
    }

    public class OrderResult
    {
        public string OrderId { get; set; }
        public string Status { get; set; }
        public string ErrorMessage { get; set; }
        public ShippingInfo ShippingInfo { get; set; }
        public DateTime? ProcessedAt { get; set; }
    }

    public class PaymentException : Exception
    {
        public PaymentException(string message) : base(message) { }
    }
}