Developer forum

Forum » CMS - Standard features » New Index - Instances not used based on time

New Index - Instances not used based on time

Nuno Aguiar
Reply

Hi,

 

We noticed that the new index always uses the first instance, instead of getting the most recently built. Shouldn't it pull from the most recently built?

http://screencast.com/t/lQ13hVmt 

 

Best Regards,

Nuno Aguiar


Replies

 
Nicolai Høeg Pedersen
Reply

Hi Nuno

That is not how it is designed. You instance B will be used if A is unavailable - if it fails or if it is being updated.

 
Nuno Aguiar
Reply

Hi Nicolai,

 

I see and makes some sense, but at the same time, if you don't get the most recent index, there's no point in allowing more than 2 instances.

 

I was hoping we could create dummy instances with new fields to test whatever we needed, and don't touch instance A and/or B. In the end we could rebuild instances A and/or B and delete our test (C) instance.

 

I guess you can do the same thing if you create instance C and leave that as a backup, but sounds like a very simple change to get the most recent instance instead of the first one. Do you see any issues with it?

 

Best Regards,

Nuno Aguiar

 
Nicolai Høeg Pedersen
Reply

The idea is that you index all instances in a row. The reason you have more than one, is that they are unavailable when being indexed and if they somehow fail. If a build fails, the indexing stops and the solution keeps running on instance 2.

If you want to test, create a new index.

The concept of having more instances and choosing one of them is called Balancing in DW. How the balancing works is provider based on DW currently only have ActivePassive balancer that behaves like this. You can create your own balancer if you feel like having another behavior.

The ActivePasive balancer in DW:

using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

using Newtonsoft.Json;

namespace Dynamicweb.Indexing.Balancing
{
    /// <summary>
    /// Represents ActivePassive index balancer class
    /// </summary>
    public class ActivePassive : IIndexBalancer
    {
        private static readonly object lockObject = new object();

        private string ActiveInstance
        {
            get
            {
                lock (lockObject)
                {
                    try
                    {
                        var balancer = GetBalancerFileName();
                        return File.Exists(balancer) ? File.ReadAllText(balancer, Encoding.UTF8) : string.Empty;
                    }
                    catch
                    {
                        return string.Empty;
                    }
                }
            }
            set
            {
                lock (lockObject)
                {
                    try
                    {
                        var balancer = GetBalancerFileName();
                        File.WriteAllText(balancer, value, Encoding.UTF8);
                    }
                    catch
                    { }
                }
            }
        }

        /// <summary>
        /// Gets or sets index
        /// </summary>
        [JsonIgnore]
        [XmlIgnore]
        public IIndex Index { get; set; }

        /// <summary>
        /// Gets index provider instance
        /// </summary>
        /// <returns></returns>
        public IIndexProvider GetInstance()
        {
            var activeInstance = ActiveInstance;
            var candidate = !string.IsNullOrEmpty(activeInstance) && Index.Instances.ContainsKey(activeInstance)
                ? Index.Instances[activeInstance]
                : null;

            if (candidate == null || !candidate.IsAvailable)
                candidate = Index.Instances.Values.FirstOrDefault(i => i.IsAvailable);

            return candidate;
        }

        /// <summary>
        /// Sets active instance
        /// </summary>
        /// <param name="name"></param>
        public void SetInstance(string name)
        {
            ActiveInstance = name;
        }

        private string GetBalancerFileName()
        {
            return Path.Combine(IndexLocationResolver.ResolveLocation(Index), this.GetType().Name);
        }
    }
}

 

 
Nuno Aguiar
Reply

Hi Nicolai,

 

Gotcha. I was hoping we would get the EndTime of a given instance and could do something like this.

 

 if (candidate == null || !candidate.IsAvailable)
                candidate = Index.Instances.Values.OrderBy(i => i.EndTime).FirstOrDefault(i => i.IsAvailable);

 

Is there a way to get that time stamp and do this? Or would you be able to make that available on the Instances object?

 

Best Regards,

Nuno Aguiar

 
Nicolai Høeg Pedersen
Reply

An instance is basically a folder on disk, so you can have a look at some last write timestamps on that folder.

BR Nicolai

 
Nuno Aguiar
Reply

Hi Nicolai,

 

Thank you. We made the change for the required project and worked likea charm. Here's the code in case you would consider updating the core funcionality.

 

We left the original code commented.

 

        public IIndexProvider GetInstance()
        {
            /*
                     var activeInstance = ActiveInstance;
                     var candidate = !string.IsNullOrEmpty(activeInstance) && Index.Instances.ContainsKey(activeInstance)
                         ? Index.Instances[activeInstance]
                         : null;

                     if (candidate == null || !candidate.IsAvailable)
                         candidate = Index.Instances.Values.FirstOrDefault(i => i.IsAvailable);

                    return candidate;
            */

            // based folder of indexes
            var basedFolder = IndexLocationResolver.ResolveLocation(Index);
            // collection to find the most recent index
            Dictionary<string, System.DateTime> dic = new Dictionary<string, System.DateTime>();
            foreach (var instanceName in Index.Instances.Values.Where(i => i.IsAvailable).Select(i => i.Name))
            {
                // get datetime of build
                var buildDir = new DirectoryInfo(Path.Combine(basedFolder, instanceName));
                dic.Add(instanceName, buildDir.LastWriteTime);
            }

            // get the correct instance name
            ActiveInstance = dic.OrderByDescending(d => d.Value).First().Key;

            return Index.Instances[ActiveInstance];
        }

 

Best Regards,

Nuno Aguiar

 

You must be logged in to post in the forum