ElasticSearch: used file-scoped namespaces

This commit is contained in:
Maksim Chegulov 2022-02-10 16:45:41 +03:00
parent cd879ed2a7
commit 53237d8c6f
13 changed files with 2326 additions and 2339 deletions

View File

@ -23,25 +23,24 @@
*
*/
namespace ASC.ElasticSearch
{
public enum Analyzer
{
standard,
whitespace,
uax_url_email
}
[Flags]
public enum CharFilter
{
io,
html
}
[Flags]
public enum Filter
{
lowercase
}
namespace ASC.ElasticSearch;
public enum Analyzer
{
standard,
whitespace,
uax_url_email
}
[Flags]
public enum CharFilter
{
io,
html
}
[Flags]
public enum Filter
{
lowercase
}

View File

@ -23,11 +23,10 @@
*
*/
namespace ASC.ElasticSearch
namespace ASC.ElasticSearch;
public class Document
{
public class Document
{
public string Data { get; set; }
public Attachment Attachment { get; set; }
}
public string Data { get; set; }
public Attachment Attachment { get; set; }
}

View File

@ -1,16 +1,15 @@
namespace ASC.ElasticSearch
namespace ASC.ElasticSearch;
public interface ISearchItem
{
public interface ISearchItem
{
public int Id { get; set; }
public int TenantId { get; set; }
public string IndexName { get; }
public int Id { get; set; }
public int TenantId { get; set; }
public string IndexName { get; }
public Expression<Func<ISearchItem, object[]>> GetSearchContentFields(SearchSettingsHelper searchSettings);
}
public interface ISearchItemDocument : ISearchItem
{
public Document Document { get; set; }
}
public Expression<Func<ISearchItem, object[]>> GetSearchContentFields(SearchSettingsHelper searchSettings);
}
public interface ISearchItemDocument : ISearchItem
{
public Document Document { get; set; }
}

View File

@ -23,170 +23,169 @@
*
*/
namespace ASC.ElasticSearch.Core
{
[Serializable]
public class SearchSettings : ISettings
{
public string Data { get; set; }
public Guid ID => new Guid("{93784AB2-10B5-4C2F-9B36-F2662CCCF316}");
internal List<SearchSettingsItem> Items
{
get
{
if (_items != null)
{
return _items;
}
namespace ASC.ElasticSearch.Core;
var parsed = JsonConvert.DeserializeObject<List<SearchSettingsItem>>(Data ?? "");
return _items = parsed ?? new List<SearchSettingsItem>();
}
set
{
_items = value;
}
}
private List<SearchSettingsItem> _items;
public ISettings GetDefault(IServiceProvider serviceProvider)
{
return new SearchSettings();
}
internal bool IsEnabled(string name)
{
var wrapper = Items.FirstOrDefault(r => r.ID == name);
return wrapper != null && wrapper.Enabled;
}
}
[Scope]
public class SearchSettingsHelper
[Serializable]
public class SearchSettings : ISettings
{
public string Data { get; set; }
public Guid ID => new Guid("{93784AB2-10B5-4C2F-9B36-F2662CCCF316}");
internal List<SearchSettingsItem> Items
{
public IConfiguration Configuration { get; }
internal List<IFactoryIndexer> AllItems =>
_allItems ??= _serviceProvider.GetService<IEnumerable<IFactoryIndexer>>().ToList();
private readonly TenantManager _tenantManager;
private readonly SettingsManager _settingsManager;
private readonly CoreBaseSettings _coreBaseSettings;
private readonly ICacheNotify<ReIndexAction> _cacheNotify;
private readonly IServiceProvider _serviceProvider;
private List<IFactoryIndexer> _allItems;
public SearchSettingsHelper(
TenantManager tenantManager,
SettingsManager settingsManager,
CoreBaseSettings coreBaseSettings,
ICacheNotify<ReIndexAction> cacheNotify,
IServiceProvider serviceProvider,
IConfiguration configuration)
get
{
_tenantManager = tenantManager;
_settingsManager = settingsManager;
_coreBaseSettings = coreBaseSettings;
_cacheNotify = cacheNotify;
_serviceProvider = serviceProvider;
Configuration = configuration;
}
public List<SearchSettingsItem> GetAllItems()
{
if (!_coreBaseSettings.Standalone)
if (_items != null)
{
return new List<SearchSettingsItem>();
return _items;
}
var settings = _settingsManager.Load<SearchSettings>();
return AllItems.Select(r => new SearchSettingsItem
{
ID = r.IndexName,
Enabled = settings.IsEnabled(r.IndexName),
Title = r.SettingsTitle
}).ToList();
}
public void Set(List<SearchSettingsItem> items)
{
if (!_coreBaseSettings.Standalone)
{
return;
}
var parsed = JsonConvert.DeserializeObject<List<SearchSettingsItem>>(Data ?? "");
var settings = _settingsManager.Load<SearchSettings>();
var settingsItems = settings.Items;
var toReIndex = !settingsItems.Any() ? items.Where(r => r.Enabled).ToList() : items.Where(item => settingsItems.Any(r => r.ID == item.ID && r.Enabled != item.Enabled)).ToList();
settings.Items = items;
settings.Data = JsonConvert.SerializeObject(items);
_settingsManager.Save(settings);
return _items = parsed ?? new List<SearchSettingsItem>();
}
set
{
_items = value;
}
}
var action = new ReIndexAction() { Tenant = _tenantManager.GetCurrentTenant().TenantId };
action.Names.AddRange(toReIndex.Select(r => r.ID).ToList());
private List<SearchSettingsItem> _items;
_cacheNotify.Publish(action, CacheNotifyAction.Any);
public ISettings GetDefault(IServiceProvider serviceProvider)
{
return new SearchSettings();
}
internal bool IsEnabled(string name)
{
var wrapper = Items.FirstOrDefault(r => r.ID == name);
return wrapper != null && wrapper.Enabled;
}
}
[Scope]
public class SearchSettingsHelper
{
public IConfiguration Configuration { get; }
internal List<IFactoryIndexer> AllItems =>
_allItems ??= _serviceProvider.GetService<IEnumerable<IFactoryIndexer>>().ToList();
private readonly TenantManager _tenantManager;
private readonly SettingsManager _settingsManager;
private readonly CoreBaseSettings _coreBaseSettings;
private readonly ICacheNotify<ReIndexAction> _cacheNotify;
private readonly IServiceProvider _serviceProvider;
private List<IFactoryIndexer> _allItems;
public SearchSettingsHelper(
TenantManager tenantManager,
SettingsManager settingsManager,
CoreBaseSettings coreBaseSettings,
ICacheNotify<ReIndexAction> cacheNotify,
IServiceProvider serviceProvider,
IConfiguration configuration)
{
_tenantManager = tenantManager;
_settingsManager = settingsManager;
_coreBaseSettings = coreBaseSettings;
_cacheNotify = cacheNotify;
_serviceProvider = serviceProvider;
Configuration = configuration;
}
public List<SearchSettingsItem> GetAllItems()
{
if (!_coreBaseSettings.Standalone)
{
return new List<SearchSettingsItem>();
}
public bool CanIndexByContent<T>(int tenantId) where T : class, ISearchItem
var settings = _settingsManager.Load<SearchSettings>();
return AllItems.Select(r => new SearchSettingsItem
{
return CanIndexByContent(typeof(T), tenantId);
ID = r.IndexName,
Enabled = settings.IsEnabled(r.IndexName),
Title = r.SettingsTitle
}).ToList();
}
public void Set(List<SearchSettingsItem> items)
{
if (!_coreBaseSettings.Standalone)
{
return;
}
public bool CanIndexByContent(Type t, int tenantId)
var settings = _settingsManager.Load<SearchSettings>();
var settingsItems = settings.Items;
var toReIndex = !settingsItems.Any() ? items.Where(r => r.Enabled).ToList() : items.Where(item => settingsItems.Any(r => r.ID == item.ID && r.Enabled != item.Enabled)).ToList();
settings.Items = items;
settings.Data = JsonConvert.SerializeObject(items);
_settingsManager.Save(settings);
var action = new ReIndexAction() { Tenant = _tenantManager.GetCurrentTenant().TenantId };
action.Names.AddRange(toReIndex.Select(r => r.ID).ToList());
_cacheNotify.Publish(action, CacheNotifyAction.Any);
}
public bool CanIndexByContent<T>(int tenantId) where T : class, ISearchItem
{
return CanIndexByContent(typeof(T), tenantId);
}
public bool CanIndexByContent(Type t, int tenantId)
{
if (!typeof(ISearchItemDocument).IsAssignableFrom(t))
{
if (!typeof(ISearchItemDocument).IsAssignableFrom(t))
{
return false;
}
if (Convert.ToBoolean(Configuration["core:search-by-content"] ?? "false"))
{
return true;
}
if (!_coreBaseSettings.Standalone)
{
return true;
}
var settings = _settingsManager.LoadForTenant<SearchSettings>(tenantId);
return settings.IsEnabled(((ISearchItemDocument)_serviceProvider.GetService(t)).IndexName);
return false;
}
public bool CanSearchByContent<T>() where T : class, ISearchItem
if (Convert.ToBoolean(Configuration["core:search-by-content"] ?? "false"))
{
return CanSearchByContent(typeof(T));
return true;
}
public bool CanSearchByContent(Type t)
if (!_coreBaseSettings.Standalone)
{
var tenantId = _tenantManager.GetCurrentTenant().TenantId;
if (!CanIndexByContent(t, tenantId))
{
return false;
}
return true;
}
if (_coreBaseSettings.Standalone)
{
return true;
}
var settings = _settingsManager.LoadForTenant<SearchSettings>(tenantId);
return _tenantManager.GetTenantQuota(tenantId).ContentSearch;
}
}
[Serializable]
public class SearchSettingsItem
{
public string ID { get; set; }
public bool Enabled { get; set; }
public string Title { get; set; }
}
return settings.IsEnabled(((ISearchItemDocument)_serviceProvider.GetService(t)).IndexName);
}
public bool CanSearchByContent<T>() where T : class, ISearchItem
{
return CanSearchByContent(typeof(T));
}
public bool CanSearchByContent(Type t)
{
var tenantId = _tenantManager.GetCurrentTenant().TenantId;
if (!CanIndexByContent(t, tenantId))
{
return false;
}
if (_coreBaseSettings.Standalone)
{
return true;
}
return _tenantManager.GetTenantQuota(tenantId).ContentSearch;
}
}
[Serializable]
public class SearchSettingsItem
{
public string ID { get; set; }
public bool Enabled { get; set; }
public string Title { get; set; }
}

