public void SetDomain(string path, string domains) { if (string.IsNullOrEmpty(path)) { throw new Exception("path null or empty"); } var meta = repo.GetPuckMeta().Where(x => x.Name == DBNames.DomainMapping).ToList(); if (string.IsNullOrEmpty(domains)) { var m = meta.Where(x => x.Key == path).ToList(); m.ForEach(x => { repo.DeletePuckMeta(x); }); if (m.Count > 0) { repo.SaveChanges(); } } else { var d = domains.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries) .Where(x => !string.IsNullOrEmpty(x) && !string.IsNullOrWhiteSpace(x)) .Select(x => x.ToLower()) .ToList(); d.ForEach(dd => { if (meta.Where(x => x.Value == dd && !x.Key.Equals(path)).Count() > 0) { throw new Exception($"domain {dd} already mapped to another node, unset first."); } }); var m = meta.Where(x => x.Key == path).ToList(); m.ForEach(x => { repo.DeletePuckMeta(x); }); d.ForEach(x => { var newMeta = new PuckMeta(); newMeta.Name = DBNames.DomainMapping; newMeta.Key = path; newMeta.Value = x; repo.AddPuckMeta(newMeta); }); repo.SaveChanges(); } StateHelper.UpdateDomainMappings(true); }
public static void Sync(CancellationToken ct) { bool taken = false; using (var scope = PuckCache.ServiceProvider.CreateScope()) { var contentService = scope.ServiceProvider.GetService <I_Content_Service>(); var searcher = scope.ServiceProvider.GetService <I_Content_Searcher>(); var repo = scope.ServiceProvider.GetService <I_Puck_Repository>(); var config = scope.ServiceProvider.GetService <IConfiguration>(); var cache = scope.ServiceProvider.GetService <IMemoryCache>(); try { Monitor.TryEnter(lck, lock_wait, ref taken); if (!taken) { return; } var serverName = ApiHelper.ServerName(); var meta = repo.GetPuckMeta().Where(x => x.Name == DBNames.SyncId && x.Key == serverName).FirstOrDefault(); if (meta == null) { return; } var syncId = int.Parse(meta.Value); var instructionsQuery = repo.GetPuckInstruction().Where(x => x.Id > syncId && x.ServerName != serverName); var instructionsCount = instructionsQuery.Count(); if (instructionsCount == 0) { return; } void handleMaxInstructions() { //todo, update settings and republish entire site if (!PuckCache.IsRepublishingEntireSite) { PuckCache.IsRepublishingEntireSite = true; var republishTask = contentService.RePublishEntireSite2(); republishTask.GetAwaiter().GetResult(); } StateHelper.UpdateTaskMappings(); StateHelper.UpdateRedirectMappings(); StateHelper.UpdatePathLocaleMappings(); StateHelper.UpdateDomainMappings(); StateHelper.UpdateCacheMappings(); StateHelper.UpdateCrops(); } void updateMaxInstructionId(List <PuckInstruction> instructions) { //update syncId //var maxInstructionId = instructions.Max(x => x.Id); var maxInstructionIdOrDefault = repo.GetPuckInstruction().Max(x => (int?)x.Id); var maxInstructionId = maxInstructionIdOrDefault.HasValue ? maxInstructionIdOrDefault.Value : 0; meta.Value = maxInstructionId.ToString(); repo.SaveChanges(); OnAfterSync(null, new AfterSyncEventArgs { Instructions = instructions }); } //dosync var hasPublishInstruction = false; var haveRepublished = false; if (instructionsCount > PuckCache.MaxSyncInstructions) { handleMaxInstructions(); updateMaxInstructionId(new List <PuckInstruction>()); } else { var instructions = instructionsQuery.ToList(); var instructionTotal = 0; instructions.ForEach(x => instructionTotal += x.Count); if (instructionTotal > PuckCache.MaxSyncInstructions) { handleMaxInstructions(); } else { foreach (var instruction in instructions) { try { if (instruction.InstructionKey == InstructionKeys.RemoveFromCache) { var keys = instruction.InstructionDetail.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); foreach (var key in keys) { cache.Remove(key); } } else if (instruction.InstructionKey == InstructionKeys.SetSearcher) { searcher.SetSearcher(); } else if (instruction.InstructionKey == InstructionKeys.Delete) { hasPublishInstruction = true; if (Indexer.CanWrite) { var qh = new QueryHelper <BaseModel>(prependTypeTerm: false); qh.SetQuery(instruction.InstructionDetail); var models = qh.GetAllNoCast(limit: int.MaxValue, fallBackToBaseModel: true); Indexer.Delete(models); } else { searcher.SetSearcher(); } } else if (instruction.InstructionKey == InstructionKeys.RepublishSite && !haveRepublished) { if (Indexer.CanWrite) { if (!PuckCache.IsRepublishingEntireSite) { PuckCache.IsRepublishingEntireSite = true; var republishTask = contentService.RePublishEntireSite2(); republishTask.GetAwaiter().GetResult(); hasPublishInstruction = true; } } else { searcher.SetSearcher(); } haveRepublished = true; } else if (instruction.InstructionKey == InstructionKeys.Publish) { hasPublishInstruction = true; var toIndex = new List <BaseModel>(); //instruction detail holds comma separated list of ids and variants in format id:variant,id:variant var idList = instruction.InstructionDetail.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (Indexer.CanWrite) { foreach (var idAndVariant in idList) { var idAndVariantArr = idAndVariant.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries); var id = Guid.Parse(idAndVariantArr[0]); var variant = idAndVariantArr[1]; var publishedOrCurrentRevision = repo.PublishedOrCurrentRevision(id, variant); if (publishedOrCurrentRevision != null) { var model = publishedOrCurrentRevision.ToBaseModel(); if (model != null) { toIndex.Add(model); } } } Indexer.Index(toIndex); } else { searcher.SetSearcher(); } } else if (instruction.InstructionKey == InstructionKeys.UpdateCrops) { StateHelper.UpdateCrops(); } else if (instruction.InstructionKey == InstructionKeys.UpdateCacheMappings) { StateHelper.UpdateCacheMappings(); } else if (instruction.InstructionKey == InstructionKeys.UpdateDomainMappings) { StateHelper.UpdateDomainMappings(); } else if (instruction.InstructionKey == InstructionKeys.UpdatePathLocales) { StateHelper.UpdatePathLocaleMappings(); } else if (instruction.InstructionKey == InstructionKeys.UpdateRedirects) { StateHelper.UpdateRedirectMappings(); } else if (instruction.InstructionKey == InstructionKeys.UpdateTaskMappings) { StateHelper.UpdateTaskMappings(); } } catch (Exception ex) { PuckCache.PuckLog.Log( $"error processing sync instruction (id:{instruction.Id}), skipping. error message:{ex.Message}" , ex.StackTrace , level: "error" , exceptionType: ex.GetType() ); } } if (hasPublishInstruction) { if (((config.GetValue <bool?>("UseAzureDirectory") ?? false) || (config.GetValue <bool?>("UseSyncDirectory") ?? false)) && config.GetValue <bool>("IsEditServer")) { var newInstruction = new PuckInstruction(); newInstruction.InstructionKey = InstructionKeys.SetSearcher; newInstruction.Count = 1; newInstruction.ServerName = ApiHelper.ServerName(); repo.AddPuckInstruction(newInstruction); repo.SaveChanges(); } } } updateMaxInstructionId(instructions); } } catch (Exception ex) { PuckCache.PuckLog.Log(ex); } finally { if (taken) { Monitor.Exit(lck); } PuckCache.IsSyncQueued = false; } } }