Skip to content

Commit 80370a5

Browse files
authored
Merge pull request #95 from umbraco/feature/algolia-notifications
Extended indexing and CacheRefresher notifications integration
2 parents a3c0a3e + 882f76c commit 80370a5

12 files changed

+181
-175
lines changed

src/Umbraco.Cms.Integrations.Search.Algolia/AlgoliaComposer.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,7 @@ public void Compose(IUmbracoBuilder builder)
2020
{
2121
builder.AddNotificationHandler<UmbracoApplicationStartingNotification, RunAlgoliaIndicesMigration>();
2222

23-
builder.AddNotificationAsyncHandler<ContentPublishedNotification, ContentPublishedHandler>();
24-
25-
builder.AddNotificationAsyncHandler<ContentDeletedNotification, ContentDeletedHandler>();
26-
27-
builder.AddNotificationAsyncHandler<ContentUnpublishedNotification, ContentUnpublishedHandler>();
23+
builder.AddNotificationAsyncHandler<ContentCacheRefresherNotification, AlgoliaContentCacheRefresherHandler>();
2824

2925
var options = builder.Services.AddOptions<AlgoliaSettings>()
3026
.Bind(builder.Config.GetSection(Constants.SettingsPath));

src/Umbraco.Cms.Integrations.Search.Algolia/Builders/ContentRecordBuilder.cs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,16 @@ public class ContentRecordBuilder
1111
{
1212
private readonly Record _record = new();
1313

14+
private readonly IUserService _userService;
15+
1416
private readonly IPublishedUrlProvider _urlProvider;
1517

1618
private readonly IAlgoliaSearchPropertyIndexValueFactory _algoliaSearchPropertyIndexValueFactory;
1719

18-
public ContentRecordBuilder(IPublishedUrlProvider urlProvider, IAlgoliaSearchPropertyIndexValueFactory algoliaSearchPropertyIndexValueFactory)
20+
public ContentRecordBuilder(IUserService userService, IPublishedUrlProvider urlProvider, IAlgoliaSearchPropertyIndexValueFactory algoliaSearchPropertyIndexValueFactory)
1921
{
22+
_userService = userService;
23+
2024
_urlProvider = urlProvider;
2125

2226
_algoliaSearchPropertyIndexValueFactory = algoliaSearchPropertyIndexValueFactory;
@@ -26,15 +30,26 @@ public ContentRecordBuilder BuildFromContent(IContent content, Func<IProperty, b
2630
{
2731
_record.ObjectID = content.Key.ToString();
2832

33+
var creator = _userService.GetProfileById(content.CreatorId);
34+
var writer = _userService.GetProfileById(content.WriterId);
35+
2936
_record.Id = content.Id;
3037
_record.Name = content.Name;
38+
3139
_record.CreateDate = content.CreateDate.ToString();
40+
_record.CreatorName = creator.Name;
3241
_record.UpdateDate = content.UpdateDate.ToString();
42+
_record.WriterName = writer.Name;
43+
44+
_record.TemplateId = content.TemplateId.HasValue ? content.TemplateId.Value : -1;
45+
_record.Level = content.Level;
46+
_record.Path = content.Path;
47+
_record.ContentTypeAlias = content.ContentType.Alias;
3348
_record.Url = _urlProvider.GetUrl(content.Id);
3449

35-
if (content.AvailableCultures.Count() > 0)
50+
if (content.PublishedCultures.Count() > 0)
3651
{
37-
foreach (var culture in content.AvailableCultures)
52+
foreach (var culture in content.PublishedCultures)
3853
{
3954
_record.Data.Add($"name-{culture}", content.CultureInfos[culture].Name);
4055
_record.Data.Add($"url-{culture}", _urlProvider.GetUrl(content.Id, culture: culture));
@@ -45,9 +60,9 @@ public ContentRecordBuilder BuildFromContent(IContent content, Func<IProperty, b
4560
{
4661
if (!_record.Data.ContainsKey(property.Alias))
4762
{
48-
if (content.AvailableCultures.Count() > 0)
63+
if (content.PublishedCultures.Count() > 0)
4964
{
50-
foreach (var culture in content.AvailableCultures)
65+
foreach (var culture in content.PublishedCultures)
5166
{
5267
var indexValue = _algoliaSearchPropertyIndexValueFactory.GetValue(property, culture);
5368
_record.Data.Add($"{indexValue.Key}-{culture}", indexValue.Value);

src/Umbraco.Cms.Integrations.Search.Algolia/Controllers/SearchController.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ public class SearchController : UmbracoAuthorizedApiController
2929

3030
private readonly UmbracoHelper _umbracoHelper;
3131

32+
private readonly IUserService _userService;
33+
3234
private readonly IPublishedUrlProvider _urlProvider;
3335

3436
private readonly IContentService _contentService;
@@ -40,6 +42,7 @@ public SearchController(
4042
IAlgoliaSearchService<SearchResponse<Record>> searchService,
4143
IAlgoliaIndexDefinitionStorage<AlgoliaIndex> indexStorage,
4244
UmbracoHelper umbracoHelper,
45+
IUserService userService,
4346
IPublishedUrlProvider urlProvider,
4447
IContentService contentService,
4548
IAlgoliaSearchPropertyIndexValueFactory algoliaSearchPropertyIndexValueFactory)
@@ -52,6 +55,8 @@ public SearchController(
5255

5356
_umbracoHelper = umbracoHelper;
5457

58+
_userService = userService;
59+
5560
_urlProvider = urlProvider;
5661

5762
_contentService = contentService;
@@ -86,7 +91,9 @@ public async Task<IActionResult> SaveIndex([FromBody] IndexConfiguration index)
8691
Date = DateTime.Now
8792
});
8893

89-
var result = await _indexService.PushData(index.Name);
94+
var result = await _indexService.IndexExists(index.Name)
95+
? Result.Ok()
96+
: await _indexService.PushData(index.Name);
9097

9198
return new JsonResult(result);
9299
}
@@ -113,7 +120,7 @@ public async Task<IActionResult> BuildIndex([FromBody] IndexConfiguration indexC
113120

114121
foreach (var contentItem in contentItems)
115122
{
116-
var record = new ContentRecordBuilder(_urlProvider, _algoliaSearchPropertyIndexValueFactory)
123+
var record = new ContentRecordBuilder(_userService, _urlProvider, _algoliaSearchPropertyIndexValueFactory)
117124
.BuildFromContent(_contentService.GetById(contentItem.Id), (p) => contentDataItem.Properties.Any(q => q.Alias == p.Alias))
118125
.Build();
119126

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
using Microsoft.Extensions.Logging;
2+
3+
using Umbraco.Cms.Core.Cache;
4+
using Umbraco.Cms.Core.Events;
5+
using Umbraco.Cms.Core.Notifications;
6+
using Umbraco.Cms.Core.Services.Changes;
7+
using Umbraco.Cms.Core.Services;
8+
using Umbraco.Cms.Core.Routing;
9+
using Umbraco.Cms.Integrations.Search.Algolia.Migrations;
10+
using Umbraco.Cms.Integrations.Search.Algolia.Services;
11+
using Umbraco.Cms.Core.Models;
12+
using Umbraco.Cms.Integrations.Search.Algolia.Builders;
13+
using System.Text.Json;
14+
using Umbraco.Cms.Integrations.Search.Algolia.Models;
15+
using Umbraco.Cms.Core.Sync;
16+
17+
namespace Umbraco.Cms.Integrations.Search.Algolia.Handlers
18+
{
19+
public class AlgoliaContentCacheRefresherHandler : INotificationAsyncHandler<ContentCacheRefresherNotification>
20+
{
21+
private readonly IServerRoleAccessor _serverRoleAccessor;
22+
23+
private readonly IContentService _contentService;
24+
25+
private readonly ILogger _logger;
26+
27+
private readonly IAlgoliaIndexDefinitionStorage<AlgoliaIndex> _indexStorage;
28+
29+
private readonly IAlgoliaIndexService _indexService;
30+
31+
private readonly IUserService _userService;
32+
33+
private readonly IPublishedUrlProvider _urlProvider;
34+
35+
private readonly IAlgoliaSearchPropertyIndexValueFactory _algoliaSearchPropertyIndexValueFactory;
36+
37+
public AlgoliaContentCacheRefresherHandler(
38+
IServerRoleAccessor serverRoleAccessor,
39+
ILogger<AlgoliaContentCacheRefresherHandler> logger,
40+
IContentService contentService,
41+
IAlgoliaIndexDefinitionStorage<AlgoliaIndex> indexStorage,
42+
IAlgoliaIndexService indexService,
43+
IUserService userService,
44+
IPublishedUrlProvider urlProvider,
45+
IAlgoliaSearchPropertyIndexValueFactory algoliaSearchPropertyIndexValueFactory)
46+
{
47+
_serverRoleAccessor = serverRoleAccessor;
48+
_contentService = contentService;
49+
_logger = logger;
50+
_indexStorage = indexStorage;
51+
_indexService = indexService;
52+
_userService = userService;
53+
_urlProvider = urlProvider;
54+
_algoliaSearchPropertyIndexValueFactory = algoliaSearchPropertyIndexValueFactory;
55+
}
56+
57+
public async Task HandleAsync(ContentCacheRefresherNotification notification, CancellationToken cancellationToken)
58+
{
59+
if (notification.MessageObject is not ContentCacheRefresher.JsonPayload[] payloads)
60+
{
61+
return;
62+
}
63+
64+
switch (_serverRoleAccessor.CurrentServerRole)
65+
{
66+
case ServerRole.Subscriber:
67+
_logger.LogDebug("Algolia indexing task will not run on subscriber servers.");
68+
return;
69+
case ServerRole.Unknown:
70+
_logger.LogDebug("Algolia indexing task will not run on servers with unknown role.");
71+
return;
72+
case ServerRole.Single:
73+
case ServerRole.SchedulingPublisher:
74+
default:
75+
break;
76+
}
77+
78+
var refreshedContent = _contentService
79+
.GetByIds(
80+
payloads
81+
.Where(p => p.ChangeTypes == TreeChangeTypes.RefreshNode || p.ChangeTypes == TreeChangeTypes.RefreshBranch)
82+
.Select(p => p.Id));
83+
84+
await RebuildIndex(refreshedContent);
85+
}
86+
87+
protected async Task RebuildIndex(IEnumerable<IContent> entities)
88+
{
89+
try
90+
{
91+
var indices = _indexStorage.Get();
92+
93+
foreach (var entity in entities)
94+
{
95+
foreach (var index in indices)
96+
{
97+
var indexConfiguration = JsonSerializer.Deserialize<List<ContentData>>(index.SerializedData)
98+
.FirstOrDefault(p => p.ContentType.Alias == entity.ContentType.Alias);
99+
if (indexConfiguration == null || indexConfiguration.ContentType.Alias != entity.ContentType.Alias) continue;
100+
101+
var record = new ContentRecordBuilder(_userService, _urlProvider, _algoliaSearchPropertyIndexValueFactory)
102+
.BuildFromContent(entity, (p) => indexConfiguration.Properties.Any(q => q.Alias == p.Alias))
103+
.Build();
104+
105+
var result = entity.Trashed || !entity.Published
106+
? await _indexService.DeleteData(index.Name, entity.Key.ToString())
107+
: await _indexService.UpdateData(index.Name, record);
108+
109+
if (result.Failure)
110+
_logger.LogError($"Failed to update data for Algolia index: {result}");
111+
}
112+
}
113+
}
114+
catch (Exception ex)
115+
{
116+
_logger.LogError($"Failed to update data for Algolia index: {ex.Message}");
117+
}
118+
}
119+
}
120+
}

src/Umbraco.Cms.Integrations.Search.Algolia/Handlers/BaseContentHandler.cs

Lines changed: 0 additions & 77 deletions
This file was deleted.

src/Umbraco.Cms.Integrations.Search.Algolia/Handlers/ContentDeletedHandler.cs

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/Umbraco.Cms.Integrations.Search.Algolia/Handlers/ContentPublishedHandler.cs

Lines changed: 0 additions & 25 deletions
This file was deleted.

src/Umbraco.Cms.Integrations.Search.Algolia/Handlers/ContentUnpublishedHandler.cs

Lines changed: 0 additions & 26 deletions
This file was deleted.

0 commit comments

Comments
 (0)