Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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;
}
}
}
@vaggelis2018

This comment has been minimized.

Copy link

vaggelis2018 commented Jun 7, 2019

@hartviglarsen Hello man, What exactly is the product service? Does it queries all the products from the database?

@cleversolutions

This comment has been minimized.

Copy link

cleversolutions commented Jun 13, 2019

Awesome thanks!!

@hartviglarsen

This comment has been minimized.

Copy link
Owner Author

hartviglarsen commented Jun 16, 2019

@vaggelis2018 Sorry I completely missed your question!

Yes - In my local copy it simply queries a database and gets an IEnumerable<Product> :) (The product services is not a part of the CMS ;)).

Here are some examples from the CMS:
https://github.com/umbraco/Umbraco-CMS/blob/v8/dev/src/Umbraco.Examine/ContentIndexPopulator.cs#L61
https://github.com/umbraco/Umbraco-CMS/blob/v8/dev/src/Umbraco.Examine/MemberIndexPopulator.cs#L20

@cleversolutions

This comment has been minimized.

Copy link

cleversolutions commented Jun 17, 2019

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

@vaggelis2018

This comment has been minimized.

Copy link

vaggelis2018 commented Jun 17, 2019

@hartviglarsen thanks for your help!

@cleversolutions

This comment has been minimized.

Copy link

cleversolutions commented Jun 17, 2019

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);
        }
    }
@sebwells

This comment has been minimized.

Copy link

sebwells commented Jun 17, 2019

@hartviglarsen I have the same problem with the locking. Any ideas of the best solution please?

@perritoMedia

This comment has been minimized.

Copy link

perritoMedia commented Jul 3, 2019

@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));

@perritoMedia

This comment has been minimized.

Copy link

perritoMedia commented Jul 3, 2019

@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);

        }


    }

`

@hartviglarsen

This comment has been minimized.

Copy link
Owner Author

hartviglarsen commented Jul 5, 2019

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. :)

@cleversolutions

This comment has been minimized.

Copy link

cleversolutions commented Jul 6, 2019

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.

@Shazwazza

This comment has been minimized.

Copy link

Shazwazza commented Jul 8, 2019

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.

@AndersBrohus-MySupport

This comment has been minimized.

Copy link

AndersBrohus-MySupport commented Aug 29, 2019

Any news on this with index's not getting unlocked? :)

@cleversolutions

This comment has been minimized.

Copy link

cleversolutions commented Aug 29, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.