/// <summary> /// Gets all vulcan clients /// </summary> /// <returns></returns> public virtual IVulcanClient[] GetClients(string alias = null) { VulcanHelper.GuardForNullAlias(ref alias); var clientList = new List <IVulcanClient>(); var client = CreateElasticClient(CommonConnectionSettings.ConnectionSettings); var aliasStart = Index + "-" + alias; var aliases = client.CatAliases()?.Records.Where(a => a.Alias.StartsWith(aliasStart)).ToList(); if (aliases?.Any() != true) { return(clientList.ToArray()); } var indices = aliases.Select(a => a.Index).ToList(); if (indices.Any() != true) { return(clientList.ToArray()); } clientList.AddRange ( indices .Select(index => index.Substring(Index.Length + 16)) .Select(cultureName => GetClient(cultureName.Equals("invariant", StringComparison.OrdinalIgnoreCase) ? CultureInfo.InvariantCulture : new CultureInfo(cultureName) ) ) ); return(clientList.ToArray()); }
/// <summary> /// Swaps alias for culture /// </summary> /// <param name="language"></param> /// <param name="oldAlias"></param> /// <param name="newAlias"></param> public void SwitchAlias(CultureInfo language, string oldAlias, string newAlias) { lock (this) { var cultureInfo = language ?? CultureInfo.CurrentUICulture; VulcanHelper.GuardForNullAlias(ref oldAlias); VulcanHelper.GuardForNullAlias(ref newAlias); var client = CreateElasticClient(CommonConnectionSettings.ConnectionSettings); // use a raw elasticclient because we just need this to be quick var oldFullAlias = VulcanHelper.GetAliasName(Index, cultureInfo, oldAlias); var newFullAlias = VulcanHelper.GetAliasName(Index, cultureInfo, newAlias); var oldIndex = client.GetAlias(a => a.Name(oldFullAlias)).Indices?.First().Key; var newIndex = client.GetAlias(a => a.Name(newFullAlias)).Indices?.First().Key; client.Alias(bad => bad.Remove(a => a.Alias(oldFullAlias).Index("*")) .Remove(a => a.Alias(newFullAlias).Index("*")) .Add(a => a.Alias(oldFullAlias).Index(newIndex)) .Add(a => a.Alias(newFullAlias).Index(oldIndex))); client.Refresh("*"); Clients?.Clear(); // force a client refresh } }
/// <summary> /// Delete content for all clients /// </summary> /// <param name="contentLink"></param> /// <param name="typeName"></param> /// <param name="alias"></param> public virtual void DeleteContentEveryLanguage(ContentReference contentLink, string typeName, string alias = null) { VulcanHelper.GuardForNullAlias(ref alias); // we don't know what language(s), or even if invariant, so send a delete request to all foreach (var client in GetClients(alias)) { client.DeleteContent(contentLink, typeName); } }
/// <summary> /// Delete content by language /// </summary> /// <param name="content"></param> /// <param name="alias"></param> public virtual void DeleteContentByLanguage(IContent content, string alias = null) { VulcanHelper.GuardForNullAlias(ref alias); IVulcanClient client; if (content is ILocalizable localizable) { client = GetClient(localizable.Language, alias); } else { client = GetClient(CultureInfo.InvariantCulture, alias); } client.DeleteContent(content); }
/// <summary> /// Delete item /// </summary> /// <param name="pocoIndexer"></param> /// <param name="item"></param> /// <param name="alias"></param> public virtual void DeleteItem(IVulcanPocoIndexer pocoIndexer, object item, string alias = null) { VulcanHelper.GuardForNullAlias(ref alias); var id = pocoIndexer.GetItemIdentifier(item); var type = GetTypeName(item); try { var invariantClient = GetInvariantClient(alias); var response = invariantClient.Delete(new DeleteRequest(invariantClient.IndexName, type, id)); Logger.Debug("Vulcan deleted " + id + " for type " + type + ": " + response.DebugInformation); } catch (Exception e) { Logger.Warning("Vulcan could not delete object of type " + type + " with ID " + id, e); } }
/// <summary> /// Index item /// </summary> /// <param name="pocoIndexer"></param> /// <param name="item"></param> /// <param name="alias"></param> public virtual void IndexItem(IVulcanPocoIndexer pocoIndexer, object item, string alias = null) { var id = pocoIndexer.GetItemIdentifier(item); var type = GetTypeName(item); VulcanHelper.GuardForNullAlias(ref alias); try { var invariantClient = GetInvariantClient(alias); var response = invariantClient.Index(item, z => z.Id(id).Type(type)); Logger.Debug($"Vulcan indexed {id} for type {type}: {response.DebugInformation}"); } catch (Exception e) { Logger.Warning($"Vulcan could not index object of type {type} with ID {id}", e); } }
/// <summary> /// Index content for all langauges /// </summary> /// <param name="content"></param> /// <param name="alias"></param> public virtual void IndexContentEveryLanguage(IContent content, string alias = null) { VulcanHelper.GuardForNullAlias(ref alias); if (content is ILocalizable localizable) { foreach (var language in localizable.ExistingLanguages) { var client = GetClient(language, alias); client.IndexContent(ContentLoader.Get <IContent>(content.ContentLink.ToReferenceWithoutVersion(), language)); } } else { var client = GetClient(CultureInfo.InvariantCulture, alias); client.IndexContent(content); } }
/// <summary> /// Swap all culture aliases /// </summary> /// <param name="oldAlias"></param> /// <param name="newAlias"></param> public void SwitchAliasAllCultures(string oldAlias, string newAlias) { lock (this) { VulcanHelper.GuardForNullAlias(ref oldAlias); VulcanHelper.GuardForNullAlias(ref newAlias); var aliasOldStart = Index + "-" + oldAlias + "_"; var aliasNewStart = Index + "-" + newAlias + "_"; var client = CreateElasticClient(CommonConnectionSettings.ConnectionSettings); // use a raw elasticclient because we just need this to be quick var aliases = client.CatAliases()?.Records.Where(a => a.Alias.StartsWith(Index + "-")).ToList(); var handled = new List <string>(); if (aliases != null) { foreach (var alias in aliases) { if (handled.Contains(alias.Alias)) { continue; } // haven't handled this yet! string checkAlias = null; if (alias.Alias.StartsWith(aliasOldStart)) { checkAlias = alias.Alias.Replace("-" + oldAlias + "_", "-" + newAlias + "_"); } else if (alias.Alias.StartsWith(aliasNewStart)) { checkAlias = alias.Alias.Replace("-" + newAlias + "_", "-" + oldAlias + "_"); } if (checkAlias == null) { continue; } var checkAliasRecord = aliases.FirstOrDefault(a => a.Alias == checkAlias); if (checkAliasRecord != null) { // swapping! client.Alias(bad => bad.Remove(a => a.Alias(alias.Alias).Index("*")) .Remove(a => a.Alias(checkAliasRecord.Alias).Index("*")) .Add(a => a.Alias(alias.Alias).Index(checkAliasRecord.Index)) .Add(a => a.Alias(checkAliasRecord.Alias).Index(alias.Index))); handled.Add(alias.Alias); handled.Add(checkAliasRecord.Alias); Logger.Warning("Vulcan swapped indexes for aliases: " + alias.Alias + " and " + checkAliasRecord.Alias); } else { // no swap, simply switching this client.Alias(bad => bad.Remove(a => a.Alias(alias.Alias).Index("*")) .Add(a => a.Alias(checkAlias).Index(alias.Index))); Logger.Warning("Vulcan switched index to new indexAlias: " + alias.Alias + " to " + checkAlias); } } } client.Refresh("*"); Clients?.Clear(); // force a client refresh } }
/// <summary> /// Index item /// </summary> /// <param name="pocoIndexer"></param> /// <param name="updateStatus"></param> /// <param name="count"></param> /// <param name="stopSignaled"></param> /// <param name="alias"></param> /// <returns></returns> public virtual string Index(IVulcanPocoIndexer pocoIndexer, Action <string> updateStatus, ref int count, ref bool stopSignaled, string alias = null) { if (pocoIndexer == null) { throw new ArgumentNullException($"{nameof(pocoIndexer)} cannot be null!"); } VulcanHelper.GuardForNullAlias(ref alias); var total = pocoIndexer.TotalItems; var pageSize = pocoIndexer.PageSize; pageSize = pageSize < 1 ? 1 : pageSize; // don't allow 0 or negative var totalPages = (total + pageSize - 1) / pageSize; var internalCount = 0; var invariantClient = GetInvariantClient(alias); for (var page = 1; page <= totalPages; page++) { updateStatus?.Invoke($"Indexing page {page} of {totalPages} items of {pocoIndexer.IndexerName} content!"); var itemsToIndex = pocoIndexer.GetItems(page, pageSize)?.ToList(); var firstItem = itemsToIndex?.FirstOrDefault(); if (firstItem == null) { break; } var itemType = firstItem.GetType(); var itemTypeName = GetTypeName(firstItem); var operationType = typeof(BulkIndexOperation <>).MakeGenericType(itemType); var operations = new List <IBulkOperation>(); foreach (var item in itemsToIndex) { if (stopSignaled) { return("Stop of job was called"); } if (!(Activator.CreateInstance(operationType, item) is IBulkOperation indexItem)) { throw new Exception("Unable to create item for bulk request"); } indexItem.Type = new TypeName { Name = itemTypeName, Type = itemType }; indexItem.Id = pocoIndexer.GetItemIdentifier(item); operations.Add(indexItem); internalCount++; count++; } // https://www.elastic.co/guide/en/elasticsearch/client/net-api/1.x/bulk.html var request = new BulkRequest { #if NEST2 Refresh = true, Consistency = Consistency.One, #elif NEST5 Refresh = Refresh.True, #endif Operations = operations }; invariantClient.Bulk(request); } return($"Indexed {internalCount} of {total} items of {pocoIndexer.IndexerName} content!"); }
/// <summary> /// invariant client /// </summary> protected IVulcanClient GetInvariantClient(string alias = null) { VulcanHelper.GuardForNullAlias(ref alias); return(VulcanHander.GetClient(CultureInfo.InvariantCulture, alias)); }