Skip to content

Commit 585a75b

Browse files
committed
add review mutations and subscriptions
1 parent d6a3e40 commit 585a75b

24 files changed

+285
-789
lines changed

dotnet/OpenBreweryDB.API/GraphQL/Queries/BreweriesQuery.cs renamed to dotnet/OpenBreweryDB.API/GraphQL/Breweries/BreweryQueries.cs

File renamed without changes.

dotnet/OpenBreweryDB.API/GraphQL/Resolvers/BreweryResolvers.cs renamed to dotnet/OpenBreweryDB.API/GraphQL/Breweries/BreweryResolvers.cs

File renamed without changes.

dotnet/OpenBreweryDB.API/GraphQL/Types/BreweryType.cs renamed to dotnet/OpenBreweryDB.API/GraphQL/Breweries/Types/BreweryType.cs

File renamed without changes.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using System;
2+
using System.Linq;
3+
using System.Threading;
4+
using System.Threading.Tasks;
5+
using AndcultureCode.CSharp.Core.Extensions;
6+
using HotChocolate;
7+
using HotChocolate.Execution;
8+
using HotChocolate.Subscriptions;
9+
using HotChocolate.Types;
10+
using OpenBreweryDB.API.GraphQL.Reviews.Types;
11+
using OpenBreweryDB.Core.Conductors.Breweries.Interfaces;
12+
using OpenBreweryDB.Data;
13+
using OpenBreweryDB.Data.Models.Reviews;
14+
15+
namespace OpenBreweryDB.API.GraphQL.Reviews
16+
{
17+
[ExtendObjectType(Name = "Mutation")]
18+
public class ReviewMutations
19+
{
20+
private const string SUBJECT_EMPTY = "The subject cannot be empty.";
21+
private const string BODY_EMPTY = "The body cannot be empty.";
22+
23+
public async Task<ReviewPayload> CreateReview(
24+
ReviewInput input,
25+
[Service] BreweryDbContext dbContext,
26+
[Service] IBreweryConductor breweryConductor,
27+
[Service] ITopicEventSender eventSender,
28+
CancellationToken cancellationToken)
29+
{
30+
if (string.IsNullOrEmpty(input.Subject))
31+
{
32+
throw new QueryException(
33+
ErrorBuilder.New()
34+
.SetMessage(SUBJECT_EMPTY)
35+
.SetCode(nameof(SUBJECT_EMPTY))
36+
.Build());
37+
}
38+
39+
if (string.IsNullOrEmpty(input.Body))
40+
{
41+
throw new QueryException(
42+
ErrorBuilder.New()
43+
.SetMessage(BODY_EMPTY)
44+
.SetCode(nameof(BODY_EMPTY))
45+
.Build());
46+
}
47+
48+
var review = new Review
49+
{
50+
Subject = input.Subject,
51+
Body = input.Body,
52+
BreweryId = input.BreweryId,
53+
CreatedOn = DateTimeOffset.Now,
54+
};
55+
56+
_ = await dbContext.AddAsync(review);
57+
_ = await dbContext.SaveChangesAsync(cancellationToken);
58+
59+
var breweryResult = breweryConductor.Find(input.BreweryId);
60+
61+
if (breweryResult.HasErrorsOrResultIsNull())
62+
{
63+
var error = breweryResult.Errors.First();
64+
65+
throw new QueryException(
66+
ErrorBuilder.New()
67+
.SetMessage(error.Message)
68+
.SetCode(error.Key)
69+
.Build());
70+
}
71+
72+
review.Brewery = breweryResult.ResultObject;
73+
74+
await eventSender.SendAsync("reviews", review, cancellationToken);
75+
76+
return new ReviewPayload(review, input.ClientMutationId);
77+
}
78+
}
79+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System.Collections.Generic;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
using HotChocolate;
5+
using HotChocolate.Subscriptions;
6+
using HotChocolate.Types;
7+
using OpenBreweryDB.Data.Models.Reviews;
8+
9+
namespace OpenBreweryDB.API.GraphQL.Reviews
10+
{
11+
[ExtendObjectType(Name = "Subscription")]
12+
public class ReviewSubscriptions
13+
{
14+
[SubscribeAndResolve]
15+
public async Task<IAsyncEnumerable<Review>> OnReviewReceivedAsync(
16+
[Service] ITopicEventReceiver eventReceiver,
17+
CancellationToken cancellationToken)
18+
{
19+
return await eventReceiver.SubscribeAsync<string, Review>("reviews", cancellationToken);
20+
}
21+
}
22+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using HotChocolate;
2+
using HotChocolate.Types.Relay;
3+
using OpenBreweryDB.API.GraphQL.Common;
4+
using OpenBreweryDB.Core.Models;
5+
6+
namespace OpenBreweryDB.API.GraphQL.Reviews.Types
7+
{
8+
public class ReviewInput : ClientMutationBase
9+
{
10+
public ReviewInput(
11+
long breweryId,
12+
string subject,
13+
string body,
14+
string clientMutationId) : base(clientMutationId)
15+
{
16+
Subject = subject;
17+
Body = body;
18+
BreweryId = breweryId;
19+
}
20+
21+
[GraphQLNonNullType]
22+
public string Subject { get; }
23+
24+
[GraphQLNonNullType]
25+
public string Body { get; }
26+
27+
[ID(nameof(Brewery))]
28+
[GraphQLNonNullType]
29+
public long BreweryId { get; }
30+
}
31+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using OpenBreweryDB.API.GraphQL.Common;
2+
using OpenBreweryDB.Data.Models.Reviews;
3+
4+
namespace OpenBreweryDB.API.GraphQL.Reviews.Types
5+
{
6+
public class ReviewPayload : ClientMutationBase
7+
{
8+
public ReviewPayload(
9+
Review review,
10+
string clientMutationId) : base(clientMutationId)
11+
{
12+
Review = review;
13+
}
14+
15+
public Review Review { get; }
16+
}
17+
}

dotnet/OpenBreweryDB.API/Startup.cs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
using OpenBreweryDB.Data.Models.Users;
2626
using OpenBreweryDB.Core.Conductors.Users.Interfaces;
2727
using OpenBreweryDB.API.GraphQL.Users;
28+
using OpenBreweryDB.API.GraphQL.Reviews;
29+
using HotChocolate.Subscriptions;
2830

2931
namespace OpenBreweryDB.API
3032
{
@@ -48,7 +50,9 @@ public void ConfigureServices(IServiceCollection services)
4850
services.AddDbContext<BreweryDbContext>(options => options.UseSqlite("Data Source=openbrewery.db"));
4951
services.AddControllers();
5052

51-
services.AddGraphQL(sp => SchemaBuilder.New()
53+
services
54+
.AddInMemorySubscriptions()
55+
.AddGraphQL(sp => SchemaBuilder.New()
5256
.EnableRelaySupport()
5357
.AddServices(sp)
5458

@@ -61,9 +65,13 @@ public void ConfigureServices(IServiceCollection services)
6165
.AddMutationType(d => d.Name("Mutation"))
6266
.AddType<UserMutations>()
6367
.AddType<BreweryMutations>()
68+
.AddType<ReviewMutations>()
69+
.AddSubscriptionType(d => d.Name("Subscription"))
70+
.AddType<ReviewSubscriptions>()
6471
.Create(),
6572
new QueryExecutionOptions
6673
{
74+
ForceSerialExecution = true,
6775
IncludeExceptionDetails = true,
6876
TracingPreference = TracingPreference.Always
6977
});
@@ -97,7 +105,7 @@ public void ConfigureServices(IServiceCollection services)
97105
{
98106
options.AddDefaultPolicy(builder =>
99107
{
100-
builder.WithOrigins("http://localhost:3000")
108+
builder.AllowAnyOrigin()
101109
.AllowAnyHeader()
102110
.AllowAnyMethod();
103111
});
@@ -113,14 +121,14 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
113121
}
114122

115123
app.UseCors();
116-
app.UseWebSockets();
117124
app.UseRouting();
118125

119126
app.UseAuthentication();
120127

121-
app.UseGraphQL("/graphql");
122-
app.UsePlayground("/graphql");
123-
app.UseVoyager("/graphql");
128+
app.UseWebSockets()
129+
.UseGraphQL("/graphql")
130+
.UsePlayground("/graphql")
131+
.UseVoyager("/graphql");
124132

125133
app.UseEndpoints(endpoints =>
126134
{

dotnet/OpenBreweryDB.Data/BreweryDbContext.cs

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
2323
modelBuilder.Entity<Brewery>()
2424
.ToTable("breweries");
2525

26+
modelBuilder.Entity<Brewery>()
27+
.HasMany(b => b.BreweryReviews)
28+
.WithOne(r => r.Brewery);
29+
2630
// Entity: BreweryTag
2731
modelBuilder.Entity<BreweryTag>()
2832
.HasKey(t => new { t.BreweryId, t.TagId });
@@ -62,19 +66,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
6266

6367
// Entity: Review
6468
modelBuilder.Entity<Review>()
65-
.ToTable("reviews")
66-
.HasKey(f => new { f.BreweryId, f.UserId });
67-
modelBuilder.Entity<Review>()
68-
.Property(r => r.CreatedOn)
69-
.HasDefaultValueSql("GETDATE()");
70-
modelBuilder.Entity<Review>()
71-
.HasOne(f => f.User)
72-
.WithMany(u => u.UserReviews)
73-
.HasForeignKey(u => u.UserId);
74-
modelBuilder.Entity<Review>()
75-
.HasOne(f => f.Brewery)
76-
.WithMany(u => u.BreweryReviews)
77-
.HasForeignKey(u => u.BreweryId);
69+
.ToTable("reviews");
7870
}
7971
}
8072
}

dotnet/OpenBreweryDB.Data/Migrations/20200125210434_InitialModel.Designer.cs

Lines changed: 0 additions & 123 deletions
This file was deleted.

0 commit comments

Comments
 (0)