Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 33d2a64

Browse filesBrowse files
authored
Add first subscriber use case (#23)
* Add CoursesCounter, suscriber and repository * Add mother class and TestCase - Mapping database * Test publish domain and change FakeItEasy by Moc + refactor infrastructure case + apply InMemoryContext * Added DomainEventInformation and Deserializer logic * Add ability to test domain events from Specflow
1 parent fc1e096 commit 33d2a64
Copy full SHA for 33d2a64

File tree

Expand file treeCollapse file tree

49 files changed

+794
-76
lines changed
Filter options

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Dismiss banner
Expand file treeCollapse file tree

49 files changed

+794
-76
lines changed

‎apps/Mooc/Backend/Backend.csproj

Copy file name to clipboardExpand all lines: apps/Mooc/Backend/Backend.csproj
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<PrivateAssets>all</PrivateAssets>
1515
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1616
</PackageReference>
17+
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="2.2.6"/>
1718
</ItemGroup>
1819

1920
<ItemGroup>
+27Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
namespace CodelyTv.Apps.Mooc.Backend.Extension
2+
{
3+
using System.Linq;
4+
using System.Reflection;
5+
using Microsoft.Extensions.DependencyInjection;
6+
using Shared.Domain.Bus.Event;
7+
8+
public static class InMemoryEventBusExtension
9+
{
10+
public static IServiceCollection AddDomainEventSuscribersServices(this IServiceCollection services, Assembly assembly)
11+
{
12+
var classTypes = assembly.ExportedTypes.Select(t => t.GetTypeInfo()).Where(t => t.IsClass && !t.IsAbstract);
13+
14+
foreach (var type in classTypes)
15+
{
16+
var interfaces = type.ImplementedInterfaces.Select(i => i.GetTypeInfo());
17+
18+
foreach (var handlerType in interfaces.Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IDomainEventSuscriber<>)))
19+
{
20+
services.AddScoped(handlerType.AsType(), type.AsType());
21+
}
22+
}
23+
24+
return services;
25+
}
26+
}
27+
}

‎apps/Mooc/Backend/Startup.cs

Copy file name to clipboardExpand all lines: apps/Mooc/Backend/Startup.cs
+11-2Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
namespace CodelyTv.Apps.Mooc.Backend
22
{
3+
using System;
4+
using System.Linq;
35
using CodelyTv.Mooc.Courses.Application.Create;
46
using CodelyTv.Mooc.Courses.Domain;
57
using CodelyTv.Mooc.Courses.Infrastructure.Persistence;
8+
using CodelyTv.Mooc.CoursesCounter.Application.Incrementer;
9+
using CodelyTv.Mooc.CoursesCounter.Domain;
10+
using CodelyTv.Mooc.CoursesCounter.Infrastructure.Persistence;
611
using CodelyTv.Mooc.Shared.Infrastructure.Persistence.EntityFramework;
12+
using Extension;
713
using Microsoft.AspNetCore.Builder;
814
using Microsoft.AspNetCore.Hosting;
915
using Microsoft.AspNetCore.Mvc;
@@ -33,18 +39,21 @@ public void ConfigureServices(IServiceCollection services)
3339
services.AddScoped<CourseCreator, CourseCreator>();
3440
services.AddScoped<ICourseRepository, MySqlCourseRepository>();
3541

42+
services.AddScoped<CoursesCounterIncrementer, CoursesCounterIncrementer>();
43+
services.AddScoped<IUuidGenerator, CSharpUuidGenerator>();
44+
services.AddScoped<ICoursesCounterRepository, MySqlCoursesCounterRepository>();
45+
3646
services.AddScoped<IEventBus, InMemoryEventBus>();
47+
services.AddDomainEventSuscribersServices(AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(x => x.FullName.Contains("CodelyTv.Mooc")));
3748

3849
services.AddDbContext<MoocContext>(options => options.UseMySQL(_configuration.GetConnectionString("MoocDatabase")));
3950
}
4051

