Как сделать функцию более высокого порядка для ответов на конфликты c # - PullRequest
1 голос
/ 05 апреля 2019

У меня есть эта функция, которая обновляет базу данных CouchDB, но я хочу, чтобы она пыталась обновить снова, если код ответа конфликтует, я хочу, чтобы у нее было 3 попытки, как мне это сделать?

    public async Task<HttpResponseMessage> UpdateRecord(Profile latestProfile)
    {
        ProfileRecordByUpn profileRecord = await this.GetProfileByUpn(latestProfile);
        Profile oldProfile = profileRecord.Rows.First().Value;

        var client = this.clientFactory.CreateClient(NamedHttpClients.COUCHDB);

        var formatter = new JsonMediaTypeFormatter();
        formatter.SerializerSettings = new JsonSerializerSettings
        {
            Formatting = Formatting.Indented,
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };

        var query = HttpUtility.ParseQueryString(string.Empty);
        query["rev"] = oldProfile.Rev;

        //Setting the profile Active = true, because as of now we don't have any UI for disabling the account
        latestProfile.Active = oldProfile.Active;

        DateTimeOffset now = DateTimeOffset.Now;
        latestProfile.Created = oldProfile.Created;
        latestProfile.Modified = now;

        //This will check if we the InApp boolean value changed then will set date to Enabled/Disabled
        if (oldProfile.InApp != latestProfile.InApp)
        {                
            if (latestProfile.InApp == true)
            {
                latestProfile.InAppEnabled = now;
                latestProfile.InAppDisabled = oldProfile.InAppDisabled;
            }
            else
            {
                latestProfile.InAppDisabled = now;
                latestProfile.InAppEnabled = oldProfile.InAppEnabled;
            }
        }
        else
        {
            latestProfile.InAppEnabled = oldProfile.InAppEnabled;
            latestProfile.InAppDisabled = oldProfile.InAppDisabled;
        }

        //This will check if we the SMS boolean value changed then will set date to Enabled/Disabled
        if (oldProfile.SMS != latestProfile.SMS)
        {
            if (latestProfile.SMS == true)
            {
                latestProfile.SMSEnabled = now;
                latestProfile.SMSDisabled = oldProfile.SMSDisabled;
            }
            else
            {
                latestProfile.SMSDisabled = now;
                latestProfile.SMSEnabled = oldProfile.SMSEnabled;
            }
        }
        else
        {
            latestProfile.SMSEnabled = oldProfile.SMSEnabled;
            latestProfile.SMSDisabled = oldProfile.SMSDisabled;
        }

        //This will check if we the SMS boolean value changed then will set date to Enabled/Disabled
        if (oldProfile.Email != latestProfile.Email)
        {
            if (latestProfile.Email == true)
            {
                latestProfile.EmailEnabled = now;
                latestProfile.EmailDisabled = oldProfile.EmailDisabled;
            }
            else
            {
                latestProfile.EmailDisabled = now;
                latestProfile.EmailEnabled = oldProfile.EmailEnabled;
            }
        }
        else
        {
            latestProfile.EmailEnabled = oldProfile.EmailEnabled;
            latestProfile.EmailDisabled = oldProfile.EmailDisabled;
        }

        var response = await this.couchDbClient.AuthenticatedQuery(async (c) => {
            return await c.PutAsync($"{API_PROFILES_DB}/{oldProfile.Id.ToString()}?{query}", latestProfile, formatter);
        }, NamedHttpClients.COUCHDB, client);            

        return response;
    }

так я буду вызывать эту функцию из другой функции? Сделать ли другую функцию, которая является функцией более высокого порядка, и передать эту функцию в качестве параметра этой функции более высокого порядка?

1 Ответ

2 голосов
/ 05 апреля 2019

Функции высшего порядка в C # реализуются методами, принимающими в качестве параметров делегатов, обычно это делегаты Action или Func.

В этом случае вам следует использовать установленную библиотеку, например Polly.

var policy = Policy
  .HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.Conflict)
  .RetryAsync(3);

var result = await policy.ExecuteAsync(() => UpdateRecord(latestProfile));

Обновите , чтобы сделать это самостоятельно (не скомпилированный и непроверенный код):

async Task<HttpResponseMessage> MyRetry(Func<Task<HttpResponseMessage>> action)
{
  for (int retries = 0; retries < 3; ++retries)
  {
    var result = await action();
    if (result.StatusCode != HttpStatusCode.Conflict)
      return result;
  }
  return await action();
}

Приведенный выше код будет повторяться 3 раза в течение 4общее количество вызовов, если оно продолжает возвращаться Conflict.

...