Browse Source

Merge pull request #42 from volosoft/berkan/revision-for-workers

Revision for EventTimingChangeWorker/EventTimingChangeNotifier
pull/46/head
Halil İbrahim Kalkan 5 years ago
committed by GitHub
parent
commit
6941600f68
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 19
      src/EventHub.BackgroundServices/Events/EventReminderNotifier.cs
  2. 2
      src/EventHub.BackgroundServices/Events/EventReminderWorker.cs
  3. 37
      src/EventHub.BackgroundServices/Events/EventTimingChangeNotifier.cs
  4. 26
      src/EventHub.BackgroundServices/Events/EventTimingChangeWorker.cs
  5. 26
      src/EventHub.BackgroundServices/Events/NewEventNotifier.cs
  6. 4
      src/EventHub.BackgroundServices/Events/NewEventWorker.cs
  7. 2
      src/EventHub.Domain/Events/Event.cs
  8. 32
      src/EventHub.Domain/Events/EventTimeChangeLocalEventHandler.cs
  9. 4
      src/EventHub.Domain/Events/Registrations/EventRegistration.cs
  10. 2638
      src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/20210614064205_Moved_IsTimingChangeEmailSent_To_Event.Designer.cs
  11. 35
      src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/20210614064205_Moved_IsTimingChangeEmailSent_To_Event.cs
  12. 13
      src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/EventHubMigrationsDbContextModelSnapshot.cs
  13. 5
      src/EventHub.EntityFrameworkCore/EntityFrameworkCore/EventHubDbContextModelCreatingExtensions.cs

19
src/EventHub.BackgroundServices/Events/EventReminderNotifier.cs

@ -21,10 +21,10 @@ namespace EventHub.Events
private readonly IAsyncQueryableExecuter _asyncExecuter; private readonly IAsyncQueryableExecuter _asyncExecuter;
public EventReminderNotifier( public EventReminderNotifier(
IEmailSender emailSender, IEmailSender emailSender,
ITemplateRenderer templateRenderer, ITemplateRenderer templateRenderer,
IRepository<AppUser, Guid> userRepository, IRepository<AppUser, Guid> userRepository,
IRepository<EventRegistration, Guid> eventRegistrationRepository, IRepository<EventRegistration, Guid> eventRegistrationRepository,
IAsyncQueryableExecuter asyncExecuter) IAsyncQueryableExecuter asyncExecuter)
{ {
_emailSender = emailSender; _emailSender = emailSender;
@ -33,12 +33,17 @@ namespace EventHub.Events
_eventRegistrationRepository = eventRegistrationRepository; _eventRegistrationRepository = eventRegistrationRepository;
_asyncExecuter = asyncExecuter; _asyncExecuter = asyncExecuter;
} }
public async Task NotifyAsync(Event @event) public async Task NotifyAsync(Event @event)
{ {
if (@event is null || @event.IsRemindingEmailSent)
{
return;
}
var userQueryable = await _userRepository.GetQueryableAsync(); var userQueryable = await _userRepository.GetQueryableAsync();
var registrationQueryable = await _eventRegistrationRepository.GetQueryableAsync(); var registrationQueryable = await _eventRegistrationRepository.GetQueryableAsync();
var userQuery = from eventRegistration in registrationQueryable var userQuery = from eventRegistration in registrationQueryable
join user in userQueryable on eventRegistration.UserId equals user.Id join user in userQueryable on eventRegistration.UserId equals user.Id
where eventRegistration.EventId == @event.Id where eventRegistration.EventId == @event.Id
@ -61,7 +66,7 @@ namespace EventHub.Events
user.Email, user.Email,
"The event has last thirty minutes to start!", "The event has last thirty minutes to start!",
await _templateRenderer.RenderAsync(EmailTemplates.EventReminder, templateModel) await _templateRenderer.RenderAsync(EmailTemplates.EventReminder, templateModel)
); );
} }
} }
} }

2
src/EventHub.BackgroundServices/Events/EventReminderWorker.cs