41-
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
4252
public static void Configure(IApplicationBuilder app, IHostingEnvironment env)
4353
{
4454
if (env.IsDevelopment())
4555
app.UseDeveloperExceptionPage();
4656
else
47-
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
4857
app.UseHsts();
4958

5059
app.UseHttpsRedirection();

‎database/mooc.sql

Copy file name to clipboardExpand all lines: database/mooc.sql
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,11 @@ CREATE TABLE `courses` (
33
`name` VARCHAR(255) NOT NULL,
44
`duration` VARCHAR(255) NOT NULL,
55
PRIMARY KEY (`id`)
6+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
7+
8+
CREATE TABLE `courses_counter` (
9+
`id` CHAR(36) NOT NULL,
10+
`total` INT NOT NULL,
11+
`existing_courses` JSON NOT NULL,
12+
PRIMARY KEY (`id`)
613
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

‎src/Mooc/Courses/Domain/Course.cs

Copy file name to clipboardExpand all lines: src/Mooc/Courses/Domain/Course.cs
+16Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
namespace CodelyTv.Mooc.Courses.Domain
22
{
3+
using System;
34
using CodelyTv.Shared.Domain.Aggregate;
45

56
public class Course : AggregateRoot
@@ -27,5 +28,20 @@ public static Course Create(CourseId id, CourseName name, CourseDuration duratio
2728

2829
return course;
2930
}
31+
32+
public override bool Equals(object obj)
33+
{
34+
if (this == obj) return true;
35+
36+
var item = obj as Course;
37+
if (item == null) return false;
38+
39+
return this.Id.Equals(item.Id) && this.Name.Equals(item.Name) && this.Duration.Equals(item.Duration);
40+
}
41+
42+
public override int GetHashCode()
43+
{
44+
return HashCode.Combine(this.Id, this.Name, this.Duration);
45+
}
3046
}
3147
}

‎src/Mooc/Courses/Domain/CourseCreatedDomainEvent.cs

Copy file name to clipboardExpand all lines: src/Mooc/Courses/Domain/CourseCreatedDomainEvent.cs
+20Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
namespace CodelyTv.Mooc.Courses.Domain
22
{
3+
using System;
34
using System.Collections.Generic;
45
using CodelyTv.Shared.Domain.Bus.Event;
56

@@ -15,6 +16,10 @@ public CourseCreatedDomainEvent(string id, string name, string duration, string
1516
Duration = duration;
1617
}
1718

19+
public CourseCreatedDomainEvent()
20+
{
21+
}
22+
1823
public override string EventName()
1924
{
2025
return "course.created";
@@ -33,5 +38,20 @@ public override DomainEvent FromPrimitives(string aggregateId, Dictionary<string
3338
{
3439
return new CourseCreatedDomainEvent(aggregateId, body["name"], body["duration"], eventId, occurredOn);
3540
}
41+
42+
public override bool Equals(object obj)
43+
{
44+
if (this == obj) return true;
45+
46+
var item = obj as CourseCreatedDomainEvent;
47+
if (item == null) return false;
48+
49+
return this.AggregateId.Equals(item.AggregateId) && this.Name.Equals(item.Name) && this.Duration.Equals(item.Duration);
50+
}
51+
52+
public override int GetHashCode()
53+
{
54+
return HashCode.Combine(this.AggregateId, this.Name, this.Duration);
55+
}
3656
}
3757
}
+35Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
namespace CodelyTv.Mooc.CoursesCounter.Application.Incrementer
2+
{
3+
using CodelyTv.Shared.Domain;
4+
using Courses.Domain;
5+
using Domain;
6+
7+
public class CoursesCounterIncrementer
8+
{
9+
private ICoursesCounterRepository repository;
10+
private IUuidGenerator uuidGenerator;
11+
12+
public CoursesCounterIncrementer(ICoursesCounterRepository repository, IUuidGenerator uuidGenerator)
13+
{
14+
this.repository = repository;
15+
this.uuidGenerator = uuidGenerator;
16+
}
17+
18+
public void Increment(CourseId id)
19+
{
20+
CoursesCounter counter = repository.Search() ?? InitializeCounter();
21+
22+
if (!counter.HasIncremented(id))
23+
{
24+
counter.Increment(id);
25+
26+
repository.Save(counter);
27+
}
28+
}
29+
30+
private CoursesCounter InitializeCounter()
31+
{
32+
return CoursesCounter.Initialize(uuidGenerator.Generate());
33+
}
34+
}
35+
}
+23Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
namespace CodelyTv.Mooc.CoursesCounter.Application.Incrementer
2+
{
3+
using System.Threading.Tasks;
4+
using CodelyTv.Shared.Domain.Bus.Event;
5+
using Courses.Domain;
6+
7+
public class IncrementCoursesCounterOnCourseCreated : IDomainEventSuscriber<CourseCreatedDomainEvent>
8+
{
9+
private readonly CoursesCounterIncrementer _incrementer;
10+
11+
public IncrementCoursesCounterOnCourseCreated(CoursesCounterIncrementer incrementer)
12+
{
13+
_incrementer = incrementer;
14+
}
15+
16+
public async Task On(CourseCreatedDomainEvent @event)
17+
{
18+
CourseId courseId = new CourseId(@event.AggregateId);
19+
20+
_incrementer.Increment(courseId);
21+
}
22+
}
23+
}
+57Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
namespace CodelyTv.Mooc.CoursesCounter.Domain
2+
{
3+
using System;
4+
using System.Collections.Generic;
5+
using Courses.Domain;
6+
7+
public class CoursesCounter
8+
{
9+
public CoursesCounterId Id { get; private set; }
10+
public CoursesCounterTotal Total { get; private set; }
11+
public List<CourseId> ExistingCourses { get; private set; }
12+
13+
public CoursesCounter(CoursesCounterId id, CoursesCounterTotal total, List<CourseId> existingCourses)
14+
{
15+
Id = id;
16+
Total = total;
17+
ExistingCourses = existingCourses;
18+
}
19+
20+
private CoursesCounter()
21+
{
22+
}
23+
24+
public static CoursesCounter Initialize(string id)
25+
{
26+
return new CoursesCounter(new CoursesCounterId(id), CoursesCounterTotal.Initialize(), new List<CourseId>());
27+
}
28+
29+
public bool HasIncremented(CourseId id)
30+
{
31+
return this.ExistingCourses.Contains(id);
32+
}
33+
34+
public void Increment(CourseId id)
35+
{
36+
this.Total = this.Total.Increment();
37+
this.ExistingCourses.Add(id);
38+
}
39+
40+
public override bool Equals(object obj)
41+
{
42+
if (this == obj) return true;
43+
44+
var item = obj as CoursesCounter;
45+
if (item == null) return false;
46+
47+
return this.Id.Equals(item.Id) &&
48+
this.Total.Equals(item.Total) &&
49+
this.ExistingCourses.Equals(item.ExistingCourses);
50+
}
51+
52+
public override int GetHashCode()
53+
{
54+
return HashCode.Combine(this.Id, this.Total, this.ExistingCourses);
55+
}
56+
}
57+
}
+11Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace CodelyTv.Mooc.CoursesCounter.Domain
2+
{
3+
using CodelyTv.Shared.Domain.ValueObject;
4+
5+
public class CoursesCounterId : Uuid
6+
{
7+
public CoursesCounterId(string value) : base(value)
8+
{
9+
}
10+
}
11+
}
+21Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
namespace CodelyTv.Mooc.CoursesCounter.Domain
2+
{
3+
using CodelyTv.Shared.Domain.ValueObject;
4+
5+
public class CoursesCounterTotal : IntValueObject
6+
{
7+
public CoursesCounterTotal(int value) : base(value)
8+
{
9+
}
10+
11+
public static CoursesCounterTotal Initialize()
12+
{
13+
return new CoursesCounterTotal(0);
14+
}
15+
16+
public CoursesCounterTotal Increment()
17+
{
18+
return new CoursesCounterTotal(this.Value + 1);
19+
}
20+
}
21+
}
+10Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace CodelyTv.Mooc.CoursesCounter.Domain
2+
{
3+
using System.Threading.Tasks;
4+
5+
public interface ICoursesCounterRepository
6+
{
7+
Task Save(CoursesCounter counter);
8+
CoursesCounter Search();
9+
}
10+
}
+37Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
namespace CodelyTv.Mooc.CoursesCounter.Infrastructure.Persistence
2+
{
3+
using System.Linq;
4+
using System.Threading.Tasks;
5+
using Domain;
6+
using Microsoft.EntityFrameworkCore;
7+
using Shared.Infrastructure.Persistence.EntityFramework;
8+
9+
public class MySqlCoursesCounterRepository : ICoursesCounterRepository
10+
{
11+
private MoocContext _context;
12+
13+
public MySqlCoursesCounterRepository(MoocContext context)
14+
{
15+
this._context = context;
16+
}
17+
18+
public async Task Save(CoursesCounter counter)
19+
{
20+
if (this._context.Entry(counter).State == EntityState.Detached)
21+
{
22+
this._context.CoursesCounter.Add(counter);
23+
}
24+
else
25+
{
26+
this._context.CoursesCounter.Update(counter);
27+
}
28+
29+
await this._context.SaveChangesAsync();
30+
}
31+
32+
public CoursesCounter Search()
33+
{
34+
return this._context.CoursesCounter.FirstOrDefault();
35+
}
36+
}
37+
}

‎src/Mooc/Mooc.csproj

Copy file name to clipboardExpand all lines: src/Mooc/Mooc.csproj
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1717
</PackageReference>
1818
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.6" />
19+
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.2.6"/>
1920
<PackageReference Include="MySql.Data.EntityFrameworkCore" Version="8.0.18" />
2021
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
2122
</ItemGroup>

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.