Skip to content

Commit

Permalink
Implemented Roster seeding. (#21)
Browse files Browse the repository at this point in the history
* Moved MemoryCache to infrastructure layer.

* Fixed persistence layer.

* Fixed modifiers.

* Created a seeding Worker.

* Implemented region & starters seeding.

* Implemented roster reset.
  • Loading branch information
Utar94 authored May 23, 2024
1 parent 3154222 commit b105f6f
Show file tree
Hide file tree
Showing 43 changed files with 527 additions and 55 deletions.
6 changes: 6 additions & 0 deletions backend/PokeData.sln
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PokeData", "src\PokeData\Po
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PokeData.Contracts", "src\PokeData.Contracts\PokeData.Contracts.csproj", "{6F2213F6-F202-4C6E-B5DA-5957213C917E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PokeData.Seeding", "src\PokeData.Seeding\PokeData.Seeding.csproj", "{EA695551-C8E1-44D8-B9A4-8B4E779AA7FE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -75,6 +77,10 @@ Global
{6F2213F6-F202-4C6E-B5DA-5957213C917E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6F2213F6-F202-4C6E-B5DA-5957213C917E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6F2213F6-F202-4C6E-B5DA-5957213C917E}.Release|Any CPU.Build.0 = Release|Any CPU
{EA695551-C8E1-44D8-B9A4-8B4E779AA7FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EA695551-C8E1-44D8-B9A4-8B4E779AA7FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EA695551-C8E1-44D8-B9A4-8B4E779AA7FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EA695551-C8E1-44D8-B9A4-8B4E779AA7FE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

public interface IPokemonRosterRepository
{
Task<int> DeleteAllAsync(CancellationToken cancellationToken = default);
Task DeleteAsync(ushort speciesId, CancellationToken cancellationToken = default);
Task SaveAsync(PokemonRoster roster, CancellationToken cancellationToken = default);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
public interface IPokemonSpeciesRepository
{
Task<PokemonSpecies?> LoadAsync(ushort id, CancellationToken cancellationToken = default);
Task<PokemonSpecies?> LoadAsync(string name, CancellationToken cancellationToken = default);
}
3 changes: 1 addition & 2 deletions backend/src/PokeData.ETL/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@

namespace PokeData.ETL;

public class Program
internal class Program
{
public static void Main(string[] args)
{
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<Worker>();
builder.Services.AddMemoryCache();
builder.Services.AddPokeDataWithEntityFrameworkCoreSqlServer(builder.Configuration);
builder.Services.AddPokeDataWithPokeApiClient();

Expand Down
2 changes: 1 addition & 1 deletion backend/src/PokeData.ETL/Worker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ protected override async Task ExecuteAsync(CancellationToken cancellationToken)
}

chrono.Stop();
_logger.LogInformation("Operation completed in {elapsed}ms.", chrono.ElapsedMilliseconds);
_logger.LogInformation("Operation completed in {Elapsed}ms.", chrono.ElapsedMilliseconds);
}
}
27 changes: 0 additions & 27 deletions backend/src/PokeData.EntityFrameworkCore.Relational/Db.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ protected AggregateEntity(DomainEvent @event)
Update(@event);
}

public IEnumerable<ActorId> GetActorIds() => new ActorId[] { new(CreatedBy), new(UpdatedBy) };
public IEnumerable<ActorId> GetActorIds() => [new(CreatedBy), new(UpdatedBy)];

protected void Update(DomainEvent @event)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ internal class GenerationEntity : AggregateEntity
public string UniqueName { get; private set; } = string.Empty;
public string UniqueNameNormalized
{
get => UniqueName.ToUpper();
get => PokemonDb.Normalize(UniqueName);
private set { }
}
public string? DisplayName { get; private set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ internal class PokemonSpeciesEntity : AggregateEntity
public string UniqueName { get; private set; } = string.Empty;
public string UniqueNameNormalized
{
get => UniqueName.ToUpper();
get => PokemonDb.Normalize(UniqueName);
private set { }
}
public string? DisplayName { get; private set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ internal class PokemonTypeEntity : AggregateEntity
public string UniqueName { get; private set; } = string.Empty;
public string UniqueNameNormalized
{
get => UniqueName.ToUpper();
get => PokemonDb.Normalize(UniqueName);
private set { }
}
public string? DisplayName { get; private set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ internal class PokemonVarietyEntity : AggregateEntity
public string UniqueName { get; private set; } = string.Empty;
public string UniqueNameNormalized
{
get => UniqueName.ToUpper();
get => PokemonDb.Normalize(UniqueName);
private set { }
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ internal class RegionEntity : AggregateEntity
public string UniqueName { get; private set; } = string.Empty;
public string UniqueNameNormalized
{
get => UniqueName.ToUpper();
get => PokemonDb.Normalize(UniqueName);
private set { }
}
public string? DisplayName { get; private set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ internal class ResourceEntity : AggregateEntity
public string Source { get; private set; } = string.Empty;
public string SourceNormalized
{
get => Source.ToUpper();
get => PokemonDb.Normalize(Source);
private set { }
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ namespace PokeData.EntityFrameworkCore.Relational;
public interface ISqlHelper
{
IQueryBuilder ApplyTextSearch(IQueryBuilder builder, TextSearch search, params ColumnId[] columns);
IDeleteBuilder DeleteFrom(TableId table);
IQueryBuilder QueryFrom(TableId table);
}
64 changes: 64 additions & 0 deletions backend/src/PokeData.EntityFrameworkCore.Relational/PokemonDb.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using Logitar.Data;
using PokeData.EntityFrameworkCore.Relational.Entities;

namespace PokeData.EntityFrameworkCore.Relational;

internal static class PokemonDb
{
public static class PokemonRoster
{
public static readonly TableId Table = new(nameof(PokemonContext.PokemonRoster));

public static readonly ColumnId AggregateId = new(nameof(PokemonRosterEntity.AggregateId), Table);
public static readonly ColumnId Category = new(nameof(PokemonRosterEntity.Category), Table);
public static readonly ColumnId CreatedBy = new(nameof(PokemonRosterEntity.CreatedBy), Table);
public static readonly ColumnId CreatedOn = new(nameof(PokemonRosterEntity.CreatedOn), Table);
public static readonly ColumnId IsBaby = new(nameof(PokemonRosterEntity.IsBaby), Table);
public static readonly ColumnId IsLegendary = new(nameof(PokemonRosterEntity.IsLegendary), Table);
public static readonly ColumnId IsMythical = new(nameof(PokemonRosterEntity.IsMythical), Table);
public static readonly ColumnId Name = new(nameof(PokemonRosterEntity.Name), Table);
public static readonly ColumnId Number = new(nameof(PokemonRosterEntity.Number), Table);
public static readonly ColumnId PokemonSpeciesId = new(nameof(PokemonRosterEntity.PokemonSpeciesId), Table);
public static readonly ColumnId PrimaryTypeId = new(nameof(PokemonRosterEntity.PrimaryTypeId), Table);
public static readonly ColumnId RegionId = new(nameof(PokemonRosterEntity.RegionId), Table);
public static readonly ColumnId SecondaryTypeId = new(nameof(PokemonRosterEntity.SecondaryTypeId), Table);
public static readonly ColumnId UpdatedBy = new(nameof(PokemonRosterEntity.UpdatedBy), Table);
public static readonly ColumnId UpdatedOn = new(nameof(PokemonRosterEntity.UpdatedOn), Table);
public static readonly ColumnId Version = new(nameof(PokemonRosterEntity.Version), Table);
}

public static class PokemonTypes
{
public static readonly TableId Table = new(nameof(PokemonContext.PokemonTypes));

public static readonly ColumnId AggregateId = new(nameof(PokemonTypeEntity.AggregateId), Table);
public static readonly ColumnId CreatedBy = new(nameof(PokemonTypeEntity.CreatedBy), Table);
public static readonly ColumnId CreatedOn = new(nameof(PokemonTypeEntity.CreatedOn), Table);
public static readonly ColumnId DisplayName = new(nameof(PokemonTypeEntity.DisplayName), Table);
public static readonly ColumnId PokemonTypeId = new(nameof(PokemonTypeEntity.PokemonTypeId), Table);
public static readonly ColumnId UniqueName = new(nameof(PokemonTypeEntity.UniqueName), Table);
public static readonly ColumnId UniqueNameNormalized = new(nameof(PokemonTypeEntity.UniqueNameNormalized), Table);
public static readonly ColumnId UpdatedBy = new(nameof(PokemonTypeEntity.UpdatedBy), Table);
public static readonly ColumnId UpdatedOn = new(nameof(PokemonTypeEntity.UpdatedOn), Table);
public static readonly ColumnId Version = new(nameof(PokemonTypeEntity.Version), Table);
}

public static class Regions
{
public static readonly TableId Table = new(nameof(PokemonContext.Regions));

public static readonly ColumnId AggregateId = new(nameof(RegionEntity.AggregateId), Table);
public static readonly ColumnId CreatedBy = new(nameof(RegionEntity.CreatedBy), Table);
public static readonly ColumnId CreatedOn = new(nameof(RegionEntity.CreatedOn), Table);
public static readonly ColumnId DisplayName = new(nameof(RegionEntity.DisplayName), Table);
public static readonly ColumnId MainGenerationId = new(nameof(RegionEntity.MainGenerationId), Table);
public static readonly ColumnId RegionId = new(nameof(RegionEntity.RegionId), Table);
public static readonly ColumnId UniqueName = new(nameof(RegionEntity.UniqueName), Table);
public static readonly ColumnId UniqueNameNormalized = new(nameof(RegionEntity.UniqueNameNormalized), Table);
public static readonly ColumnId UpdatedBy = new(nameof(RegionEntity.UpdatedBy), Table);
public static readonly ColumnId UpdatedOn = new(nameof(RegionEntity.UpdatedOn), Table);
public static readonly ColumnId Version = new(nameof(RegionEntity.Version), Table);
}

public static string Normalize(string value) => value.Trim().ToUpper();
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public PokemonTypeQuerier(IActorService actorService, PokemonContext context, IS

public async Task<PokemonType?> ReadAsync(string uniqueName, CancellationToken cancellationToken)
{
string uniqueNameNormalized = uniqueName.Trim().ToUpper();
string uniqueNameNormalized = PokemonDb.Normalize(uniqueName);

PokemonTypeEntity? region = await _regions.AsNoTracking()
.SingleOrDefaultAsync(x => x.UniqueNameNormalized == uniqueNameNormalized, cancellationToken);
Expand All @@ -43,13 +43,13 @@ public PokemonTypeQuerier(IActorService actorService, PokemonContext context, IS

public async Task<SearchResults<PokemonType>> SearchAsync(SearchPokemonTypesPayload payload, CancellationToken cancellationToken)
{
IQueryBuilder builder = _sqlHelper.QueryFrom(Db.PokemonTypes.Table)
.SelectAll(Db.PokemonTypes.Table);
_sqlHelper.ApplyTextSearch(builder, payload.Search, Db.PokemonTypes.UniqueName, Db.PokemonTypes.DisplayName);
IQueryBuilder builder = _sqlHelper.QueryFrom(PokemonDb.PokemonTypes.Table)
.SelectAll(PokemonDb.PokemonTypes.Table);
_sqlHelper.ApplyTextSearch(builder, payload.Search, PokemonDb.PokemonTypes.UniqueName, PokemonDb.PokemonTypes.DisplayName);

if (payload.NumberIn.Count > 1)
{
builder.Where(Db.PokemonTypes.PokemonTypeId, Operators.IsIn(payload.NumberIn));
builder.Where(PokemonDb.PokemonTypes.PokemonTypeId, Operators.IsIn(payload.NumberIn));
}

IQueryable<PokemonTypeEntity> query = _regions.FromQuery(builder).AsNoTracking();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public RegionQuerier(IActorService actorService, PokemonContext context, ISqlHel

public async Task<Region?> ReadAsync(string uniqueName, CancellationToken cancellationToken)
{
string uniqueNameNormalized = uniqueName.Trim().ToUpper();
string uniqueNameNormalized = PokemonDb.Normalize(uniqueName);

RegionEntity? region = await _regions.AsNoTracking()
.SingleOrDefaultAsync(x => x.UniqueNameNormalized == uniqueNameNormalized, cancellationToken);
Expand All @@ -43,13 +43,13 @@ public RegionQuerier(IActorService actorService, PokemonContext context, ISqlHel

public async Task<SearchResults<Region>> SearchAsync(SearchRegionsPayload payload, CancellationToken cancellationToken)
{
IQueryBuilder builder = _sqlHelper.QueryFrom(Db.Regions.Table)
.SelectAll(Db.Regions.Table);
_sqlHelper.ApplyTextSearch(builder, payload.Search, Db.Regions.UniqueName, Db.Regions.DisplayName);
IQueryBuilder builder = _sqlHelper.QueryFrom(PokemonDb.Regions.Table)
.SelectAll(PokemonDb.Regions.Table);
_sqlHelper.ApplyTextSearch(builder, payload.Search, PokemonDb.Regions.UniqueName, PokemonDb.Regions.DisplayName);

if (payload.NumberIn.Count > 1)
{
builder.Where(Db.Regions.RegionId, Operators.IsIn(payload.NumberIn));
builder.Where(PokemonDb.Regions.RegionId, Operators.IsIn(payload.NumberIn));
}

IQueryable<RegionEntity> query = _regions.FromQuery(builder)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore;
using Logitar.Data;
using Microsoft.EntityFrameworkCore;
using PokeData.Domain.Roster;
using PokeData.EntityFrameworkCore.Relational.Entities;

Expand All @@ -7,10 +8,18 @@ namespace PokeData.EntityFrameworkCore.Relational.Repositories;
internal class PokemonRosterRepository : IPokemonRosterRepository
{
private readonly PokemonContext _context;
private readonly ISqlHelper _sqlHelper;

public PokemonRosterRepository(PokemonContext context)
public PokemonRosterRepository(PokemonContext context, ISqlHelper sqlHelper)
{
_context = context;
_sqlHelper = sqlHelper;
}

public async Task<int> DeleteAllAsync(CancellationToken cancellationToken)
{
ICommand command = _sqlHelper.DeleteFrom(PokemonDb.PokemonRoster.Table).Build();
return await _context.Database.ExecuteSqlRawAsync(command.Text, command.Parameters.ToArray());
}

public async Task DeleteAsync(ushort speciesId, CancellationToken cancellationToken)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,17 @@ public PokemonSpeciesRepository(PokemonContext context)

return species == null ? null : DomainMapper.ToPokemonSpecies(species);
}

public async Task<PokemonSpecies?> LoadAsync(string name, CancellationToken cancellationToken)
{
string uniqueNameNormalized = PokemonDb.Normalize(name);

PokemonSpeciesEntity? species = await _context.PokemonSpecies.AsNoTracking()
.Include(x => x.Generation).ThenInclude(x => x!.MainRegion)
.Include(x => x.Varieties).ThenInclude(x => x.PrimaryType)
.Include(x => x.Varieties).ThenInclude(x => x.SecondaryType)
.SingleOrDefaultAsync(x => x.UniqueNameNormalized == uniqueNameNormalized, cancellationToken);

return species == null ? null : DomainMapper.ToPokemonSpecies(species);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public PokemonTypeRepository(PokemonContext context)

if (type == null)
{
string uniqueNameNormalized = idOrUniqueName.Trim().ToUpper();
string uniqueNameNormalized = PokemonDb.Normalize(idOrUniqueName);

type = await _context.PokemonTypes.AsNoTracking()
.SingleOrDefaultAsync(x => x.UniqueNameNormalized == uniqueNameNormalized, cancellationToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public RegionRepository(PokemonContext context)

if (region == null)
{
string uniqueNameNormalized = idOrUniqueName.Trim().ToUpper();
string uniqueNameNormalized = PokemonDb.Normalize(idOrUniqueName);

region = await _context.Regions.AsNoTracking()
.Include(x => x.MainGeneration)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,7 @@ public IQueryBuilder ApplyTextSearch(IQueryBuilder builder, TextSearch search, p
}
protected virtual ConditionalOperator CreateOperator(string pattern) => Operators.IsLike(pattern);

public abstract IDeleteBuilder DeleteFrom(TableId table);

public abstract IQueryBuilder QueryFrom(TableId table);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ namespace PokeData.EntityFrameworkCore.SqlServer;

internal class SqlServerHelper : SqlHelper
{
public override IDeleteBuilder DeleteFrom(TableId table) => SqlServerDeleteBuilder.From(table);

public override IQueryBuilder QueryFrom(TableId table) => SqlServerQueryBuilder.From(table);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public static IServiceCollection AddPokeDataInfrastructure(this IServiceCollecti
return services
.AddLogitarEventSourcingInfrastructure()
.AddMediatR(config => config.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()))
.AddMemoryCache()
.AddPokeDataApplication()
.AddSingleton(serviceProvider =>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

<ItemGroup>
<PackageReference Include="Logitar.EventSourcing.Infrastructure" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" />
</ItemGroup>

<ItemGroup>
Expand Down
5 changes: 5 additions & 0 deletions backend/src/PokeData.Seeding/Commands/SeedRegionsCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using MediatR;

namespace PokeData.Seeding.Commands;

internal record SeedRegionsCommand(string Path, Encoding Encoding) : INotification;
Loading

0 comments on commit b105f6f

Please sign in to comment.