View File

@ -23,447 +23,446 @@
*
*/
namespace ASC.ElasticSearch
namespace ASC.ElasticSearch;
[Scope]
public class Selector<T> where T : class, ISearchItem
{
[Scope]
public class Selector<T> where T : class, ISearchItem
private readonly IServiceProvider _serviceProvider;
private readonly QueryContainerDescriptor<T> _queryContainerDescriptor = new QueryContainerDescriptor<T>();
private SortDescriptor<T> _sortContainerDescriptor = new SortDescriptor<T>();
private QueryContainer _queryContainer = new QueryContainer();
private int _limit = 1000, offset;
public Selector(IServiceProvider serviceProvider)
{
private readonly IServiceProvider _serviceProvider;
private readonly QueryContainerDescriptor<T> _queryContainerDescriptor = new QueryContainerDescriptor<T>();
private SortDescriptor<T> _sortContainerDescriptor = new SortDescriptor<T>();
private QueryContainer _queryContainer = new QueryContainer();
private int _limit = 1000, offset;
_serviceProvider = serviceProvider;
}
public Selector(IServiceProvider serviceProvider)
public Selector<T> Where<TProperty>(Expression<Func<T, TProperty>> selector, TProperty value)
{
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.Term(w, value));
return this;
}
public Selector<T> Where(Expression<Func<T, Guid>> selector, Guid value)
{
_queryContainer = _queryContainer && +Wrap(selector, (a, w) => w.Match(r => r.Field(a).Query(value.ToString())));
return this;
}
public Selector<T> Gt(Expression<Func<T, object>> selector, double? value)
{
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.Range(a => a.Field(w).GreaterThan(value)));
return this;
}
public Selector<T> Lt(Expression<Func<T, object>> selector, double? value)
{
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.Range(a => a.Field(w).LessThan(value)));
return this;
}
public Selector<T> Gt(Expression<Func<T, object>> selector, DateTime? value)
{
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.DateRange(a => a.Field(w).GreaterThan(value)));
return this;
}
public Selector<T> Ge(Expression<Func<T, object>> selector, DateTime? value)
{
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.DateRange(a => a.Field(w).GreaterThanOrEquals(value)));
return this;
}
public Selector<T> Lt(Expression<Func<T, object>> selector, DateTime? value)
{
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.DateRange(a => a.Field(w).LessThan(value)));
return this;
}
public Selector<T> Le(Expression<Func<T, object>> selector, DateTime? value)
{
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.DateRange(a => a.Field(w).LessThanOrEquals(value)));
return this;
}
public Selector<T> In<TValue>(Expression<Func<T, object>> selector, TValue[] values)
{
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.Terms(a => a.Field(w).Terms(values)));
return this;
}
public Selector<T> InAll<TValue>(Expression<Func<T, object>> selector, TValue[] values)
{
foreach (var v in values)
{
_serviceProvider = serviceProvider;
}
public Selector<T> Where<TProperty>(Expression<Func<T, TProperty>> selector, TProperty value)
{
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.Term(w, value));
return this;
}
public Selector<T> Where(Expression<Func<T, Guid>> selector, Guid value)
{
_queryContainer = _queryContainer && +Wrap(selector, (a, w) => w.Match(r => r.Field(a).Query(value.ToString())));
return this;
}
public Selector<T> Gt(Expression<Func<T, object>> selector, double? value)
{
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.Range(a => a.Field(w).GreaterThan(value)));
return this;
}
public Selector<T> Lt(Expression<Func<T, object>> selector, double? value)
{
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.Range(a => a.Field(w).LessThan(value)));
return this;
}
public Selector<T> Gt(Expression<Func<T, object>> selector, DateTime? value)
{
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.DateRange(a => a.Field(w).GreaterThan(value)));
return this;
}
public Selector<T> Ge(Expression<Func<T, object>> selector, DateTime? value)
{
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.DateRange(a => a.Field(w).GreaterThanOrEquals(value)));
return this;
}
public Selector<T> Lt(Expression<Func<T, object>> selector, DateTime? value)
{
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.DateRange(a => a.Field(w).LessThan(value)));
return this;
}
public Selector<T> Le(Expression<Func<T, object>> selector, DateTime? value)
{
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.DateRange(a => a.Field(w).LessThanOrEquals(value)));
return this;
}
public Selector<T> In<TValue>(Expression<Func<T, object>> selector, TValue[] values)
{
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.Terms(a => a.Field(w).Terms(values)));
return this;
}
public Selector<T> InAll<TValue>(Expression<Func<T, object>> selector, TValue[] values)
{
foreach (var v in values)
{
var v1 = v;
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.Term(a => a.Field(w).Value(v1)));
}
return this;
var v1 = v;
_queryContainer = _queryContainer && +Wrap(selector, (w, r) => r.Term(a => a.Field(w).Value(v1)));
}
public Selector<T> Match(Expression<Func<T, object>> selector, string value)
{
value = value.PrepareToSearch();
return this;
}
if (IsExactlyPhrase(value))
public Selector<T> Match(Expression<Func<T, object>> selector, string value)
{
value = value.PrepareToSearch();
if (IsExactlyPhrase(value))
{
_queryContainer &= Wrap(selector, (a, w) => w.MatchPhrase(r => r.Field(a).Query(value.TrimQuotes())));
}
else if (value.HasOtherLetter() || IsExactly(value))
{
_queryContainer &= Wrap(selector, (a, w) => w.Match(r => r.Field(a).Query(value.TrimQuotes())));
}
else
{
if (IsPhrase(value))
{
_queryContainer &= Wrap(selector, (a, w) => w.MatchPhrase(r => r.Field(a).Query(value.TrimQuotes())));
}
else if (value.HasOtherLetter() || IsExactly(value))
{
_queryContainer &= Wrap(selector, (a, w) => w.Match(r => r.Field(a).Query(value.TrimQuotes())));
var phrase = value.Split(' ');
foreach (var p in phrase)
{
var p1 = p;
_queryContainer &= Wrap(selector, (a, w) => w.Wildcard(r => r.Field(a).Value(p1.WrapAsterisk())));
}
}
else
{
if (IsPhrase(value))
{
var phrase = value.Split(' ');
foreach (var p in phrase)
{
var p1 = p;
_queryContainer &= Wrap(selector, (a, w) => w.Wildcard(r => r.Field(a).Value(p1.WrapAsterisk())));
}
}
else
{
_queryContainer &= Wrap(selector, (a, w) => w.Wildcard(r => r.Field(a).Value(value.WrapAsterisk())));
}
_queryContainer &= Wrap(selector, (a, w) => w.Wildcard(r => r.Field(a).Value(value.WrapAsterisk())));
}
if (IsExactly(value))
{
_queryContainer |= Wrap(selector, (a, w) => w.MatchPhrase(r => r.Field(a).Query(value)));
}
return this;
}
public Selector<T> Match(Expression<Func<T, object[]>> selector, string value)
if (IsExactly(value))
{
Match(() => ((NewArrayExpression)selector.Body).Expressions.ToArray(), value);
return this;
_queryContainer |= Wrap(selector, (a, w) => w.MatchPhrase(r => r.Field(a).Query(value)));
}
public Selector<T> MatchAll(string value)
{
Match(() =>
{
var t = _serviceProvider.GetService<T>();
var searchSettingsHelper = _serviceProvider.GetService<SearchSettingsHelper>();
return this;
}
return ((NewArrayExpression)(t.GetSearchContentFields(searchSettingsHelper)).Body).Expressions.ToArray();
},
value);
return this;
}
public Selector<T> Sort(Expression<Func<T, object>> selector, bool asc)
{
_sortContainerDescriptor = _sortContainerDescriptor.Field(selector, asc ? SortOrder.Ascending : SortOrder.Descending);
return this;
}
public Selector<T> Limit(int newOffset = 0, int newLimit = 1000)
{
offset = newOffset;
_limit = newLimit;
return this;
}
public Selector<T> Or(Expression<Func<Selector<T>, Selector<T>>> selectorLeft, Expression<Func<Selector<T>, Selector<T>>> selectorRight)
{
return new Selector<T>(_serviceProvider)
{
_queryContainer = _queryContainer &
(selectorLeft.Compile()(new Selector<T>(_serviceProvider))._queryContainer |
selectorRight.Compile()(new Selector<T>(_serviceProvider))._queryContainer)
};
}
public static Selector<T> Or(Selector<T> selectorLeft, Selector<T> selectorRight)
{
return new Selector<T>(selectorLeft._serviceProvider)
{
_queryContainer = selectorLeft._queryContainer | selectorRight._queryContainer
};
}
public Selector<T> Not(Expression<Func<Selector<T>, Selector<T>>> selector)
{
return new Selector<T>(_serviceProvider)
{
_queryContainer = _queryContainer & !selector.Compile()(new Selector<T>(_serviceProvider))._queryContainer
};
}
public static Selector<T> Not(Selector<T> selector)
{
return new Selector<T>(selector._serviceProvider)
{
_queryContainer = !selector._queryContainer
};
}
public static Selector<T> operator &(Selector<T> selectorLeft, Selector<T> selectorRight)
{
return new Selector<T>(selectorLeft._serviceProvider)
{
_queryContainer = selectorLeft._queryContainer & selectorRight._queryContainer
};
}
public static Selector<T> operator |(Selector<T> selectorLeft, Selector<T> selectorRight)
{
return Or(selectorLeft, selectorRight);
}
public static Selector<T> operator !(Selector<T> selector)
{
return Not(selector);
}
internal Func<SearchDescriptor<T>, ISearchRequest> GetDescriptor(BaseIndexer<T> indexer, bool onlyId = false)
{
return s =>
{
var result = s
.Query(q => _queryContainer)
.Index(indexer.IndexName)
.Sort(r => _sortContainerDescriptor)
.From(offset)
.Size(_limit);
if (onlyId)
{
result = result.Source(r => r.Includes(a => a.Field("id")));
}
return result;
};
}
internal Func<DeleteByQueryDescriptor<T>, IDeleteByQueryRequest> GetDescriptorForDelete(BaseIndexer<T> indexer, bool immediately = true)
{
return s =>
{
var result = s
.Query(q => _queryContainer)
.Index(indexer.IndexName);
if (immediately)
{
result.Refresh();
}
return result;
};
}
internal Func<UpdateByQueryDescriptor<T>, IUpdateByQueryRequest> GetDescriptorForUpdate(BaseIndexer<T> indexer, Func<ScriptDescriptor, IScript> script, bool immediately = true)
{
return s =>
{
var result = s
.Query(q => _queryContainer)
.Index(indexer.IndexName)
.Script(script);
if (immediately)
{
result.Refresh();
}
return result;
};
}
private void Match(Func<Fields> propsFunc, string value)
{
if (string.IsNullOrEmpty(value))
{
return;
}
value = value.PrepareToSearch();
var props = propsFunc();
if (IsExactlyPhrase(value))
{
_queryContainer = _queryContainer && MultiPhrase(props, value.TrimQuotes());
}
else if (value.HasOtherLetter() || IsExactly(value))
{
_queryContainer = _queryContainer && MultiMatch(props, value.TrimQuotes());
}
else
{
if (IsPhrase(value))
{
var phrase = value.Split(' ');
foreach (var p in phrase)
{
_queryContainer = _queryContainer && MultiWildCard(props, p.WrapAsterisk());
}
}
else
{
_queryContainer = _queryContainer && MultiWildCard(props, value.WrapAsterisk());
}
}
if (IsExactly(value))
{
_queryContainer = _queryContainer || MultiPhrase(props, value);
}
}
private QueryContainer Wrap(Field fieldSelector, Func<Field, QueryContainerDescriptor<T>, QueryContainer> selector)
{
var path = IsNested(fieldSelector);
if (string.IsNullOrEmpty(path) &&
!string.IsNullOrEmpty(fieldSelector.Name) &&
fieldSelector.Name.IndexOf(".", StringComparison.InvariantCulture) > 0)
{
var splitted = fieldSelector.Name.Split(':')[1];
path = splitted.Split('.')[0];
fieldSelector = new Field(splitted);
}
if (!string.IsNullOrEmpty(path))
{
return _queryContainerDescriptor.Nested(a => a.Query(b => selector(fieldSelector, b)).Path(path));
}
return selector(fieldSelector, _queryContainerDescriptor);
}
private string IsNested(Field selector)
{
if (!(selector.Expression is LambdaExpression lambdaExpression))
{
return null;
}
if (lambdaExpression.Body is MethodCallExpression methodCallExpression && methodCallExpression.Arguments.Count > 1)
{
return !(methodCallExpression.Arguments[0] is MemberExpression pathMember)
? null
: pathMember.Member.Name.ToLowerCamelCase();
}
return null;
}
private bool IsPhrase(string searchText)
{
return searchText.Contains(" ") || searchText.Contains("\r\n") || searchText.Contains("\n");
}
private bool IsExactlyPhrase(string searchText)
{
return IsPhrase(searchText) && IsExactly(searchText);
}
private bool IsExactly(string searchText)
{
return searchText.StartsWith("\"") && searchText.EndsWith("\"");
}
private QueryContainer MultiMatch(Fields fields, string value)
{
var qcWildCard = new QueryContainer();
foreach (var field in fields)
{
var field1 = field;
qcWildCard = qcWildCard || Wrap(field1, (a, w) => w.Match(r => r.Field(a).Query(value.ToLower())));
}
return qcWildCard;
}
private QueryContainer MultiWildCard(Fields fields, string value)
{
var qcWildCard = new QueryContainer();
foreach (var field in fields)
{
qcWildCard = qcWildCard || Wrap(field, (a, w) => w.Wildcard(r => r.Field(a).Value(value)));
}
return qcWildCard;
}
private QueryContainer MultiPhrase(Fields fields, string value)
{
var qcWildCard = new QueryContainer();
foreach (var field in fields)
{
qcWildCard = qcWildCard || Wrap(field, (a, w) => w.MatchPhrase(r => r.Field(a).Query(value.ToLower())));
}
return qcWildCard;
}
}
internal static class StringExtension
public Selector<T> Match(Expression<Func<T, object[]>> selector, string value)
{
private static bool Any(this string value, UnicodeCategory category)
{
return !string.IsNullOrWhiteSpace(value)
&& value.Any(@char => char.GetUnicodeCategory(@char) == category);
}
Match(() => ((NewArrayExpression)selector.Body).Expressions.ToArray(), value);
public static bool HasOtherLetter(this string value)
{
return value.Any(UnicodeCategory.OtherLetter);
}
return this;
}
public static string WrapAsterisk(this string value)
public Selector<T> MatchAll(string value)
{
Match(() =>
{
var result = value;
var t = _serviceProvider.GetService<T>();
var searchSettingsHelper = _serviceProvider.GetService<SearchSettingsHelper>();
if (!value.Contains("*") && !value.Contains("?"))
return ((NewArrayExpression)(t.GetSearchContentFields(searchSettingsHelper)).Body).Expressions.ToArray();
},
value);
return this;
}
public Selector<T> Sort(Expression<Func<T, object>> selector, bool asc)
{
_sortContainerDescriptor = _sortContainerDescriptor.Field(selector, asc ? SortOrder.Ascending : SortOrder.Descending);
return this;
}
public Selector<T> Limit(int newOffset = 0, int newLimit = 1000)
{
offset = newOffset;
_limit = newLimit;
return this;
}
public Selector<T> Or(Expression<Func<Selector<T>, Selector<T>>> selectorLeft, Expression<Func<Selector<T>, Selector<T>>> selectorRight)
{
return new Selector<T>(_serviceProvider)
{
_queryContainer = _queryContainer &
(selectorLeft.Compile()(new Selector<T>(_serviceProvider))._queryContainer |
selectorRight.Compile()(new Selector<T>(_serviceProvider))._queryContainer)
};
}
public static Selector<T> Or(Selector<T> selectorLeft, Selector<T> selectorRight)
{
return new Selector<T>(selectorLeft._serviceProvider)
{
_queryContainer = selectorLeft._queryContainer | selectorRight._queryContainer
};
}
public Selector<T> Not(Expression<Func<Selector<T>, Selector<T>>> selector)
{
return new Selector<T>(_serviceProvider)
{
_queryContainer = _queryContainer & !selector.Compile()(new Selector<T>(_serviceProvider))._queryContainer
};
}
public static Selector<T> Not(Selector<T> selector)
{
return new Selector<T>(selector._serviceProvider)
{
_queryContainer = !selector._queryContainer
};
}
public static Selector<T> operator &(Selector<T> selectorLeft, Selector<T> selectorRight)
{
return new Selector<T>(selectorLeft._serviceProvider)
{
_queryContainer = selectorLeft._queryContainer & selectorRight._queryContainer
};
}
public static Selector<T> operator |(Selector<T> selectorLeft, Selector<T> selectorRight)
{
return Or(selectorLeft, selectorRight);
}
public static Selector<T> operator !(Selector<T> selector)
{
return Not(selector);
}
internal Func<SearchDescriptor<T>, ISearchRequest> GetDescriptor(BaseIndexer<T> indexer, bool onlyId = false)
{
return s =>
{
var result = s
.Query(q => _queryContainer)
.Index(indexer.IndexName)
.Sort(r => _sortContainerDescriptor)
.From(offset)
.Size(_limit);
if (onlyId)
{
result = "*" + result + "*";
result = result.Source(r => r.Includes(a => a.Field("id")));
}
return result;
};
}
internal Func<DeleteByQueryDescriptor<T>, IDeleteByQueryRequest> GetDescriptorForDelete(BaseIndexer<T> indexer, bool immediately = true)
{
return s =>
{
var result = s
.Query(q => _queryContainer)
.Index(indexer.IndexName);
if (immediately)
{
result.Refresh();
}
return result;
};
}
internal Func<UpdateByQueryDescriptor<T>, IUpdateByQueryRequest> GetDescriptorForUpdate(BaseIndexer<T> indexer, Func<ScriptDescriptor, IScript> script, bool immediately = true)
{
return s =>
{
var result = s
.Query(q => _queryContainer)
.Index(indexer.IndexName)
.Script(script);
if (immediately)
{
result.Refresh();
}
return result;
};
}
private void Match(Func<Fields> propsFunc, string value)
{
if (string.IsNullOrEmpty(value))
{
return;
}
public static string ReplaceBackslash(this string value)
value = value.PrepareToSearch();
var props = propsFunc();
if (IsExactlyPhrase(value))
{
return value.Replace("\\", "\\\\");
_queryContainer = _queryContainer && MultiPhrase(props, value.TrimQuotes());
}
else if (value.HasOtherLetter() || IsExactly(value))
{
_queryContainer = _queryContainer && MultiMatch(props, value.TrimQuotes());
}
else
{
if (IsPhrase(value))
{
var phrase = value.Split(' ');
foreach (var p in phrase)
{
_queryContainer = _queryContainer && MultiWildCard(props, p.WrapAsterisk());
}
}
else
{
_queryContainer = _queryContainer && MultiWildCard(props, value.WrapAsterisk());
}
}
public static string TrimQuotes(this string value)
if (IsExactly(value))
{
return value.Trim('\"');
_queryContainer = _queryContainer || MultiPhrase(props, value);
}
}
private QueryContainer Wrap(Field fieldSelector, Func<Field, QueryContainerDescriptor<T>, QueryContainer> selector)
{
var path = IsNested(fieldSelector);
if (string.IsNullOrEmpty(path) &&
!string.IsNullOrEmpty(fieldSelector.Name) &&
fieldSelector.Name.IndexOf(".", StringComparison.InvariantCulture) > 0)
{
var splitted = fieldSelector.Name.Split(':')[1];
path = splitted.Split('.')[0];
fieldSelector = new Field(splitted);
}
public static string PrepareToSearch(this string value)
if (!string.IsNullOrEmpty(path))
{
return value.ReplaceBackslash().ToLowerInvariant().Replace('ё', 'е').Replace('Ё', 'Е');
}
}
return _queryContainerDescriptor.Nested(a => a.Query(b => selector(fieldSelector, b)).Path(path));
}
return selector(fieldSelector, _queryContainerDescriptor);
}
private string IsNested(Field selector)
{
if (!(selector.Expression is LambdaExpression lambdaExpression))
{
return null;
}
if (lambdaExpression.Body is MethodCallExpression methodCallExpression && methodCallExpression.Arguments.Count > 1)
{
return !(methodCallExpression.Arguments[0] is MemberExpression pathMember)
? null
: pathMember.Member.Name.ToLowerCamelCase();
}
return null;
}
private bool IsPhrase(string searchText)
{
return searchText.Contains(" ") || searchText.Contains("\r\n") || searchText.Contains("\n");
}
private bool IsExactlyPhrase(string searchText)
{
return IsPhrase(searchText) && IsExactly(searchText);
}
private bool IsExactly(string searchText)
{
return searchText.StartsWith("\"") && searchText.EndsWith("\"");
}
private QueryContainer MultiMatch(Fields fields, string value)
{
var qcWildCard = new QueryContainer();
foreach (var field in fields)
{
var field1 = field;
qcWildCard = qcWildCard || Wrap(field1, (a, w) => w.Match(r => r.Field(a).Query(value.ToLower())));
}
return qcWildCard;
}
private QueryContainer MultiWildCard(Fields fields, string value)
{
var qcWildCard = new QueryContainer();
foreach (var field in fields)
{
qcWildCard = qcWildCard || Wrap(field, (a, w) => w.Wildcard(r => r.Field(a).Value(value)));
}
return qcWildCard;
}
private QueryContainer MultiPhrase(Fields fields, string value)
{
var qcWildCard = new QueryContainer();
foreach (var field in fields)
{
qcWildCard = qcWildCard || Wrap(field, (a, w) => w.MatchPhrase(r => r.Field(a).Query(value.ToLower())));
}
return qcWildCard;
}
}
internal static class StringExtension
{
private static bool Any(this string value, UnicodeCategory category)
{
return !string.IsNullOrWhiteSpace(value)
&& value.Any(@char => char.GetUnicodeCategory(@char) == category);
}
public static bool HasOtherLetter(this string value)
{
return value.Any(UnicodeCategory.OtherLetter);
}
public static string WrapAsterisk(this string value)
{
var result = value;
if (!value.Contains("*") && !value.Contains("?"))
{
result = "*" + result + "*";
}
return result;
}
public static string ReplaceBackslash(this string value)
{
return value.Replace("\\", "\\\\");
}
public static string TrimQuotes(this string value)
{
return value.Trim('\"');
}
public static string PrepareToSearch(this string value)
{
return value.ReplaceBackslash().ToLowerInvariant().Replace('ё', 'е').Replace('Ё', 'Е');
}
}

