Создать личное статическое поле на уровне модуля в F # - PullRequest
0 голосов
/ 02 июля 2018

Я пытаюсь создать настроенный объект, который можно повторно использовать в запросах в функциях Azure. Пример ниже в C #. Идея состоит в том, чтобы избежать дорогостоящего создания настраиваемого DocumentClient экземпляра для каждого запроса. Поле client является статическим и используется повторно в этом примере, взятом из документации:

using System;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;

private static DocumentClient client = GetCustomClient();
private static DocumentClient GetCustomClient()
{
    DocumentClient customClient = new DocumentClient(
        new Uri(ConfigurationManager.AppSettings["CosmosDBAccountEndpoint"]), 
        ConfigurationManager.AppSettings["CosmosDBAccountKey"],
        new ConnectionPolicy
        {
            ConnectionMode = ConnectionMode.Direct,
            ConnectionProtocol = Protocol.Tcp,
            // Customize retry options for Throttled requests
            RetryOptions = new RetryOptions()
            {
                MaxRetryAttemptsOnThrottledRequests = 10,
                MaxRetryWaitTimeInSeconds = 30
            }
        });

    // Customize PreferredLocations
    customClient.ConnectionPolicy.PreferredLocations.Add(LocationNames.CentralUS);
    customClient.ConnectionPolicy.PreferredLocations.Add(LocationNames.NorthEurope);

    return customClient;
}

[FunctionName("CosmosDbSample")]
public static async Task<HttpResponseMessage> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "foo/{id}")] HttpRequestMessage req,
    string id,
    TraceWriter log)
{
    Uri documentUri = UriFactory.CreateDocumentUri("ToDoList", "Items", id);
    Document doc = await client.ReadDocumentAsync(documentUri);

    if (doc == null)
    {
        return req.CreateResponse(HttpStatusCode.NotFound);
    }

    return req.CreateResponse(HttpStatusCode.OK, doc);
}

Чтобы попытаться смоделировать на более простом примере, я попробовал код ниже. Работает нормально:

namespace TransactionsAggregate

open Microsoft.AspNetCore.Http
open Microsoft.Azure.WebJobs
open Microsoft.Azure.WebJobs.Host
open Microsoft.Azure.WebJobs.Extensions.Http
open System.Net
open System.Net.Http
open System.Web.Http
open Newtonsoft.Json
open System.Text


module Ping =    


    type Name = {
        First: string
        Last: string
    }

    type Greeting = {
        Greeting: string
    }


    let jsonFormatter = System.Net.Http.Formatting.JsonMediaTypeFormatter()
    jsonFormatter.SerializerSettings.ContractResolver <- new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()



    [<FunctionName("Ping1")>]
    let run([<HttpTrigger>] req: HttpRequest, log: TraceWriter) =
        async {

        log.Info("Chamando Ping 1")
        let! jsonContent = req.ReadAsStringAsync() |> Async.AwaitTask

        try
            let name = JsonConvert.DeserializeObject<Name>(jsonContent, jsonFormatter.SerializerSettings)

            let response = new HttpResponseMessage(HttpStatusCode.OK)
            let body = JsonConvert.SerializeObject( { Greeting = sprintf "Hello %s %s!" name.First name.Last })
            let content = new StringContent(body, Encoding.UTF8, "application/json")
            response.Content <- content
            return response

        with _ ->
            return new HttpResponseMessage(HttpStatusCode.BadRequest)
        } |> Async.StartAsTask

В этом примере F # у нас есть функция Azure, которая работает в версии V2 и написана на .NET Core. Это предварительно скомпилированная функция (не скрипт). Это проект библиотеки классов. Этот пример просто повторяет переданные параметры. jsonFormatter определен и настроен на уровне модуля и не помечен как статический. Есть ли способ создать статическое поле чего-то похожего, чтобы я мог кэшировать этот jsonFormatter или в будущем гораздо более дорогой объект? Кроме того, есть ли гарантия, что в приложении будет только один экземпляр этого значения?

Документация: https://docs.microsoft.com/en-us/sandbox/functions-recipes/cosmos-db

Заранее спасибо

1 Ответ

0 голосов
/ 02 июля 2018

Вы уже достигли своей цели. let привязка в модуле F # будет выполняться только один раз для экземпляра функций Azure, это похоже на статическое поле только для чтения в C #.

Функции Azure могут запускать несколько экземпляров (серверов) одновременно и с течением времени. Каждый раз, когда предоставляется новый экземпляр, первое выполнение будет медленным и будет включать в себя инициализацию дорогих выражений. Следующее выполнение в том же экземпляре будет использовать их повторно, так что это будет намного быстрее.

...