<commit_before>﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Exceptionless.DateTimeExtensions;
using Foundatio.Caching;
using Foundatio.Logging;
using Foundatio.Repositories.Elasticsearch.Extensions;
using Foundatio.Repositories.Elasticsearch.Jobs;
using Foundatio.Repositories.Extensions;
using Foundatio.Utility;
using Nest;

namespace Foundatio.Repositories.Elasticsearch.Configuration {
    public class VersionedIndex : IndexBase, IMaintainableIndex {
        public VersionedIndex(IElasticClient client, string name, int version = 1, ICacheClient cache = null, ILoggerFactory loggerFactory = null)
            : base(client, name, cache, loggerFactory) {
            Version = version;
            VersionedName = String.Concat(Name, "-v", Version);
        }

        public int Version { get; }
        public string VersionedName { get; }
        public bool DiscardIndexesOnReindex { get; set; } = true;

        public override async Task ConfigureAsync() {
            if (!await IndexExistsAsync(VersionedName).AnyContext()) {
                if (!await AliasExistsAsync(Name).AnyContext())
                    await CreateIndexAsync(VersionedName, d => ConfigureDescriptor(d).AddAlias(Name)).AnyContext();
                else
                    await CreateIndexAsync(VersionedName, ConfigureDescriptor).AnyContext();
            }
        }

        protected virtual async Task CreateAliasAsync(string index, string name) {
            if (await AliasExistsAsync(Name).AnyContext())
                return;
            
            var response = await _client.AliasAsync(a => a.Add(s => s.Index(index).Alias(name))).AnyContext();
            if (response.IsValid) {
                while (!await AliasExistsAsync(name).AnyContext())
                    SystemClock.Sleep(100);

                return;
            }

            if (await AliasExistsAsync(name).AnyContext())
                return;

            string message = $"Error creating alias {name}: {response.GetErrorMessage()}";
            _logger.Error().Exception(response.ConnectionStatus.OriginalException).Message(message).Property("request", response.GetRequest()).Write();
            throw new ApplicationException(message, response.ConnectionStatus.OriginalException);
        }

        protected async Task<bool> AliasExistsAsync(string alias) {
            var response = await _client.AliasExistsAsync(alias).AnyContext();
            if (response.IsValid)
                return response.Exists;
            <commit_msg>Fixed a bug where aliases weren't always being created<commit_after>﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Exceptionless.DateTimeExtensions;
using Foundatio.Caching;
using Foundatio.Logging;
using Foundatio.Repositories.Elasticsearch.Extensions;
using Foundatio.Repositories.Elasticsearch.Jobs;
using Foundatio.Repositories.Extensions;
using Foundatio.Utility;
using Nest;

namespace Foundatio.Repositories.Elasticsearch.Configuration {
    public class VersionedIndex : IndexBase, IMaintainableIndex {
        public VersionedIndex(IElasticClient client, string name, int version = 1, ICacheClient cache = null, ILoggerFactory loggerFactory = null)
            : base(client, name, cache, loggerFactory) {
            Version = version;
            VersionedName = String.Concat(Name, "-v", Version);
        }

        public int Version { get; }
        public string VersionedName { get; }
        public bool DiscardIndexesOnReindex { get; set; } = true;

        public override async Task ConfigureAsync() {
            if (!await IndexExistsAsync(VersionedName).AnyContext()) {
                if (!await AliasExistsAsync(Name).AnyContext())
                    await CreateIndexAsync(VersionedName, d => ConfigureDescriptor(d).AddAlias(Name)).AnyContext();
                else
                    await CreateIndexAsync(VersionedName, ConfigureDescriptor).AnyContext();
            }
        }

        protected virtual async Task CreateAliasAsync(string index, string name) {
            if (await AliasExistsAsync(name).AnyContext())
                return;
            
            var response = await _client.AliasAsync(a => a.Add(s => s.Index(index).Alias(name))).AnyContext();
            if (response.IsValid) {
                while (!await AliasExistsAsync(name).AnyContext())
                    SystemClock.Sleep(100);

                return;
            }

            if (await AliasExistsAsync(name).AnyContext())
                return;

            string message = $"Error creating alias {name}: {response.GetErrorMessage()}";
            _logger.Error().Exception(response.ConnectionStatus.OriginalException).Message(message).Property("request", response.GetRequest()).Write();
            throw new ApplicationException(message, response.ConnectionStatus.OriginalException);
        }

        protected async Task<bool> AliasExistsAsync(string alias) {
            var response = await _client.AliasExistsAsync(alias).AnyContext();
            if (response.IsValid)
                return response.Exists;
            
{'fraction_non_alphanumeric': 0.09441159641426664, 'fraction_numerical': 0.0015258439824527943, 'mean_word_length': 2.7217885024840314, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4036579', 'n_tokens_mistral': 1296, 'n_tokens_neox': 1280, 'n_words': 298}