⏪ Putting back the view mark flush handler
This commit is contained in:
		
							
								
								
									
										52
									
								
								DysonNetwork.Sphere/Post/PostViewFlushHandler.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								DysonNetwork.Sphere/Post/PostViewFlushHandler.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
			
		||||
using DysonNetwork.Shared.Cache;
 | 
			
		||||
using Microsoft.EntityFrameworkCore;
 | 
			
		||||
using Quartz;
 | 
			
		||||
 | 
			
		||||
namespace DysonNetwork.Sphere.Post;
 | 
			
		||||
 | 
			
		||||
public class PostViewFlushHandler(IServiceProvider serviceProvider) : IFlushHandler<PostViewInfo>
 | 
			
		||||
{
 | 
			
		||||
    public async Task FlushAsync(IReadOnlyList<Sphere.Post.PostViewInfo> items)
 | 
			
		||||
    {
 | 
			
		||||
        using var scope = serviceProvider.CreateScope();
 | 
			
		||||
        var db = scope.ServiceProvider.GetRequiredService<AppDatabase>();
 | 
			
		||||
        var cache = scope.ServiceProvider.GetRequiredService<ICacheService>();
 | 
			
		||||
 | 
			
		||||
        // Group views by post
 | 
			
		||||
        var postViews = items
 | 
			
		||||
            .GroupBy(x => x.PostId)
 | 
			
		||||
            .ToDictionary(g => g.Key, g => g.ToList());
 | 
			
		||||
 | 
			
		||||
        // Calculate total views and unique views per post
 | 
			
		||||
        foreach (var postId in postViews.Keys)
 | 
			
		||||
        {
 | 
			
		||||
            // Calculate unique views by distinct viewer IDs (not null)
 | 
			
		||||
            var uniqueViews = postViews[postId]
 | 
			
		||||
                .Where(v => !string.IsNullOrEmpty(v.ViewerId))
 | 
			
		||||
                .Select(v => v.ViewerId)
 | 
			
		||||
                .Distinct()
 | 
			
		||||
                .Count();
 | 
			
		||||
 | 
			
		||||
            // Total views is just the count of all items for this post
 | 
			
		||||
            var totalViews = postViews[postId].Count;
 | 
			
		||||
 | 
			
		||||
            // Update the post in the database
 | 
			
		||||
            await db.Posts
 | 
			
		||||
                .Where(p => p.Id == postId)
 | 
			
		||||
                .ExecuteUpdateAsync(p => p
 | 
			
		||||
                    .SetProperty(x => x.ViewsTotal, x => x.ViewsTotal + totalViews)
 | 
			
		||||
                    .SetProperty(x => x.ViewsUnique, x => x.ViewsUnique + uniqueViews));
 | 
			
		||||
 | 
			
		||||
            // Invalidate any cache entries for this post
 | 
			
		||||
            await cache.RemoveAsync($"post:{postId}");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public class PostViewFlushJob(FlushBufferService fbs, PostViewFlushHandler hdl) : IJob
 | 
			
		||||
{
 | 
			
		||||
    public async Task Execute(IJobExecutionContext context)
 | 
			
		||||
    {
 | 
			
		||||
        await fbs.FlushAsync(hdl);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
using DysonNetwork.Sphere.Post;
 | 
			
		||||
using DysonNetwork.Sphere.WebReader;
 | 
			
		||||
using Quartz;
 | 
			
		||||
 | 
			
		||||
@@ -16,15 +17,15 @@ public static class ScheduledJobsConfiguration
 | 
			
		||||
                .WithIdentity("AppDatabaseRecyclingTrigger")
 | 
			
		||||
                .WithCronSchedule("0 0 0 * * ?"));
 | 
			
		||||
 | 
			
		||||
            // var postViewFlushJob = new JobKey("PostViewFlush");
 | 
			
		||||
            // q.AddJob<PostViewFlushJob>(opts => opts.WithIdentity(postViewFlushJob));
 | 
			
		||||
            // q.AddTrigger(opts => opts
 | 
			
		||||
            //     .ForJob(postViewFlushJob)
 | 
			
		||||
            //     .WithIdentity("PostViewFlushTrigger")
 | 
			
		||||
            //     .WithSimpleSchedule(o => o
 | 
			
		||||
            //         .WithIntervalInMinutes(1)
 | 
			
		||||
            //         .RepeatForever())
 | 
			
		||||
            // );
 | 
			
		||||
            var postViewFlushJob = new JobKey("PostViewFlush");
 | 
			
		||||
            q.AddJob<PostViewFlushJob>(opts => opts.WithIdentity(postViewFlushJob));
 | 
			
		||||
            q.AddTrigger(opts => opts
 | 
			
		||||
                .ForJob(postViewFlushJob)
 | 
			
		||||
                .WithIdentity("PostViewFlushTrigger")
 | 
			
		||||
                .WithSimpleSchedule(o => o
 | 
			
		||||
                    .WithIntervalInMinutes(1)
 | 
			
		||||
                    .RepeatForever())
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            var webFeedScraperJob = new JobKey("WebFeedScraper");
 | 
			
		||||
            q.AddJob<WebFeedScraperJob>(opts => opts.WithIdentity(webFeedScraperJob));
 | 
			
		||||
 
 | 
			
		||||
@@ -143,6 +143,7 @@ public static class ServiceCollectionExtensions
 | 
			
		||||
    public static IServiceCollection AddAppFlushHandlers(this IServiceCollection services)
 | 
			
		||||
    {
 | 
			
		||||
        services.AddSingleton<FlushBufferService>();
 | 
			
		||||
        services.AddScoped<PostViewFlushHandler>();
 | 
			
		||||
 | 
			
		||||
        return services;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user