@ -45,7 +45,7 @@ namespace EventHub.Events
{ {
await eventReminderNotifier.NotifyAsync(@event); await eventReminderNotifier.NotifyAsync(@event);
} }
@event.IsRemindingEmailSent = true; @event.IsRemindingEmailSent = true;
await eventRepository.UpdateAsync(@event); await eventRepository.UpdateAsync(@event);
} }

37
src/EventHub.BackgroundServices/Events/EventTimingChangeNotifier.cs

@ -16,46 +16,43 @@ namespace EventHub.Events
{ {
private readonly IEmailSender _emailSender; private readonly IEmailSender _emailSender;
private readonly ITemplateRenderer _templateRenderer; private readonly ITemplateRenderer _templateRenderer;
private readonly IRepository<EventRegistration, Guid> _eventRegistrationRepository;
private readonly IAsyncQueryableExecuter _asyncExecuter; private readonly IAsyncQueryableExecuter _asyncExecuter;
private readonly IRepository<AppUser, Guid> _userRepository; private readonly IRepository<AppUser, Guid> _userRepository;
private readonly IRepository<EventRegistration, Guid> _eventRegistrationRepository;
public EventTimingChangeNotifier( public EventTimingChangeNotifier(
IEmailSender emailSender, IEmailSender emailSender,
ITemplateRenderer templateRenderer, ITemplateRenderer templateRenderer,
IRepository<EventRegistration, Guid> eventRegistrationRepository,
IAsyncQueryableExecuter asyncExecuter, IAsyncQueryableExecuter asyncExecuter,
IRepository<AppUser, Guid> userRepository) IRepository<AppUser, Guid> userRepository,
IRepository<EventRegistration, Guid> eventRegistrationRepository)
{ {
_emailSender = emailSender; _emailSender = emailSender;
_templateRenderer = templateRenderer; _templateRenderer = templateRenderer;
_eventRegistrationRepository = eventRegistrationRepository;
_asyncExecuter = asyncExecuter; _asyncExecuter = asyncExecuter;
_userRepository = userRepository; _userRepository = userRepository;
_eventRegistrationRepository = eventRegistrationRepository;
} }
public async Task NotifyAsync(Event @event) public async Task NotifyAsync(Event @event)
{ {
if (@event is null) if (@event is null || @event.IsTimingChangeEmailSent)
{ {
return; return;
} }
//TODO: It will be more performant if we join to users instead of individually query (already done for EventReminderNotifier)
var queryable = await _eventRegistrationRepository.GetQueryableAsync(); var userQueryable = await _userRepository.GetQueryableAsync();
var registrations = await _asyncExecuter.ToListAsync( var registrationQueryable = await _eventRegistrationRepository.GetQueryableAsync();
queryable.Where(x => x.EventId == @event.Id && !x.IsTimingChangeEmailSent)
);
foreach (var registration in registrations) var userQuery = from eventRegistration in registrationQueryable
{ join user in userQueryable on eventRegistration.UserId equals user.Id
var user = await _userRepository.FindAsync(registration.UserId); where eventRegistration.EventId == @event.Id
if (user is null) select user;
{
continue; var users = await _asyncExecuter.ToListAsync(userQuery);
}
foreach (var user in users)
{
var templateModel = new var templateModel = new
{ {
UserName = user.GetFullNameOrUsername(), UserName = user.GetFullNameOrUsername(),
@ -70,11 +67,7 @@ namespace EventHub.Events
"Event time has been changed!", "Event time has been changed!",
await _templateRenderer.RenderAsync(EmailTemplates.EventTimingChanged, templateModel) await _templateRenderer.RenderAsync(EmailTemplates.EventTimingChanged, templateModel)
); );
registration.IsTimingChangeEmailSent = true;
} }
await _eventRegistrationRepository.UpdateManyAsync(registrations, autoSave: true);
} }
} }
} }

26
src/EventHub.BackgroundServices/Events/EventTimingChangeWorker.cs

