Browse Source

refactor: emailing for event reminder and new event

pull/18/head
Berkan 6 years ago
parent
commit
36088724d5
  1. 2
      src/EventHub.Application/Emailing/Templates/EventReminder.tpl
  2. 2
      src/EventHub.Application/Emailing/Templates/NewEventCreated.tpl
  3. 1
      src/EventHub.Application/EventHub.Application.csproj
  4. 1
      src/EventHub.Application/EventHubApplicationModule.cs
  5. 17
      src/EventHub.Application/Events/EventAppService.cs
  6. 35
      src/EventHub.Application/Events/EventReminderNotifier.cs
  7. 39
      src/EventHub.Application/Events/EventReminderWorker.cs
  8. 50
      src/EventHub.Application/Events/NewEventDetectorWorker.cs
  9. 31
      src/EventHub.Application/Events/NewEventNotifier.cs

2
src/EventHub.Application/Emailing/Templates/EventReminder.tpl

@ -79,7 +79,7 @@
Hi {{model.user_name}}, Hi {{model.user_name}},
</p> </p>
<p> <p>
See you in 30 minutes at the "{{model.title}}" event The "{{model.title}}" event will start very soon.
</p> </p>
<div> <div>
<table border="0" cellpadding="0" cellspacing="0" style=" border-collapse: separate; vertical-align: top; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;"> <table border="0" cellpadding="0" cellspacing="0" style=" border-collapse: separate; vertical-align: top; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">

2
src/EventHub.Application/Emailing/Templates/NewEventCreated.tpl

@ -79,7 +79,7 @@
Hi {{model.user_name}}, Hi {{model.user_name}},
</p> </p>
<p> <p>
A new event was created by "{{model.organization_name}}" under the title of "{{model.title}}". A new event called "{{model.title}}" has been created.
</p> </p>
<div> <div>
<table border="0" cellpadding="0" cellspacing="0" style=" border-collapse: separate; vertical-align: top; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;"> <table border="0" cellpadding="0" cellspacing="0" style=" border-collapse: separate; vertical-align: top; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">

1
src/EventHub.Application/EventHub.Application.csproj

@ -13,7 +13,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.2" />
<PackageReference Include="Volo.Abp.Account.Application" Version="4.2.0-rc.1" /> <PackageReference Include="Volo.Abp.Account.Application" Version="4.2.0-rc.1" />
<PackageReference Include="Volo.Abp.Identity.Application" Version="4.2.0-rc.1" /> <PackageReference Include="Volo.Abp.Identity.Application" Version="4.2.0-rc.1" />
<PackageReference Include="Volo.Abp.PermissionManagement.Application" Version="4.2.0-rc.1" /> <PackageReference Include="Volo.Abp.PermissionManagement.Application" Version="4.2.0-rc.1" />

1
src/EventHub.Application/EventHubApplicationModule.cs

@ -23,6 +23,7 @@ namespace EventHub
public override void OnApplicationInitialization(ApplicationInitializationContext context) public override void OnApplicationInitialization(ApplicationInitializationContext context)
{ {
context.AddBackgroundWorker<EventReminderWorker>(); context.AddBackgroundWorker<EventReminderWorker>();
context.AddBackgroundWorker<NewEventDetectorWorker>();
} }
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)

17
src/EventHub.Application/Events/EventAppService.cs