View File

@ -1,8 +1,7 @@
namespace ASC.ElasticSearch.Core
namespace ASC.ElasticSearch.Core;
public class State
{
public class State
{
public string Indexing { get; set; }
public DateTime? LastIndexed { get; set; }
}
public string Indexing { get; set; }
public DateTime? LastIndexed { get; set; }
}

File diff suppressed because it is too large Load Diff

View File

@ -23,41 +23,41 @@
*
*/
namespace ASC.ElasticSearch
namespace ASC.ElasticSearch;
[Singletone]
public class Client
{
[Singletone]
public class Client
public ElasticClient Instance
{
public ElasticClient Instance
get
{
get
if (_client != null)
{
return _client;
}
lock (_locker)
{
if (_client != null)
{
return _client;
}
lock (_locker)
using var scope = _serviceProvider.CreateScope();
var CoreConfiguration = _serviceProvider.GetService<CoreConfiguration>();
var launchSettings = CoreConfiguration.GetSection<Settings>(Tenant.DEFAULT_TENANT) ?? _settings;
var uri = new Uri(string.Format("{0}://{1}:{2}", launchSettings.Scheme, launchSettings.Host, launchSettings.Port));
var settings = new ConnectionSettings(new SingleNodeConnectionPool(uri))
.RequestTimeout(TimeSpan.FromMinutes(5))
.MaximumRetries(10)
.ThrowExceptions();
if (_logger.IsTraceEnabled)
{
if (_client != null)
settings.DisableDirectStreaming().PrettyJson().EnableDebugMode(r =>
{
return _client;
}
using var scope = _serviceProvider.CreateScope();
var CoreConfiguration = _serviceProvider.GetService<CoreConfiguration>();
var launchSettings = CoreConfiguration.GetSection<Settings>(Tenant.DEFAULT_TENANT) ?? _settings;
var uri = new Uri(string.Format("{0}://{1}:{2}", launchSettings.Scheme, launchSettings.Host, launchSettings.Port));
var settings = new ConnectionSettings(new SingleNodeConnectionPool(uri))
.RequestTimeout(TimeSpan.FromMinutes(5))
.MaximumRetries(10)
.ThrowExceptions();
if (_logger.IsTraceEnabled)
{
settings.DisableDirectStreaming().PrettyJson().EnableDebugMode(r =>
{
//Log.Trace(r.DebugInformation);
//if (r.RequestBodyInBytes != null)
@ -66,65 +66,64 @@ namespace ASC.ElasticSearch
//}
if (r.HttpStatusCode != null && (r.HttpStatusCode == 403 || r.HttpStatusCode == 500) && r.ResponseBodyInBytes != null)
{
_logger.TraceFormat("Response: {0}", Encoding.UTF8.GetString(r.ResponseBodyInBytes));
}
});
}
try
{
if (Ping(new ElasticClient(settings)))
{
_client = new ElasticClient(settings);
_client.Ingest.PutPipeline("attachments", p => p
.Processors(pp => pp
.Attachment<Attachment>(a => a.Field("document.data").TargetField("document.attachment"))
));
_logger.TraceFormat("Response: {0}", Encoding.UTF8.GetString(r.ResponseBodyInBytes));
}
}
catch (Exception e)
{
_logger.Error(e);
}
return _client;
});
}
try
{
if (Ping(new ElasticClient(settings)))
{
_client = new ElasticClient(settings);
_client.Ingest.PutPipeline("attachments", p => p
.Processors(pp => pp
.Attachment<Attachment>(a => a.Field("document.data").TargetField("document.attachment"))
));
}
}
catch (Exception e)
{
_logger.Error(e);
}
return _client;
}
}
private static volatile ElasticClient _client;
private static readonly object _locker = new object();
private readonly ILog _logger;
private readonly Settings _settings;
private readonly IServiceProvider _serviceProvider;
public Client(IOptionsMonitor<ILog> option, IServiceProvider serviceProvider, Settings settings)
{
_logger = option.Get("ASC.Indexer");
_settings = settings;
_serviceProvider = serviceProvider;
}
public bool Ping()
{
return Ping(Instance);
}
private bool Ping(ElasticClient elasticClient)
{
if (elasticClient == null)
{
return false;
}
var result = elasticClient.Ping(new PingRequest());
_logger.DebugFormat("Ping {0}", result.DebugInformation);
return result.IsValid;
}
}
private static volatile ElasticClient _client;
private static readonly object _locker = new object();
private readonly ILog _logger;
private readonly Settings _settings;
private readonly IServiceProvider _serviceProvider;
public Client(IOptionsMonitor<ILog> option, IServiceProvider serviceProvider, Settings settings)
{
_logger = option.Get("ASC.Indexer");
_settings = settings;
_serviceProvider = serviceProvider;
}
public bool Ping()
{
return Ping(Instance);
}
private bool Ping(ElasticClient elasticClient)
{
if (elasticClient == null)
{
return false;
}
var result = elasticClient.Ping(new PingRequest());
_logger.DebugFormat("Ping {0}", result.DebugInformation);
return result.IsValid;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -23,14 +23,13 @@
*
*/
namespace ASC.ElasticSearch
namespace ASC.ElasticSearch;
public interface IIndexer
{
public interface IIndexer
{
string IndexName { get; }
string IndexName { get; }
void IndexAll();
void IndexAll();
Task ReIndex();
}
Task ReIndex();
}

View File

@ -23,115 +23,98 @@
*
*/
namespace ASC.ElasticSearch
namespace ASC.ElasticSearch;
[Singletone(Additional = typeof(ServiceLauncherExtension))]
public class ElasticSearchIndexService : IHostedService, IDisposable
{
[Singletone(Additional = typeof(ServiceLauncherExtension))]
public class ElasticSearchIndexService : IHostedService, IDisposable
private readonly ILog _logger;
private readonly ICacheNotify<AscCacheItem> _notify;
private readonly ICacheNotify<IndexAction> _indexNotify;
private readonly IServiceProvider _serviceProvider;
private readonly CancellationTokenSource _cancellationTokenSource;
private readonly TimeSpan _period;
private Timer _timer = null!;
private bool _isStarted;
public ElasticSearchIndexService(
IOptionsMonitor<ILog> options,
ICacheNotify<AscCacheItem> notify,
ICacheNotify<IndexAction> indexNotify,
IServiceProvider serviceProvider,
Settings settings)
{
private readonly ILog _logger;
private readonly ICacheNotify<AscCacheItem> _notify;
private readonly ICacheNotify<IndexAction> _indexNotify;
private readonly IServiceProvider _serviceProvider;
private readonly CancellationTokenSource _cancellationTokenSource;
private readonly TimeSpan _period;
private Timer _timer = null!;
private bool _isStarted;
_logger = options.Get("ASC.Indexer");
_notify = notify;
_indexNotify = indexNotify;
_serviceProvider = serviceProvider;
_cancellationTokenSource = new CancellationTokenSource();
_period = TimeSpan.FromMinutes(settings.Period.Value);
}
public ElasticSearchIndexService(
IOptionsMonitor<ILog> options,
ICacheNotify<AscCacheItem> notify,
ICacheNotify<IndexAction> indexNotify,
IServiceProvider serviceProvider,
Settings settings)
public Task StartAsync(CancellationToken cancellationToken)
{
_logger.Info("ElasticSearch Index Service running.");
try
{
_logger = options.Get("ASC.Indexer");
_notify = notify;
_indexNotify = indexNotify;
_serviceProvider = serviceProvider;
_cancellationTokenSource = new CancellationTokenSource();
_period = TimeSpan.FromMinutes(settings.Period.Value);
}
public Task StartAsync(CancellationToken cancellationToken)
{
_logger.Info("ElasticSearch Index Service running.");
try
_notify.Subscribe(async (item) =>
{
_notify.Subscribe(async (item) =>
while (_isStarted)
{
while (_isStarted)
{
await Task.Delay(10000);
}
IndexAll(true);
}, CacheNotifyAction.Any);
}
catch (Exception e)
{
_logger.Error("Subscribe on start", e);
}
var task = new Task(async () =>
{
using var scope = _serviceProvider.CreateScope();
var scopeClass = scope.ServiceProvider.GetService<ServiceLauncherScope>();
var (factoryIndexer, service) = scopeClass;
while (!factoryIndexer.CheckState(false))
{
if (_cancellationTokenSource.IsCancellationRequested)
{
return;
}
await Task.Delay(10000);
}
service.Subscribe();
_timer = new Timer(_ => IndexAll(), null, TimeSpan.Zero, TimeSpan.Zero);
}, _cancellationTokenSource.Token, TaskCreationOptions.LongRunning);
task.ConfigureAwait(false);
task.Start();
return Task.CompletedTask;
IndexAll(true);
}, CacheNotifyAction.Any);
}
catch (Exception e)
{
_logger.Error("Subscribe on start", e);
}
public Task StopAsync(CancellationToken cancellationToken)
var task = new Task(async () =>
{
_logger.Info("ElasticSearch Index Service is stopping.");
_isStarted = false;
_timer?.Change(Timeout.Infinite, 0);
_cancellationTokenSource.Cancel();
return Task.CompletedTask;
}
public void IndexProduct(IFactoryIndexer product, bool reindex)
{
if (reindex)
using var scope = _serviceProvider.CreateScope();
var scopeClass = scope.ServiceProvider.GetService<ServiceLauncherScope>();
var (factoryIndexer, service) = scopeClass;
while (!factoryIndexer.CheckState(false))
{
try
if (_cancellationTokenSource.IsCancellationRequested)
{
if (!_isStarted)
{
return;
}
return;
}
_logger.DebugFormat("Product reindex {0}", product.IndexName);
product.ReIndex();
}
catch (Exception e)
{
_logger.Error(e);
_logger.ErrorFormat("Product reindex {0}", product.IndexName);
}
await Task.Delay(10000);
}
service.Subscribe();
_timer = new Timer(_ => IndexAll(), null, TimeSpan.Zero, TimeSpan.Zero);
}, _cancellationTokenSource.Token, TaskCreationOptions.LongRunning);
task.ConfigureAwait(false);
task.Start();
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
_logger.Info("ElasticSearch Index Service is stopping.");
_isStarted = false;
_timer?.Change(Timeout.Infinite, 0);
_cancellationTokenSource.Cancel();
return Task.CompletedTask;
}
public void IndexProduct(IFactoryIndexer product, bool reindex)
{
if (reindex)
{
try
{
if (!_isStarted)
@ -139,85 +122,101 @@ namespace ASC.ElasticSearch
return;
}
_logger.DebugFormat("Product {0}", product.IndexName);
_indexNotify.Publish(new IndexAction() { Indexing = product.IndexName, LastIndexed = 0 }, CacheNotifyAction.Any);
product.IndexAll();
_logger.DebugFormat("Product reindex {0}", product.IndexName);
product.ReIndex();
}
catch (Exception e)
{
_logger.Error(e);
_logger.ErrorFormat("Product {0}", product.IndexName);
_logger.ErrorFormat("Product reindex {0}", product.IndexName);
}
}
private void IndexAll(bool reindex = false)
try
{
try
if (!_isStarted)
{
_timer.Change(Timeout.Infinite, Timeout.Infinite);
_isStarted = true;
return;
}
using (var scope = _serviceProvider.CreateScope())
_logger.DebugFormat("Product {0}", product.IndexName);
_indexNotify.Publish(new IndexAction() { Indexing = product.IndexName, LastIndexed = 0 }, CacheNotifyAction.Any);
product.IndexAll();
}
catch (Exception e)
{
_logger.Error(e);
_logger.ErrorFormat("Product {0}", product.IndexName);
}
}
private void IndexAll(bool reindex = false)
{
try
{
_timer.Change(Timeout.Infinite, Timeout.Infinite);
_isStarted = true;
using (var scope = _serviceProvider.CreateScope())
{
var wrappers = scope.ServiceProvider.GetService<IEnumerable<IFactoryIndexer>>();
Parallel.ForEach(wrappers, wrapper =>
{
var wrappers = scope.ServiceProvider.GetService<IEnumerable<IFactoryIndexer>>();
Parallel.ForEach(wrappers, wrapper =>
using (var scope = _serviceProvider.CreateScope())
{
using (var scope = _serviceProvider.CreateScope())
{
var w = (IFactoryIndexer)scope.ServiceProvider.GetService(wrapper.GetType());
IndexProduct(w, reindex);
}
});
}
_timer.Change(_period, _period);
_indexNotify.Publish(new IndexAction() { Indexing = "", LastIndexed = DateTime.Now.Ticks }, CacheNotifyAction.Any);
_isStarted = false;
var w = (IFactoryIndexer)scope.ServiceProvider.GetService(wrapper.GetType());
IndexProduct(w, reindex);
}
});
}
catch (Exception e)
{
_logger.Fatal("IndexAll", e);
throw;
}
_timer.Change(_period, _period);
_indexNotify.Publish(new IndexAction() { Indexing = "", LastIndexed = DateTime.Now.Ticks }, CacheNotifyAction.Any);
_isStarted = false;
}
public void Dispose()
catch (Exception e)
{
var handle = new AutoResetEvent(false);
_logger.Fatal("IndexAll", e);
if (!(bool)_timer?.Dispose(handle))
throw new Exception("Timer already disposed");
handle.WaitOne();
throw;
}
}
[Scope]
public class ServiceLauncherScope
public void Dispose()
{
private readonly FactoryIndexer _factoryIndexer;
private readonly Service.ElasticSearchService _service;
var handle = new AutoResetEvent(false);
public ServiceLauncherScope(FactoryIndexer factoryIndexer, Service.ElasticSearchService service)
{
_factoryIndexer = factoryIndexer;
_service = service;
}
if (!(bool)_timer?.Dispose(handle))
throw new Exception("Timer already disposed");
public void Deconstruct(out FactoryIndexer factoryIndexer, out Service.ElasticSearchService service)
{
factoryIndexer = _factoryIndexer;
service = _service;
}
}
public class ServiceLauncherExtension
{
public static void Register(DIHelper services)
{
services.TryAdd<ServiceLauncherScope>();
}
handle.WaitOne();
}
}
[Scope]
public class ServiceLauncherScope
{
private readonly FactoryIndexer _factoryIndexer;
private readonly Service.ElasticSearchService _service;
public ServiceLauncherScope(FactoryIndexer factoryIndexer, Service.ElasticSearchService service)
{
_factoryIndexer = factoryIndexer;
_service = service;
}
public void Deconstruct(out FactoryIndexer factoryIndexer, out Service.ElasticSearchService service)
{
factoryIndexer = _factoryIndexer;
service = _service;
}
}
public class ServiceLauncherExtension
{
public static void Register(DIHelper services)
{
services.TryAdd<ServiceLauncherScope>();
}
}