@ -1,7 +1,6 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using EventHub.Events.Registrations;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Volo.Abp.BackgroundWorkers; using Volo.Abp.BackgroundWorkers;
@ -17,7 +16,7 @@ namespace EventHub.Events
public EventTimingChangeWorker( public EventTimingChangeWorker(
AbpAsyncTimer timer, AbpAsyncTimer timer,
IServiceScopeFactory serviceScopeFactory IServiceScopeFactory serviceScopeFactory
) : base( ) : base(
timer, timer,
serviceScopeFactory) serviceScopeFactory)
{ {
@ -29,27 +28,26 @@ namespace EventHub.Events
{ {
var eventTimingChangeNotifier = workerContext.ServiceProvider.GetRequiredService<EventTimingChangeNotifier>(); var eventTimingChangeNotifier = workerContext.ServiceProvider.GetRequiredService<EventTimingChangeNotifier>();
var eventRepository = workerContext.ServiceProvider.GetRequiredService<IRepository<Event, Guid>>(); var eventRepository = workerContext.ServiceProvider.GetRequiredService<IRepository<Event, Guid>>();
var eventRegistrationRepository = workerContext.ServiceProvider.GetRequiredService<IRepository<EventRegistration, Guid>>();
var asyncExecuter = workerContext.ServiceProvider.GetRequiredService<IAsyncQueryableExecuter>(); var asyncExecuter = workerContext.ServiceProvider.GetRequiredService<IAsyncQueryableExecuter>();
var queryable = await eventRegistrationRepository.GetQueryableAsync(); var queryable = await eventRepository.GetQueryableAsync();
var query = queryable var query = queryable.Where(x => !x.IsTimingChangeEmailSent);
.Where(x => !x.IsTimingChangeEmailSent)
.Select(x => x.EventId) var events = await asyncExecuter.ToListAsync(query);
.Distinct();
foreach (var @event in events)
var eventRegistrations = await asyncExecuter.ToListAsync(query);
foreach (var eventRegistration in eventRegistrations)
{ {
try try
{ {
await eventTimingChangeNotifier.NotifyAsync(await eventRepository.FindAsync(eventRegistration)); await eventTimingChangeNotifier.NotifyAsync(@event);
@event.IsTimingChangeEmailSent = true;
await eventRepository.UpdateAsync(@event);
} }
catch (Exception e) catch (Exception e)
{ {
Logger.LogError($"An error occurred while sending an email to the attendees of the event after the event time has changed. Error message: {e.Message}"); Logger.LogError($"An error occurred while sending an email to the attendees of the event after the event time has changed. Error message: {e.Message}");
} }
} }
} }
} }

26
src/EventHub.BackgroundServices/Events/NewEventNotifier.cs

