diff --git a/src/Http/Wolverine.Http.Tests/Marten/compiled_query_writer.cs b/src/Http/Wolverine.Http.Tests/Marten/compiled_query_writer.cs new file mode 100644 index 000000000..6aa186044 --- /dev/null +++ b/src/Http/Wolverine.Http.Tests/Marten/compiled_query_writer.cs @@ -0,0 +1,69 @@ +using Alba; +using Marten.Schema.Identity; +using Shouldly; +using WolverineWebApi.Marten; + +namespace Wolverine.Http.Tests.Marten; + +public class compiled_query_writer : IntegrationContext +{ + public compiled_query_writer(AppFixture fixture) : base(fixture) + { + } + + [Fact] + public async Task endpoint_returning_compiled_list_query_should_return_query_result() + { + await using var session = Store.LightweightSession(); + int notApprovedInvoices = 5; + int approvedInvoices = 3; + for (int i = 0; i < notApprovedInvoices; i++) + { + var invoice = + new Invoice() + { + Approved = false + }; + session.Store(invoice); + } + + for (int i = 0; i < approvedInvoices; i++) + { + var invoice = + new Invoice() + { + Approved = true + }; + session.Store(invoice); + } + + await session.SaveChangesAsync(); + + var approvedInvoiceList = await Host.GetAsJson>("/invoices/approved"); + approvedInvoiceList.ShouldNotBeNull(); + approvedInvoiceList.Count.ShouldBe(approvedInvoices); + } + + [Fact] + public async Task endpoint_returning_compiled_query_should_return_query_result() + { + var invoice = new Invoice() + { + Id = Guid.NewGuid() + }; + using var session = Store.LightweightSession(); + session.Store(invoice); + await session.SaveChangesAsync(); + + + var invoiceCompiled = await Host.GetAsJson($"/invoices/compiled/{invoice.Id}"); + invoiceCompiled.ShouldNotBeNull(); + invoiceCompiled.Id.ShouldBe(invoice.Id); + + await Host.Scenario(x => + { + x.Get.Url($"/invoices/compiled/{Guid.NewGuid()}"); + x.StatusCodeShouldBe(404); + }); + } +} \ No newline at end of file diff --git a/src/Http/WolverineWebApi/Internal/Generated/WolverineHandlers/GET_invoices_approved.cs b/src/Http/WolverineWebApi/Internal/Generated/WolverineHandlers/GET_invoices_approved.cs new file mode 100644 index 000000000..5363be0e0 --- /dev/null +++ b/src/Http/WolverineWebApi/Internal/Generated/WolverineHandlers/GET_invoices_approved.cs @@ -0,0 +1,47 @@ +// +#pragma warning disable +using Microsoft.AspNetCore.Routing; +using System; +using System.Linq; +using Wolverine.Http; +using Wolverine.Marten.Publishing; +using Wolverine.Runtime; + +namespace Internal.Generated.WolverineHandlers +{ + // START: GET_invoices_approved + public class GET_invoices_approved : Wolverine.Http.HttpHandler + { + private readonly Wolverine.Http.WolverineHttpOptions _wolverineHttpOptions; + private readonly Wolverine.Marten.Publishing.OutboxedSessionFactory _outboxedSessionFactory; + private readonly Wolverine.Runtime.IWolverineRuntime _wolverineRuntime; + + public GET_invoices_approved(Wolverine.Http.WolverineHttpOptions wolverineHttpOptions, Wolverine.Marten.Publishing.OutboxedSessionFactory outboxedSessionFactory, Wolverine.Runtime.IWolverineRuntime wolverineRuntime) : base(wolverineHttpOptions) + { + _wolverineHttpOptions = wolverineHttpOptions; + _outboxedSessionFactory = outboxedSessionFactory; + _wolverineRuntime = wolverineRuntime; + } + + + + public override async System.Threading.Tasks.Task Handle(Microsoft.AspNetCore.Http.HttpContext httpContext) + { + var messageContext = new Wolverine.Runtime.MessageContext(_wolverineRuntime); + // Building the Marten session + await using var documentSession = _outboxedSessionFactory.OpenSession(messageContext); + + // The actual HTTP request handler execution + var approvedInvoicedCompiledQuery = WolverineWebApi.Marten.InvoicesEndpoint.GetApproved(); + + // Run the compiled query and stream the response + await Marten.AspNetCore.QueryableExtensions.WriteArray(documentSession, approvedInvoicedCompiledQuery, httpContext); + } + + } + + // END: GET_invoices_approved + + +} + diff --git a/src/Http/WolverineWebApi/Internal/Generated/WolverineHandlers/GET_invoices_compiled_id.cs b/src/Http/WolverineWebApi/Internal/Generated/WolverineHandlers/GET_invoices_compiled_id.cs new file mode 100644 index 000000000..481bc1b3a --- /dev/null +++ b/src/Http/WolverineWebApi/Internal/Generated/WolverineHandlers/GET_invoices_compiled_id.cs @@ -0,0 +1,54 @@ +// +#pragma warning disable +using Microsoft.AspNetCore.Routing; +using System; +using System.Linq; +using Wolverine.Http; +using Wolverine.Marten.Publishing; +using Wolverine.Runtime; + +namespace Internal.Generated.WolverineHandlers +{ + // START: GET_invoices_compiled_id + public class GET_invoices_compiled_id : Wolverine.Http.HttpHandler + { + private readonly Wolverine.Http.WolverineHttpOptions _wolverineHttpOptions; + private readonly Wolverine.Marten.Publishing.OutboxedSessionFactory _outboxedSessionFactory; + private readonly Wolverine.Runtime.IWolverineRuntime _wolverineRuntime; + + public GET_invoices_compiled_id(Wolverine.Http.WolverineHttpOptions wolverineHttpOptions, Wolverine.Marten.Publishing.OutboxedSessionFactory outboxedSessionFactory, Wolverine.Runtime.IWolverineRuntime wolverineRuntime) : base(wolverineHttpOptions) + { + _wolverineHttpOptions = wolverineHttpOptions; + _outboxedSessionFactory = outboxedSessionFactory; + _wolverineRuntime = wolverineRuntime; + } + + + + public override async System.Threading.Tasks.Task Handle(Microsoft.AspNetCore.Http.HttpContext httpContext) + { + var messageContext = new Wolverine.Runtime.MessageContext(_wolverineRuntime); + // Building the Marten session + await using var documentSession = _outboxedSessionFactory.OpenSession(messageContext); + if (!System.Guid.TryParse((string)httpContext.GetRouteValue("id"), out var id)) + { + httpContext.Response.StatusCode = 404; + return; + } + + + + // The actual HTTP request handler execution + var byIdCompiled = WolverineWebApi.Marten.InvoicesEndpoint.GetCompiled(id); + + // Run the compiled query and stream the response + await Marten.AspNetCore.QueryableExtensions.WriteOne(documentSession, byIdCompiled, httpContext); + } + + } + + // END: GET_invoices_compiled_id + + +} + diff --git a/src/Http/WolverineWebApi/Marten/Documents.cs b/src/Http/WolverineWebApi/Marten/Documents.cs index 14dd65fca..738e0ba2e 100644 --- a/src/Http/WolverineWebApi/Marten/Documents.cs +++ b/src/Http/WolverineWebApi/Marten/Documents.cs @@ -1,4 +1,6 @@ +using System.Linq.Expressions; using Marten; +using Marten.Linq; using Microsoft.AspNetCore.Mvc; using Wolverine.Http; using Wolverine.Http.Marten; @@ -54,6 +56,18 @@ public static IMartenOp Approve([Document("number")] Invoice invoice) } #endregion + + [WolverineGet("/invoices/approved")] + public static ApprovedInvoicedCompiledQuery GetApproved() + { + return new ApprovedInvoicedCompiledQuery(); + } + + [WolverineGet("/invoices/compiled/{id}")] + public static ByIdCompiled GetCompiled(Guid id) + { + return new ByIdCompiled(id); + } } public class Invoice @@ -61,4 +75,27 @@ public class Invoice public Guid Id { get; set; } public bool Paid { get; set; } public bool Approved { get; set; } +} + +public class ApprovedInvoicedCompiledQuery : ICompiledListQuery +{ + public Expression, IEnumerable>> QueryIs() + { + return q => q.Where(x => x.Approved); + } +} + +public class ByIdCompiled : ICompiledQuery +{ + public readonly Guid Id; + + public ByIdCompiled(Guid id) + { + Id = id; + } + + public Expression, Invoice?>> QueryIs() + { + return q => q.FirstOrDefault(x => x.Id == Id); + } } \ No newline at end of file diff --git a/src/Http/WolverineWebApi/Program.cs b/src/Http/WolverineWebApi/Program.cs index 65fda8774..be968556d 100644 --- a/src/Http/WolverineWebApi/Program.cs +++ b/src/Http/WolverineWebApi/Program.cs @@ -12,6 +12,7 @@ using Wolverine.FluentValidation; using Wolverine.Http; using Wolverine.Http.FluentValidation; +using Wolverine.Http.Marten; using Wolverine.Http.Tests.DifferentAssembly.Validation; using Wolverine.Marten; using WolverineWebApi; @@ -139,6 +140,8 @@ // Only want this middleware on endpoints on this one handler opts.AddMiddleware(typeof(BeforeAndAfterMiddleware), chain => chain.Method.HandlerType == typeof(MiddlewareEndpoints)); + + opts.UseMartenCompiledQueryResultPolicy(); #region sample_register_http_middleware_by_type opts.AddMiddlewareByMessageType(typeof(FakeAuthenticationMiddleware)); diff --git a/src/Http/WolverineWebApi/WolverineWebApi.csproj b/src/Http/WolverineWebApi/WolverineWebApi.csproj index ee9ccc949..433795a07 100644 --- a/src/Http/WolverineWebApi/WolverineWebApi.csproj +++ b/src/Http/WolverineWebApi/WolverineWebApi.csproj @@ -10,7 +10,7 @@ - +