@ -3,7 +3,6 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using EventHub.Organizations; using EventHub.Organizations;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Repositories;
@ -16,18 +15,15 @@ namespace EventHub.Events
private readonly EventManager _eventManager; private readonly EventManager _eventManager;
private readonly IRepository<Organization, Guid> _organizationRepository; private readonly IRepository<Organization, Guid> _organizationRepository;
private readonly IRepository<Event, Guid> _eventRepository; private readonly IRepository<Event, Guid> _eventRepository;
private readonly NewEventNotifier _newEventNotifier;
public EventAppService( public EventAppService(
EventManager eventManager, EventManager eventManager,
IRepository<Organization, Guid> organizationRepository, IRepository<Organization, Guid> organizationRepository,
IRepository<Event, Guid> eventRepository, IRepository<Event, Guid> eventRepository)
NewEventNotifier newEventNotifier)
{ {
_eventManager = eventManager; _eventManager = eventManager;
_organizationRepository = organizationRepository; _organizationRepository = organizationRepository;
_eventRepository = eventRepository; _eventRepository = eventRepository;
_newEventNotifier = newEventNotifier;
} }
[Authorize] [Authorize]
@ -51,20 +47,9 @@ namespace EventHub.Events
@event.IsOnline = input.IsOnline; @event.IsOnline = input.IsOnline;
@event.Capacity = input.Capacity; @event.Capacity = input.Capacity;
@event.IsEmailSentToMembers = true;
await _eventRepository.InsertAsync(@event); await _eventRepository.InsertAsync(@event);
try
{
await _newEventNotifier.NotifyAsync(organization, @event);
}
catch (Exception e)
{
@event.IsEmailSentToMembers = false;
Logger.LogError($"An error occurred while sending an email to the members of the {organization.Name} organization after the new event was created. Error message: {e.Message}");
}
return ObjectMapper.Map<Event, EventDto>(@event); return ObjectMapper.Map<Event, EventDto>(@event);
} }

35
src/EventHub.Application/Events/EventReminderNotifier.cs