View File

@ -23,100 +23,99 @@
*
*/
namespace ASC.ElasticSearch.Service
namespace ASC.ElasticSearch.Service;
[Singletone(Additional = typeof(ServiceExtension))]
public class ElasticSearchService
{
[Singletone(Additional = typeof(ServiceExtension))]
public class ElasticSearchService
private readonly IServiceProvider _serviceProvider;
private readonly ICacheNotify<ReIndexAction> _cacheNotify;
public ElasticSearchService(IServiceProvider serviceProvider, ICacheNotify<ReIndexAction> cacheNotify)
{
private readonly IServiceProvider _serviceProvider;
private readonly ICacheNotify<ReIndexAction> _cacheNotify;
public ElasticSearchService(IServiceProvider serviceProvider, ICacheNotify<ReIndexAction> cacheNotify)
{
_serviceProvider = serviceProvider;
_cacheNotify = cacheNotify;
}
public void Subscribe()
{
_cacheNotify.Subscribe((a) =>
{
ReIndex(a.Names.ToList(), a.Tenant);
}, CacheNotifyAction.Any);
}
public bool Support(string table)
{
return _serviceProvider.GetService<IEnumerable<IFactoryIndexer>>().Any(r => r.IndexName == table);
}
public void ReIndex(List<string> toReIndex, int tenant)
{
var allItems = _serviceProvider.GetService<IEnumerable<IFactoryIndexer>>().ToList();
var tasks = new List<Task>(toReIndex.Count);
foreach (var item in toReIndex)
{
var index = allItems.FirstOrDefault(r => r.IndexName == item);
if (index == null)
{
continue;
}
var generic = typeof(BaseIndexer<>);
var instance = (IIndexer)Activator.CreateInstance(generic.MakeGenericType(index.GetType()), index);
tasks.Add(instance.ReIndex());
}
if (!tasks.Any())
{
return;
}
Task.WhenAll(tasks).ContinueWith(r =>
{
using var scope = _serviceProvider.CreateScope();
var scopeClass = scope.ServiceProvider.GetService<ServiceScope>();
var (tenantManager, settingsManager) = scopeClass;
tenantManager.SetCurrentTenant(tenant);
settingsManager.ClearCache<SearchSettings>();
});
}
//public State GetState()
//{
// return new State
// {
// Indexing = Launcher.Indexing,
// LastIndexed = Launcher.LastIndexed
// };
//}
_serviceProvider = serviceProvider;
_cacheNotify = cacheNotify;
}
[Scope]
public class ServiceScope
public void Subscribe()
{
private readonly TenantManager _tenantManager;
private readonly SettingsManager _settingsManager;
public ServiceScope(TenantManager tenantManager, SettingsManager settingsManager)
_cacheNotify.Subscribe((a) =>
{
_tenantManager = tenantManager;
_settingsManager = settingsManager;
}
public void Deconstruct(out TenantManager tenantManager, out SettingsManager settingsManager)
{
tenantManager = _tenantManager;
settingsManager = _settingsManager;
}
ReIndex(a.Names.ToList(), a.Tenant);
}, CacheNotifyAction.Any);
}
internal class ServiceExtension
public bool Support(string table)
{
public static void Register(DIHelper services)
return _serviceProvider.GetService<IEnumerable<IFactoryIndexer>>().Any(r => r.IndexName == table);
}
public void ReIndex(List<string> toReIndex, int tenant)
{
var allItems = _serviceProvider.GetService<IEnumerable<IFactoryIndexer>>().ToList();
var tasks = new List<Task>(toReIndex.Count);
foreach (var item in toReIndex)
{
services.TryAdd<ServiceScope>();
var index = allItems.FirstOrDefault(r => r.IndexName == item);
if (index == null)
{
continue;
}
var generic = typeof(BaseIndexer<>);
var instance = (IIndexer)Activator.CreateInstance(generic.MakeGenericType(index.GetType()), index);
tasks.Add(instance.ReIndex());
}
if (!tasks.Any())
{
return;
}
Task.WhenAll(tasks).ContinueWith(r =>
{
using var scope = _serviceProvider.CreateScope();
var scopeClass = scope.ServiceProvider.GetService<ServiceScope>();
var (tenantManager, settingsManager) = scopeClass;
tenantManager.SetCurrentTenant(tenant);
settingsManager.ClearCache<SearchSettings>();
});
}
//public State GetState()
//{
// return new State
// {
// Indexing = Launcher.Indexing,
// LastIndexed = Launcher.LastIndexed
// };
//}
}
[Scope]
public class ServiceScope
{
private readonly TenantManager _tenantManager;
private readonly SettingsManager _settingsManager;
public ServiceScope(TenantManager tenantManager, SettingsManager settingsManager)
{
_tenantManager = tenantManager;
_settingsManager = settingsManager;
}
public void Deconstruct(out TenantManager tenantManager, out SettingsManager settingsManager)
{
tenantManager = _tenantManager;
settingsManager = _settingsManager;
}
}
internal class ServiceExtension
{
public static void Register(DIHelper services)
{
services.TryAdd<ServiceScope>();
}
}

