-
-
Save hartviglarsen/44743b32d4eea8eda3fb6d49b60dd547 to your computer and use it in GitHub Desktop.
public class ProductComponent : IComponent | |
{ | |
private readonly IExamineManager _examineManager; | |
private readonly ProductIndexCreator _productIndexCreator; | |
public ProductComponent (IExamineManager examineManager, ProductIndexCreator productIndexCreator) | |
{ | |
_examineManager = examineManager; | |
_productIndexCreator = productIndexCreator; | |
} | |
public void Initialize() | |
{ | |
foreach (var index in _productIndexCreator.Create()) | |
_examineManager.AddIndex(index); | |
} | |
public void Terminate() { } | |
} |
[RuntimeLevel(MinLevel = RuntimeLevel.Run)] | |
public class ProductComposer : IUserComposer | |
{ | |
public void Compose(Composition composition) | |
{ | |
composition.Components().Append<ProductComponent>(); | |
composition.RegisterUnique<ProductIndexValueSetBuilder>(); | |
composition.Register<ProductIndexPopulator>(Lifetime.Singleton); | |
composition.RegisterUnique<ProductIndexCreator>(); | |
} | |
} |
public class ProductIndexCreator : LuceneIndexCreator | |
{ | |
public override IEnumerable<IIndex> Create() | |
{ | |
var index = new LuceneIndex("ProductIndex", | |
CreateFileSystemLuceneDirectory("ProductIndex"), | |
new FieldDefinitionCollection( | |
new FieldDefinition("name", FieldDefinitionTypes.FullTextSortable), | |
new FieldDefinition("price", FieldDefinitionTypes.FullText) | |
), | |
new StandardAnalyzer(Version.LUCENE_30)); | |
return new[] { index }; | |
} | |
} |
public class ProductIndexPopulator : IndexPopulator | |
{ | |
private readonly ProductIndexValueSetBuilder _productValueSetBuilder; | |
private readonly IProductService _productService; | |
public ProductIndexPopulator(ProductIndexValueSetBuilder productValueSetBuilder, IProductService productService) | |
{ | |
_productValueSetBuilder = productValueSetBuilder; | |
_productService = productService; | |
RegisterIndex("ProductIndex"); | |
} | |
protected override void PopulateIndexes(IReadOnlyList<IIndex> indexes) | |
{ | |
var products = _productService.GetAll(); | |
if (products != null && products.Any()) | |
{ | |
foreach (var index in indexes) | |
{ | |
index.IndexItems(_productValueSetBuilder.GetValueSets(products)); | |
} | |
} | |
} | |
} |
public class ProductIndexValueSetBuilder : IValueSetBuilder<Product> | |
{ | |
public IEnumerable<ValueSet> GetValueSets(params Product[] products) | |
{ | |
foreach (var product in products) | |
{ | |
var indexValues = new Dictionary<string, object> | |
{ | |
["name"] = product.Name, | |
["price"] = product.Price | |
}; | |
var valueSet = new ValueSet(product.Id.ToString(), "product", indexValues); | |
yield return valueSet; | |
} | |
} | |
} |
@hartviglarsen thanks for your help!
Is it totally gross to force the index to be unlocked when we initialize it? I see Umbraco.Examine does essentially the same thing.
public void Initialize()
{
foreach (var index in _productIndexCreator.Create()){
// ensure the index is unlocked
if(index is LuceneIndex)
{
var luceneIndex = index as LuceneIndex;
var dir = luceneIndex.GetLuceneDirectory();
if (IndexWriter.IsLocked(dir))
{
_logger.Info(typeof(ExamineExtensions), "Forcing index {IndexerName} to be unlocked since it was left in a locked state", luceneIndex.Name);
IndexWriter.Unlock(dir);
}
}
_examineManager.AddIndex(index);
}
}
@hartviglarsen I have the same problem with the locking. Any ideas of the best solution please?
@hartviglarsen
I'm getting a conflict on type on this line - it says it can't convert an IEnumerable<Product>
to Product
index.IndexItems(_productValueSetBuilder.GetValueSets(products));
@hartviglarsen I have the same problem with the locking. Any ideas of the best solution please?
@sebwells
This is my code which stops the locking problem:
` public void Initialize()
{
//we want to tell examine to use a different fs lock instead of the default NativeFSFileLock which could cause problems if the AppDomain
//terminates and in some rare cases would only allow unlocking of the file if IIS is forcefully terminated. Instead we'll rely on the simplefslock
//which simply checks the existence of the lock file
DirectoryFactory.DefaultLockFactory = d =>
{
var simpleFsLockFactory = new NoPrefixSimpleFsLockFactory(d);
return simpleFsLockFactory;
};
foreach (var index in _orderIndexCreator.Create())
{
if (index is LuceneIndex luceneIndex)
{
var dir = luceneIndex.GetLuceneDirectory();
if (IndexWriter.IsLocked(dir))
{
//_logger.Info(typeof(ExamineExtensions), "Forcing index {IndexerName} to be unlocked since it was left in a locked state", luceneIndex.Name);
IndexWriter.Unlock(dir);
}
}
_examineManager.AddIndex(index);
}
}
`
I am not quite sure what the solution is apart from what has already been described (unlocking the index manually). I really suggest that you reach out to Shannon (Shazwazza) if are still having issues - my experience with Examine in V8 is still quite limited. :)
Thanks Morten, I’ve updated Umbraco.PDF for V8 so I’m sure I’ll get some feedback when Shannon reviews that PR. Thanks for this gist, it’s been super helpful.
Please don't manually unlock the index. There should be no need to do this and if it's locked then we need to figure out why since this will be covering up another issue. The usage of CreateFileSystemLuceneDirectory
makes sure that the correct lucene lock policy is used and then we already unlock all LuceneIndex's on startup based on this locking policy. The above code abides by this.
With all my tests locally I cannot replicate indexes being locked on restart or anything.
Am currently trying to figure this out with @hartviglarsen if he can replicate.
Any news on this with index's not getting unlocked? :)
Following the example... I got System.InvalidOperationException: 'Unable to resolve type: Umbraco.Web.Search.ExamineComponent, service name: OMG.... I'm getting mad to migrate to V8 ! :-)
One quick question @hartviglarsen, indexes I have created by following this pattern need to be manually deleted each time I start the site otherwise I get the error: Error: Lock obtain timed out: SimpleFSLock. Should the ProductComponent only create the index if it doesn't already exist, or should there be some cleanup somewhere to remove the lock (such as terminate)?
Thanks,
Evan