Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Stefan Kip 1614 posts 4131 karma points c-trib
    Mar 12, 2021 @ 11:29
    Stefan Kip
    0

    Customize Examine index - not being used on boot

    I'm customizing the Examine members index like this:

    public class CustomizeMemberIndexComponent : IComponent
    {
        private readonly IExamineManager _examineManager;
        private BaseIndexProvider _indexProvider;
    
        public CustomizeMemberIndexComponent(IExamineManager examineManager)
        {
            _examineManager = examineManager;
        }
    
        public void Initialize()
        {
            if (!_examineManager.TryGetIndex(Constants.UmbracoIndexes.MembersIndexName, out var index))
                return;
    
            var houseNumber = new FieldDefinition("houseNumber", FieldDefinitionTypes.Integer);
            index.FieldDefinitionCollection.TryAdd(houseNumber);
        }
    
        public void Terminate()
        {
        }
    }
    

    This works perfectly fine when I reindex via the back-office; the houseNumber property is indexed as number. But whenever the index gets recreated (which occurs on Azure), the houseNumber property is not index as number, but as FullTextType.
    I guess it's a timing issue and maybe I have to use the ComposeAfter attribute, but with what argument?

  • Dave Woestenborghs 3504 posts 12135 karma points MVP 9x admin c-trib
    Mar 12, 2021 @ 15:45
    Dave Woestenborghs
    0

    Hi Stefan,

    What is the runtime level of your composer ?

    Dave

  • Stefan Kip 1614 posts 4131 karma points c-trib
    Mar 12, 2021 @ 15:48
    Stefan Kip
    0

    Hey Dave!

    Sorry for not including it in the snippet:

    public class CustomizeMemberIndexComposer : ComponentComposer<CustomizeMemberIndexComponent>
    {
    }
    
  • Stefan Kip 1614 posts 4131 karma points c-trib
    Mar 16, 2021 @ 11:28
    Stefan Kip
    0

    @Dave any ideas? 🤞🏼

  • Dave Woestenborghs 3504 posts 12135 karma points MVP 9x admin c-trib
    Mar 16, 2021 @ 14:27
    Dave Woestenborghs
    0

    Sorry missed the notification.

    Maybe you can add the runtime attribute to your composer and set the minimum level to Run.

    I have it setup that way in a project without issues for content indexes : https://our.umbraco.com/Documentation/Implementation/Composing/#runtimelevel

    Dave

  • Stefan Kip 1614 posts 4131 karma points c-trib
    Mar 16, 2021 @ 14:30
    Stefan Kip
    0

    I've also switched to IUserComposer, doing some tests right now. I'll add the runtime attribute just in case as well, thanks.

  • Stefan Kip 1614 posts 4131 karma points c-trib
    Mar 16, 2021 @ 15:31
    Stefan Kip
    0

    Still no joy :-( Works fine on my machine, does not work fine on Azure and the production environment is having issues because of this :-(
    So frustrating!

  • Dave Woestenborghs 3504 posts 12135 karma points MVP 9x admin c-trib
    Mar 16, 2021 @ 16:01
    Dave Woestenborghs
    0

    Hi Stefan,

    Do you have all the correct settings configured for hosting on Azure ?

    https://our.umbraco.com/documentation/Getting-Started/Setup/Server-Setup/azure-web-apps

    Dave

  • Stefan Kip 1614 posts 4131 karma points c-trib
    Mar 16, 2021 @ 16:04
    Stefan Kip
    0

    Yeah everything is in place.
    Originally the title of the topic was "not being used on boot", but it's not in effect at all right now on prod. So when I rebuild the index manually, the houseNumber field will end up as a string every single time :-(

    I'm out of ideas here. FYI here's the current complete class:

    using System;
    using System.Linq;
    using Examine;
    using Examine.Providers;
    using Umbraco.Core;
    using Umbraco.Core.Composing;
    using Umbraco.Core.Logging;
    using Umbraco.Core.Services;
    using Umbraco.Examine;
    
    namespace Website.Core.Components
    {
        public class CustomizeMemberIndexComposer : IUserComposer
        {
            public void Compose(Composition composition)
            {
                composition.RegisterUnique<IUmbracoIndexConfig, CustomMemberIndexConfig>();
                composition.Components().Append<CustomizeMemberIndexComponent>();
            }
        }
    
        public class CustomizeMemberIndexComponent : IComponent
        {
            private readonly IExamineManager _examineManager;
            private readonly ILogger _logger;
            private BaseIndexProvider _indexProvider;
    
            public CustomizeMemberIndexComponent(IExamineManager examineManager, ILogger logger)
            {
                _examineManager = examineManager;
                _logger = logger;
            }
    
            public void Initialize()
            {
                if (!_examineManager.TryGetIndex(Constants.UmbracoIndexes.MembersIndexName, out var index))
                {
                    _logger.Error<CustomizeMemberIndexComponent>($"Index {Constants.UmbracoIndexes.MembersIndexName} not found");
                    return;
                }
    
                var houseNumber = new FieldDefinition("houseNumber", FieldDefinitionTypes.Integer);
                index.FieldDefinitionCollection.AddOrUpdate(houseNumber);
    
                _logger.Info<CustomizeMemberIndexComponent>($"Added houseNumber with type Integer to {Constants.UmbracoIndexes.MembersIndexName}");
    
                //we need to cast because BaseIndexProvider contains the TransformingIndexValues event
                if (!(index is BaseIndexProvider indexProvider))
                    throw new InvalidOperationException("Could not cast");
    
                _indexProvider = indexProvider;
    
                _indexProvider.TransformingIndexValues += IndexProviderOnTransformingIndexValues;
            }
    
            public void Terminate()
            {
                if (_indexProvider != null)
                {
                    _indexProvider.TransformingIndexValues -= IndexProviderOnTransformingIndexValues;
                }
            }
    
            private static void IndexProviderOnTransformingIndexValues(object sender, IndexingItemEventArgs e)
            {
                if (e.ValueSet.Category != IndexTypes.Member || !e.ValueSet.Values.ContainsKey("zipcode")) return;
    
                var zipcodeField = e.ValueSet.Values.Single(x => x.Key == "zipcode");
                e.ValueSet.Set("zipcode", zipcodeField.Value.Single().ToString().Replace(" ", string.Empty));
            }
        }
    
        public class CustomMemberIndexConfig : UmbracoIndexConfig, IUmbracoIndexConfig
        {
            public CustomMemberIndexConfig(IPublicAccessService publicAccessService) : base(publicAccessService)
            {
            }
    
            IValueSetValidator IUmbracoIndexConfig.GetMemberValueSetValidator()
            {
                var excludeFields = Constants.Conventions.Member.GetStandardPropertyTypeStubs().Keys;
    
                return new MemberValueSetValidator(null, null, null, excludeFields);
            }
        }
    }
    
  • Dave Woestenborghs 3504 posts 12135 karma points MVP 9x admin c-trib
    Mar 16, 2021 @ 17:58
    Dave Woestenborghs
    0

    Hi Stefan,

    I am not that familiar with the member indexing in V8.

    Is houseNumber a property on your member ? And does that end up in the index without your custom code ?

    So it might be a long shot, but could you try to remove it from the fieldcollection if it exists and add it.

    Instead of AddOrUpdate ?

    Also setting your composer using the ComposeAfter attribute and look in to the Umbraco source code where it builds the examine member index. So that you are sure your code runs last. Could be a race condition.

    Dave

  • Stefan Kip 1614 posts 4131 karma points c-trib
    Mar 18, 2021 @ 09:18
    Stefan Kip
    0

    With the debugger attached I see the houseNumber field has not been added yet at the point I'm adding it to the fieldcollection.
    Also tried ComposeAfter, didn't help.

    So on my local machine it always works correctly, also with a cold boot. On Azure it works 5 to 10% of the time. So it is some kind of timing issue I guess.

    Anyway, I worked around it by creating a custom members index with the fields I need. Which is also a whole lot quicker to (re)build than the members index. Like a few seconds vs. 10 to 15 minutes.

  • Dave Woestenborghs 3504 posts 12135 karma points MVP 9x admin c-trib
    Mar 18, 2021 @ 10:02
    Dave Woestenborghs
    0

    What version of Umbraco are you on ? I know in the latest version several fixes have been merged regarding the indexing of the members index.

  • Stefan Kip 1614 posts 4131 karma points c-trib
    Mar 18, 2021 @ 10:31
    Stefan Kip
    0

    It's v8.8.4. Can you point me in the direction of those fixes? Sounds interesting!

  • Dave Woestenborghs 3504 posts 12135 karma points MVP 9x admin c-trib
    Mar 18, 2021 @ 12:03
    Dave Woestenborghs
    0

    Hi Stefan,

    I see fixes related to member index in following releases : https://our.umbraco.com/download/releases/891 https://our.umbraco.com/download/releases/8120

    But there are some more examine related fixes in other releases as well.

    Dave

  • Stefan Kip 1614 posts 4131 karma points c-trib
    Mar 18, 2021 @ 13:25
    Stefan Kip
    0

    I'll do an upgrade soon :-)

  • Shannon Deminick 1526 posts 5272 karma points MVP 3x
    Apr 14, 2021 @ 23:20
    Shannon Deminick
    0

    This sounds very similar to the issue discussed here:

    https://github.com/umbraco/UmbracoDocs/issues/3115#issuecomment-819138962

    https://github.com/umbraco/Umbraco-CMS/issues/8893#issuecomment-819461693

    Which leads me to believe that Umbraco starts processing cache refresher instructions before the full boot sequence is complete thus locking the ability to change field types prematurely. I'm investigating this and will see what I can find.

    Side note - please be sure to also implement IUserComposer when using ComponentComposer since that only implements IComposer by default and typically all end user composers should be IUserComposer and prob also best to attribute with [RuntimeLevel(MinLevel = RuntimeLevel.Run)] since in most cases you don't want yours running during install/upgrade phases.

  • Stefan Kip 1614 posts 4131 karma points c-trib
    Apr 15, 2021 @ 09:07
    Stefan Kip
    0

    Isn't the IUserComposer using RuntimeLevel.Run by design already?

  • Shannon Deminick 1526 posts 5272 karma points MVP 3x
    Apr 15, 2021 @ 22:58
    Shannon Deminick
    0

    Nope. IUserComposer and RuntimeLevelAttribute are 2 different mechanisms.

    All IUserComposer does is ensure that it's run (along with any components it registers) after Umbraco's core composers. It's just an ordering thing.

    Also note, you will get an exception if you use ComposeAfter for a composer that has RuntimeLevelAttribute values that are different to the ones declared on your own composer.

  • Stefan Kip 1614 posts 4131 karma points c-trib
    Apr 16, 2021 @ 14:11
    Stefan Kip
    0

    Then the docs are wrong about it: https://our.umbraco.com/documentation/implementation/composing/#runtimelevel

    By default, any IUserComposer uses the Minimum Runtime Level of Run & thus does not need to explicitly add the attribute as shown in the example below.

  • Shannon Deminick 1526 posts 5272 karma points MVP 3x
    Apr 16, 2021 @ 20:40
Please Sign in or register to post replies

Write your reply to:

Draft