View File

@ -23,64 +23,63 @@
*
*/
namespace ASC.ElasticSearch.Service
namespace ASC.ElasticSearch.Service;
[Singletone]
public class Settings
{
[Singletone]
public class Settings
public string Host
{
public string Host
{
get => _host ?? "localhost";
set => _host = value;
}
public int? Port
{
get => _port ?? 9200;
set => _port = value;
}
public string Scheme
{
get => _scheme ?? "http";
set => _scheme = value;
}
public int? Period
{
get => _period ?? 1;
set => _period = value;
}
public long? MaxContentLength
{
get => _maxContentLength ?? 100 * 1024 * 1024L;
set => _maxContentLength = value;
}
public long? MaxFileSize
{
get => _maxFileSize ?? 10 * 1024 * 1024L;
set => _maxFileSize = value;
}
public int? Threads
{
get => _threads ?? 1;
set => _threads = value;
}
public bool? HttpCompression
{
get => _httpCompression ?? true;
set => _httpCompression = value;
}
private string _host;
private int? _port;
private string _scheme;
private int? _period;
private long? _maxContentLength;
private long? _maxFileSize;
private int? _threads;
private bool? _httpCompression;
public Settings(ConfigurationExtension configuration)
{
configuration.GetSetting("elastic", this);
}
get => _host ?? "localhost";
set => _host = value;
}
}
public int? Port
{
get => _port ?? 9200;
set => _port = value;
}
public string Scheme
{
get => _scheme ?? "http";
set => _scheme = value;
}
public int? Period
{
get => _period ?? 1;
set => _period = value;
}
public long? MaxContentLength
{
get => _maxContentLength ?? 100 * 1024 * 1024L;
set => _maxContentLength = value;
}
public long? MaxFileSize
{
get => _maxFileSize ?? 10 * 1024 * 1024L;
set => _maxFileSize = value;
}
public int? Threads
{
get => _threads ?? 1;
set => _threads = value;
}
public bool? HttpCompression
{
get => _httpCompression ?? true;
set => _httpCompression = value;
}
private string _host;
private int? _port;
private string _scheme;
private int? _period;
private long? _maxContentLength;
private long? _maxFileSize;
private int? _threads;
private bool? _httpCompression;
public Settings(ConfigurationExtension configuration)
{
configuration.GetSetting("elastic", this);
}
}