@ -36,21 +36,23 @@ namespace EventHub.Events
public async Task NotifyAsync(Event @event) public async Task NotifyAsync(Event @event)
{ {
//TODO: It will be more performant if we join to users instead of individually query (already done for EventReminderNotifier) if (@event is null || @event.IsEmailSentToMembers)
{
return;
}
var userQueryable = await _userRepository.GetQueryableAsync();
var organizationMembershipQueryable = await _organizationMembershipsRepository.GetQueryableAsync();
var queryable = await _organizationMembershipsRepository.GetQueryableAsync(); var userQuery = from organizationMembership in organizationMembershipQueryable
var organizationMembers = await _asyncExecuter.ToListAsync( join user in userQueryable on organizationMembership.UserId equals user.Id
queryable.Where(x => x.OrganizationId == @event.OrganizationId) where organizationMembership.OrganizationId == @event.OrganizationId
); select user;
foreach (var member in organizationMembers) var users = await _asyncExecuter.ToListAsync(userQuery);
{
var user = await _userRepository.FindAsync(member.UserId);
if (user is null)
{
continue;
}
foreach (var user in users)
{
var templateModel = new var templateModel = new
{ {
UserName = user.GetFullNameOrUsername(), UserName = user.GetFullNameOrUsername(),

4
src/EventHub.BackgroundServices/Events/NewEventWorker.cs

@ -16,7 +16,7 @@ namespace EventHub.Events
{ {
public NewEventWorker( public NewEventWorker(
AbpAsyncTimer timer, AbpAsyncTimer timer,
IServiceScopeFactory serviceScopeFactory) IServiceScopeFactory serviceScopeFactory)
: base( : base(
timer, timer,
serviceScopeFactory) serviceScopeFactory)
@ -46,7 +46,7 @@ namespace EventHub.Events
{ {
await newEventNotifier.NotifyAsync(@event); await newEventNotifier.NotifyAsync(@event);
} }
@event.IsEmailSentToMembers = true; @event.IsEmailSentToMembers = true;
await eventRepository.UpdateAsync(@event); await eventRepository.UpdateAsync(@event);
} }

2
src/EventHub.Domain/Events/Event.cs

@ -40,6 +40,8 @@ namespace EventHub.Events
public int TimingChangeCount { get; set; } public int TimingChangeCount { get; set; }
public bool IsTimingChangeEmailSent { get; set; }
private Event() private Event()
{ {

32
src/EventHub.Domain/Events/EventTimeChangeLocalEventHandler.cs

@ -1,48 +1,30 @@
using System; using System;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using EventHub.Events.Registrations;
using IdentityServer4.Validation;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Repositories;
using Volo.Abp.EventBus; using Volo.Abp.EventBus;
using Volo.Abp.Linq;
namespace EventHub.Events namespace EventHub.Events
{ {
public class EventTimeChangeLocalEventHandler : ILocalEventHandler<EventTimeChangingEventData>, ITransientDependency public class EventTimeChangeLocalEventHandler : ILocalEventHandler<EventTimeChangingEventData>, ITransientDependency
{ {
private readonly IRepository<EventRegistration, Guid> _eventRegistrationRepository; private readonly IRepository<Event, Guid> _eventRepository;
private readonly IAsyncQueryableExecuter _asyncExecuter;
public EventTimeChangeLocalEventHandler( public EventTimeChangeLocalEventHandler(IRepository<Event, Guid> eventRepository)
IRepository<EventRegistration, Guid> eventRegistrationRepository,
IAsyncQueryableExecuter asyncExecuter)
{ {
_eventRegistrationRepository = eventRegistrationRepository; _eventRepository = eventRepository;
_asyncExecuter = asyncExecuter;
} }
public async Task HandleEventAsync(EventTimeChangingEventData eventData) public async Task HandleEventAsync(EventTimeChangingEventData eventData)
{ {
await UpdateEventRegistrationForTimingChangeAsync(@eventData.Event); await UpdateEventForTimingChangeAsync(eventData.Event);
} }
private async Task UpdateEventRegistrationForTimingChangeAsync(Event @event) private async Task UpdateEventForTimingChangeAsync(Event @event)
{ {
var eventRegistrationQueryable = await _eventRegistrationRepository.GetQueryableAsync(); @event.IsTimingChangeEmailSent = false;
var query = eventRegistrationQueryable.Where(x => x.EventId == @event.Id);
var eventRegistrations = await _asyncExecuter.ToListAsync(query);
foreach (var eventRegistration in eventRegistrations) await _eventRepository.UpdateAsync(@event, true);
{
if (eventRegistration.IsTimingChangeEmailSent)
{
eventRegistration.IsTimingChangeEmailSent = false;
}
}
await _eventRegistrationRepository.UpdateManyAsync(eventRegistrations, true);
} }
} }
} }

4
src/EventHub.Domain/Events/Registrations/EventRegistration.cs

@ -8,9 +8,7 @@ namespace EventHub.Events.Registrations
public Guid EventId { get; private set; } public Guid EventId { get; private set; }
public Guid UserId { get; private set; } public Guid UserId { get; private set; }
public bool IsTimingChangeEmailSent { get; set; }
private EventRegistration() private EventRegistration()
{ {

2638
src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/20210614064205_Moved_IsTimingChangeEmailSent_To_Event.Designer.cs

File diff suppressed because it is too large

35
src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/20210614064205_Moved_IsTimingChangeEmailSent_To_Event.cs

@ -0,0 +1,35 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace EventHub.Migrations
{
public partial class Moved_IsTimingChangeEmailSent_To_Event : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "IsTimingChangeEmailSent",
table: "EhEventRegistrations");
migrationBuilder.AddColumn<bool>(
name: "IsTimingChangeEmailSent",
table: "EhEvents",
type: "boolean",
nullable: false,
defaultValue: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "IsTimingChangeEmailSent",
table: "EhEvents");
migrationBuilder.AddColumn<bool>(
name: "IsTimingChangeEmailSent",
table: "EhEventRegistrations",
type: "boolean",
nullable: false,
defaultValue: true);
}
}
}

13
src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/EventHubMigrationsDbContextModelSnapshot.cs

@ -18,7 +18,7 @@ namespace EventHub.Migrations
modelBuilder modelBuilder
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql)
.HasAnnotation("Relational:MaxIdentifierLength", 63) .HasAnnotation("Relational:MaxIdentifierLength", 63)
.HasAnnotation("ProductVersion", "5.0.5") .HasAnnotation("ProductVersion", "5.0.7")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
modelBuilder.Entity("EventHub.Countries.Country", b => modelBuilder.Entity("EventHub.Countries.Country", b =>
@ -107,6 +107,11 @@ namespace EventHub.Migrations
b.Property<bool>("IsRemindingEmailSent") b.Property<bool>("IsRemindingEmailSent")
.HasColumnType("boolean"); .HasColumnType("boolean");
b.Property<bool>("IsTimingChangeEmailSent")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(true);
b.Property<string>("Language") b.Property<string>("Language")
.HasMaxLength(16) .HasMaxLength(16)
.HasColumnType("character varying(16)"); .HasColumnType("character varying(16)");
@ -191,12 +196,6 @@ namespace EventHub.Migrations
.HasColumnType("text") .HasColumnType("text")
.HasColumnName("ExtraProperties"); .HasColumnName("ExtraProperties");
b.Property<bool>("IsTimingChangeEmailSent")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(true)
.HasColumnName("IsTimingChangeEmailSent");
b.Property<Guid>("UserId") b.Property<Guid>("UserId")
.HasColumnType("uuid"); .HasColumnType("uuid");

5
src/EventHub.EntityFrameworkCore/EntityFrameworkCore/EventHubDbContextModelCreatingExtensions.cs

@ -73,6 +73,8 @@ namespace EventHub.EntityFrameworkCore
b.HasOne<Country>().WithMany().HasForeignKey(x => x.CountryId).OnDelete(DeleteBehavior.NoAction); b.HasOne<Country>().WithMany().HasForeignKey(x => x.CountryId).OnDelete(DeleteBehavior.NoAction);
b.Property(x => x.IsTimingChangeEmailSent).HasDefaultValue(true);
b.HasIndex(x => new {x.OrganizationId, x.StartTime}); b.HasIndex(x => new {x.OrganizationId, x.StartTime});
b.HasIndex(x => x.StartTime); b.HasIndex(x => x.StartTime);
b.HasIndex(x => x.UrlCode); b.HasIndex(x => x.UrlCode);
@ -86,9 +88,6 @@ namespace EventHub.EntityFrameworkCore
b.ConfigureByConvention(); b.ConfigureByConvention();
b.Property(x => x.IsTimingChangeEmailSent).HasDefaultValue(true)
.HasColumnName(nameof(EventRegistration.IsTimingChangeEmailSent));
b.HasOne<Event>().WithMany().HasForeignKey(x => x.EventId).IsRequired().OnDelete(DeleteBehavior.NoAction); b.HasOne<Event>().WithMany().HasForeignKey(x => x.EventId).IsRequired().OnDelete(DeleteBehavior.NoAction);
if (isMigrationDbContext) if (isMigrationDbContext)

Loading…
Cancel
Save