@ -1,9 +1,13 @@
using System.Collections.Generic; using System;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using EventHub.Emailing; using EventHub.Emailing;
using EventHub.Events.Registrations;
using EventHub.Users; using EventHub.Users;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Emailing; using Volo.Abp.Emailing;
using Volo.Abp.Linq;
using Volo.Abp.TextTemplating; using Volo.Abp.TextTemplating;
namespace EventHub.Events namespace EventHub.Events
@ -12,25 +16,42 @@ namespace EventHub.Events
{ {
private readonly IEmailSender _emailSender; private readonly IEmailSender _emailSender;
private readonly ITemplateRenderer _templateRenderer; private readonly ITemplateRenderer _templateRenderer;
private readonly IRepository<AppUser, Guid> _userRepository;
private readonly IRepository<EventRegistration, Guid> _eventRegistrationRepository;
private readonly IAsyncQueryableExecuter _asyncExecuter;
public EventReminderNotifier( public EventReminderNotifier(
IEmailSender emailSender, IEmailSender emailSender,
ITemplateRenderer templateRenderer) ITemplateRenderer templateRenderer,
IRepository<AppUser, Guid> userRepository,
IRepository<EventRegistration, Guid> eventRegistrationRepository,
IAsyncQueryableExecuter asyncExecuter)
{ {
_emailSender = emailSender; _emailSender = emailSender;
_templateRenderer = templateRenderer; _templateRenderer = templateRenderer;
_userRepository = userRepository;
_eventRegistrationRepository = eventRegistrationRepository;
_asyncExecuter = asyncExecuter;
} }
public async Task NotifyAsync( public async Task NotifyAsync(Event @event)
Event @event,
IEnumerable<AppUser> users)
{ {
if (users is null || @event is null) if (@event is null)
{ {
return; return;
} }
var userQueryable = await _userRepository.GetQueryableAsync();
var eventRegistrationQueryable = await _eventRegistrationRepository.GetQueryableAsync();
var userQuery = from eventRegistration in eventRegistrationQueryable
join user in userQueryable on eventRegistration.UserId equals user.Id
where eventRegistration.EventId == @event.Id
select user;
foreach (var user in users) var usersToBeNotified = await _asyncExecuter.ToListAsync(userQuery);
foreach (var user in usersToBeNotified)
{ {
var model = new var model = new
{ {

39
src/EventHub.Application/Events/EventReminderWorker.cs

@ -1,13 +1,11 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using EventHub.Events.Registrations;
using EventHub.Users;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Volo.Abp.BackgroundWorkers; using Volo.Abp.BackgroundWorkers;
using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Repositories;
using Volo.Abp.Linq;
using Volo.Abp.Threading; using Volo.Abp.Threading;
using Volo.Abp.Uow; using Volo.Abp.Uow;
@ -25,36 +23,27 @@ namespace EventHub.Events
protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext) protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)
{ {
var eventReminderNotifier = workerContext.ServiceProvider.GetRequiredService<EventReminderNotifier>(); var eventReminderNotifier = workerContext.ServiceProvider.GetRequiredService<EventReminderNotifier>();
var eventRepository = workerContext.ServiceProvider.GetRequiredService<IRepository<Event, Guid>>(); var eventRepository = workerContext.ServiceProvider.GetRequiredService<IRepository<Event, Guid>>();
var userRepository = workerContext.ServiceProvider.GetRequiredService<IRepository<AppUser, Guid>>(); var asyncExecuter = workerContext.ServiceProvider.GetRequiredService<IAsyncQueryableExecuter>();
var eventRegistrationRepository = workerContext.ServiceProvider.GetRequiredService<IRepository<EventRegistration, Guid>>();
var eventQueryable = await eventRepository.GetQueryableAsync(); var eventQueryable = await eventRepository.GetQueryableAsync();
var userQueryable = await userRepository.GetQueryableAsync();
var eventRegistrationQueryable = await eventRegistrationRepository.GetQueryableAsync();
var thirtyOneMinutesAfter = DateTime.Now.AddMinutes(31); var thirtyOneMinutesAfter = DateTime.Now.AddMinutes(30);
var twentyNineMinutesAfter = DateTime.Now.AddMinutes(29); var oneMinutesAfter = DateTime.Now.AddMinutes(1);
var eventsStartingAfterThirtyMinutes = await eventQueryable.Where(x => var eventQuery = eventQueryable.Where(x =>
x.IsRemindingEmailSent == false && x.IsRemindingEmailSent == false &&
x.StartTime < thirtyOneMinutesAfter && x.StartTime <= thirtyOneMinutesAfter &&
x.StartTime > twentyNineMinutesAfter) x.StartTime >= oneMinutesAfter);
.ToListAsync();
var events = await asyncExecuter.ToListAsync(eventQuery);
foreach (var @event in eventsStartingAfterThirtyMinutes) foreach (var @event in events)
{ {
var usersToBeNotified = await (from eventRegistration in eventRegistrationQueryable
join user in userQueryable on eventRegistration.UserId equals user.Id
where eventRegistration.EventId == @event.Id
select user).ToListAsync();
@event.IsRemindingEmailSent = true;
try try
{ {
await eventReminderNotifier.NotifyAsync(@event, usersToBeNotified); await eventReminderNotifier.NotifyAsync(@event);
@event.IsRemindingEmailSent = true;
} }
catch (Exception e) catch (Exception e)
{ {

50
src/EventHub.Application/Events/NewEventDetectorWorker.cs

@ -0,0 +1,50 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Linq;
using Volo.Abp.Threading;
using Volo.Abp.Uow;
namespace EventHub.Events
{
public class NewEventDetectorWorker : AsyncPeriodicBackgroundWorkerBase
{
public NewEventDetectorWorker(AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory)
: base(timer, serviceScopeFactory)
{
Timer.Period = 60_000;
}
[UnitOfWork]
protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)
{
var newEventNotifier = workerContext.ServiceProvider.GetRequiredService<NewEventNotifier>();
var eventRepository = workerContext.ServiceProvider.GetRequiredService<IRepository<Event, Guid>>();
var asyncExecuter = workerContext.ServiceProvider.GetRequiredService<IAsyncQueryableExecuter>();
var eventQueryable = await eventRepository.GetQueryableAsync();
var eventQuery = eventQueryable.Where(x => x.IsEmailSentToMembers == false);
var newEvents = await asyncExecuter.ToListAsync(eventQuery);
foreach (var @event in newEvents)
{
try
{
await newEventNotifier.NotifyAsync(@event);
@event.IsEmailSentToMembers = true;
}
catch (Exception e)
{
@event.IsEmailSentToMembers = false;
Logger.LogError($"An error occurred while sending an email to the members of the organization after the new event was created. Error message: {e.Message}");
}
}
}
}
}

31
src/EventHub.Application/Events/NewEventNotifier.cs

@ -1,15 +1,13 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks; using System.Threading.Tasks;
using EventHub.Emailing; using EventHub.Emailing;
using EventHub.Organizations;
using EventHub.Organizations.Memberships; using EventHub.Organizations.Memberships;
using EventHub.Users; using EventHub.Users;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Repositories;
using Volo.Abp.Emailing; using Volo.Abp.Emailing;
using Volo.Abp.Linq;
using Volo.Abp.TextTemplating; using Volo.Abp.TextTemplating;
namespace EventHub.Events namespace EventHub.Events
@ -20,33 +18,35 @@ namespace EventHub.Events
private readonly ITemplateRenderer _templateRenderer; private readonly ITemplateRenderer _templateRenderer;
private readonly IRepository<OrganizationMembership, Guid> _organizationMembershipsRepository; private readonly IRepository<OrganizationMembership, Guid> _organizationMembershipsRepository;
private readonly IRepository<AppUser, Guid> _userRepository; private readonly IRepository<AppUser, Guid> _userRepository;
private readonly IAsyncQueryableExecuter _asyncExecuter;
public NewEventNotifier( public NewEventNotifier(
IEmailSender emailSender, IEmailSender emailSender,
ITemplateRenderer templateRenderer, ITemplateRenderer templateRenderer,
IRepository<OrganizationMembership, Guid> organizationMembershipsRepository, IRepository<OrganizationMembership, Guid> organizationMembershipsRepository,
IRepository<AppUser, Guid> userRepository) IRepository<AppUser, Guid> userRepository,
IAsyncQueryableExecuter asyncExecuter)
{ {
_emailSender = emailSender; _emailSender = emailSender;
_templateRenderer = templateRenderer; _templateRenderer = templateRenderer;
_organizationMembershipsRepository = organizationMembershipsRepository; _organizationMembershipsRepository = organizationMembershipsRepository;
_userRepository = userRepository; _userRepository = userRepository;
_asyncExecuter = asyncExecuter;
} }
public async Task NotifyAsync( public async Task NotifyAsync(Event @event)
Organization organization,
Event @event)
{ {
if (organization is null || @event is null) if (@event is null)
{ {
return; return;
} }
var organizationMemberQueryable = await _organizationMembershipsRepository.GetQueryableAsync(); var organizationMembershipsQueryable = await _organizationMembershipsRepository.GetQueryableAsync();
var organizationMembers = await organizationMemberQueryable var membershipQuery = organizationMembershipsQueryable
.Where(x => x.OrganizationId == organization.Id) .Where(x => x.OrganizationId == @event.OrganizationId);
.ToListAsync();
var organizationMembers = await _asyncExecuter.ToListAsync(membershipQuery);
foreach (var member in organizationMembers) foreach (var member in organizationMembers)
{ {
@ -60,7 +60,6 @@ namespace EventHub.Events
var model = new var model = new
{ {
UserName = user.GetFullNameOrUsername(), UserName = user.GetFullNameOrUsername(),
OrganizationName = organization.Name,
Title = @event.Title, Title = @event.Title,
StartTime = @event.StartTime, StartTime = @event.StartTime,
EndTime = @event.EndTime, EndTime = @event.EndTime,

Loading…
Cancel
Save