Skip to content

Commit

Permalink
#417 - Local cache of extemplate templates.
Browse files Browse the repository at this point in the history
  • Loading branch information
maraf committed Jun 22, 2022
1 parent 570bb8a commit ddad9a6
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/Money.Blazor.Host/Bootstrap/BootstrapTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ void AddMiddleware<T>(IServiceCollection services, bool register = true)
AddMiddleware<CurrencyMiddleware>(services);
AddMiddleware<UserMiddleware>(services);
AddMiddleware<UserPropertyMiddleware>(services);
AddMiddleware<ExpenseTemplateMiddleware>(services);
AddMiddleware<ApiVersionChecker>(services);
AddMiddleware<UserPropertyQueryHandler>(services);
AddMiddleware<PwaInstallInterop>(services, register: false);
Expand Down
1 change: 1 addition & 0 deletions src/Money.Blazor.Host/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ private static void ConfigureServices(IServiceCollection services)
.AddTransient<CategoryStorage>()
.AddTransient<ProfileStorage>()
.AddTransient<UserPropertyStorage>()
.AddTransient<ExpenseTemplateStorage>()
.AddTransient<NavigatorUrl>()
.AddSingleton<Navigator>()
.AddSingleton<Navigator.ModalContainer>()
Expand Down
109 changes: 109 additions & 0 deletions src/Money.Blazor.Host/Services/ExpenseTemplateMiddleware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
using Money.Events;
using Money.Models;
using Money.Models.Queries;
using Neptuo;
using Neptuo.Events.Handlers;
using Neptuo.Queries;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Money.Services
{
internal class ExpenseTemplateMiddleware : HttpQueryDispatcher.IMiddleware,
IEventHandler<ExpenseTemplateCreated>,
IEventHandler<ExpenseTemplateDeleted>,
IEventHandler<UserSignedOut>
{
private readonly ServerConnectionState serverConnection;
private readonly ExpenseTemplateStorage localStorage;

private readonly List<ExpenseTemplateModel> models = new List<ExpenseTemplateModel>();
private Task listAllTask;

public ExpenseTemplateMiddleware(ServerConnectionState serverConnection, ExpenseTemplateStorage localStorage)
{
Ensure.NotNull(serverConnection, "serverConnection");
Ensure.NotNull(localStorage, "localStorage");
this.serverConnection = serverConnection;
this.localStorage = localStorage;
}

public async Task<object> ExecuteAsync(object query, HttpQueryDispatcher dispatcher, HttpQueryDispatcher.Next next)
{
if (query is ListAllExpenseTemplate listAll)
{
await EnsureListAsync(null, next, listAll);
return models.Select(c => c.Clone()).ToList();
}

return await next(query);
}

private async Task EnsureListAsync(HttpQueryDispatcher dispatcher, HttpQueryDispatcher.Next next, ListAllExpenseTemplate listAll)
{
if (models.Count == 0)
{
if (listAllTask == null)
listAllTask = LoadAllAsync(dispatcher, next, listAll);

try
{
await listAllTask;
}
finally
{
listAllTask = null;
}
}
}

private async Task LoadAllAsync(HttpQueryDispatcher dispatcher, HttpQueryDispatcher.Next next, ListAllExpenseTemplate listAll)
{
models.Clear();
if (!serverConnection.IsAvailable)
{
var items = await localStorage.LoadAsync();
if (items != null)
{
models.AddRange(items);
return;
}
}

if (dispatcher != null)
{
await dispatcher.QueryAsync(listAll);
}
else
{
models.AddRange((List<ExpenseTemplateModel>)await next(listAll));
await localStorage.SaveAsync(models);
}
}

async Task IEventHandler<UserSignedOut>.HandleAsync(UserSignedOut payload)
{
models.Clear();
await localStorage.DeleteAsync();
}

Task IEventHandler<ExpenseTemplateCreated>.HandleAsync(ExpenseTemplateCreated payload)
{
models.Add(new ExpenseTemplateModel(payload.AggregateKey, payload.Amount, payload.Description, payload.CategoryKey));
return Task.CompletedTask;
}

Task IEventHandler<ExpenseTemplateDeleted>.HandleAsync(ExpenseTemplateDeleted payload)
{
var model = models.Find(m => m.Key.Equals(payload.AggregateKey));
if (model != null)
models.Remove(model);

return Task.CompletedTask;
}
}
}
19 changes: 19 additions & 0 deletions src/Money.Blazor.Host/Services/ExpenseTemplateStorage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Blazored.LocalStorage;
using Money.Models;
using Neptuo.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Money.Services
{
public class ExpenseTemplateStorage : JsonLocalStorage<List<ExpenseTemplateModel>>
{
public ExpenseTemplateStorage(FormatterContainer formatters, ILocalStorageService localStorage, ILogFactory logFactory)
: base(formatters.Query, localStorage, logFactory, "expenseTemplates")
{ }
}
}
5 changes: 4 additions & 1 deletion src/Money.Models/ExpenseTemplateModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Money.Models
/// <summary>
/// A model of single expense template.
/// </summary>
public class ExpenseTemplateModel
public class ExpenseTemplateModel : ICloneable<ExpenseTemplateModel>
{
/// <summary>
/// Gets a key of the expense template.
Expand Down Expand Up @@ -50,5 +50,8 @@ public ExpenseTemplateModel(IKey key, Price amount, string description, IKey cat
CategoryKey = categoryKey;
Description = description;
}

public ExpenseTemplateModel Clone()
=> new ExpenseTemplateModel(Key, Amount, Description, CategoryKey);
}
}

0 comments on commit ddad9a6

Please sign in to comment.