does returning object in insert method violate cqrs pattern? - integration-testing

I have implemented MediatR in my asp.net core web api application.
Our controllers simply send a command or query to MediatR and return the result.
[HttpPost]
public async Task<IActionResult> CreateQuestion(CreateQuestionCommand command)
{
await Mediator.Send(command);
return Ok();
}
Due to the CQRS pattern that says commands should not return any value we don't return any value in our MediatR commands.
everything was normal since we decided to write some BDD tests.
In our BDD tests there is a simple scenario like this:
Scenario: [Try to add a new Question]
Given [I'm an authorized administrator]
When [I create a new Question with Title '<Title>' and '<Description>' and '<IsActive>' and '<IndicatorId'>]
Then [A question with Title '<Title>' and '<Description>' and '<IsActive>' and '<IndicatorId'> should be persisted in database]
Examples:
| Title | Description | IsActive | IndicatorId |
| This is a test title | this is a test description | true | 3cb23a10-107a-4834-8c1a-3fd893217861 |
We set Id property of Question object in its constructor. which means we don't know what Id we have set to this newly created Question and therefore we can't read it after adding it to database in a test environment.
my question was how to test it in BDD?
this is my test step implementation:
[When(#"\[I create a new Question with Title '([^']*)' and '([^']*)' and '([^']*)' and '([^']*)'>]")]
public async void WhenICreateANewQuestionWithTitleAndAndAnd(string title, string description, bool isActive, Guid indicatorId)
{
var command = new CreateQuestionCommand
{
Title = title,
Description = description,
IndicatorId = indicatorId
};
await questionController.CreateQuestion(command);
}
[Then(#"\[A question with Title '([^']*)' and '([^']*)' and '([^']*)' and '([^']*)'> should be persisted in database]")]
public void ThenAQuestionWithTitleAndAndAndShouldBePersistedInDatabase(string title, string description, string isActive, string indicatorId)
{
//? how to retrieve the created data. We don't have the Id here
}
How can I retrieve the added Question?
Should I change my command handlers to return my object after inserting it to database?
And if I do so, wouldn't it be a CQRS violation?
Thank you for your time.

There's a couple of ways to go about this, but it depends on how you actually expect the system to behave. If you're doing BDD you should focus on the kind of behaviour that would be observable by real users.
If you're implementing a system that allows users to create (and save, I infer) questions in a (Q&A?) database, then should they not have the ability to view or perhaps edit the question afterwards?
As the OP is currently phrased, the trouble writing the test seems to imply a lacking capability of the system in general. If the test can't identify the entity that was created, then how can a user?
The CreateQuestion method only returns Ok(), which means that there's no data in the response. Thus, as currently implemented, there's no way for the sender of the POST request to subsequently navigate to or retrieve the new resource.
How are users supposed to interact with the service? This should give you a hint about how to write the test.
A common REST pattern is to return the address of the new resource in the response's Location header. If the CreateQuestion method were to do that, the test would also be able to investigate that value and perhaps act on it.
Another option is to return the entity ID in the response body. Again, if that's the way things are supposed to work, the test could verify that.
Other systems are more asynchronous. Perhaps you only put the CreateQuestionCommand on a queue, to be handled later. In such a case I'd write a test that verifies that the command was added to the queue. You could also write a more long-running test that then waits for an asynchronous message handler to process the command, but if you want to test something like, you also need to deal with timeouts.
In a comment, you write:
I think he might add the question and then read all questions from database and see if his question is amongst them. He'd probably test without knowing Id.
Do you expect real users of the system to spelunk around in your database? Unless you do, the database is not part of a system's observable behaviour - it's an implementation detail. Thus, behaviour-driven design shouldn't concern itself with the contents of databases, but how a system behaves.
In short, find out how to observe the behaviour you want the system to have, and then test that.

Related

How to make command to wait until all events triggered against it are completed successfully

I have came across a requirement where i want axon to wait untill all events in the eventbus fired against a particular Command finishes their execution. I will the brief the scenario:
I have a RestController which fires below command to create an application entity:
#RestController
class myController{
#PostMapping("/create")
#ResponseBody
public String create(
org.axonframework.commandhandling.gateway.CommandGateway.sendAndWait(new CreateApplicationCommand());
System.out.println(“in myController:: after sending CreateApplicationCommand”);
}
}
This command is being handled in the Aggregate, The Aggregate class is annotated with org.axonframework.spring.stereotype.Aggregate:
#Aggregate
class MyAggregate{
#CommandHandler //org.axonframework.commandhandling.CommandHandler
private MyAggregate(CreateApplicationCommand command) {
org.axonframework.modelling.command.AggregateLifecycle.apply(new AppCreatedEvent());
System.out.println(“in MyAggregate:: after firing AppCreatedEvent”);
}
#EventSourcingHandler //org.axonframework.eventsourcing.EventSourcingHandler
private void on(AppCreatedEvent appCreatedEvent) {
// Updates the state of the aggregate
this.id = appCreatedEvent.getId();
this.name = appCreatedEvent.getName();
System.out.println(“in MyAggregate:: after updating state”);
}
}
The AppCreatedEvent is handled at 2 places:
In the Aggregate itself, as we can see above.
In the projection class as below:
#EventHandler //org.axonframework.eventhandling.EventHandler
void on(AppCreatedEvent appCreatedEvent){
// persists into database
System.out.println(“in Projection:: after saving into database”);
}
The problem here is after catching the event at first place(i.e., inside aggregate) the call gets returned to myController.
i.e. The output here is:
in MyAggregate:: after firing AppCreatedEvent
in MyAggregate:: after updating state
in myController:: after sending CreateApplicationCommand
in Projection:: after saving into database
The output which i want is:
in MyAggregate:: after firing AppCreatedEvent
in MyAggregate:: after updating state
in Projection:: after saving into database
in myController:: after sending CreateApplicationCommand
In simple words, i want axon to wait untill all events triggered against a particular command are executed completely and then return to the class which triggered the command.
After searching on the forum i got to know that all sendAndWait does is wait until the handling of the command and publication of the events is finalized, and then i tired with Reactor Extension as well using below but got same results: org.axonframework.extensions.reactor.commandhandling.gateway.ReactorCommandGateway.send(new CreateApplicationCommand()).block();
Can someone please help me out.
Thanks in advance.
What would be best in your situation, #rohit, is to embrace the fact you are using an eventually consistent solution here. Thus, Command Handling is entirely separate from Event Handling, making the Query Models you create eventually consistent with the Command Model (your aggregates). Therefore, you wouldn't necessarily wait for the events exactly but react when the Query Model is present.
Embracing this comes down to building your application such that "yeah, I know my response might not be up to date now, but it might be somewhere in the near future." It is thus recommended to subscribe to the result you are interested in after or before the fact you have dispatched a command.
For example, you could see this as using WebSockets with the STOMP protocol, or you could tap into Project Reactor and use the Flux result type to receive the results as they go.
From your description, I assume you or your business have decided that the UI component should react in the (old-fashioned) synchronous way. There's nothing wrong with that, but it will bite your *ss when it comes to using something inherently eventually consistent like CQRS. You can, however, spoof the fact you are synchronous in your front-end, if you will.
To achieve this, I would recommend using Axon's Subscription Query to subscribe to the query model you know will be updated by the command you will send.
In pseudo-code, that would look a little bit like this:
public Result mySynchronousCall(String identifier) {
// Subscribe to the updates to come
SubscriptionQueryResult<Result> result = QueryGateway.subscriptionQuery(...);
// Issue command to update
CommandGateway.send(...);
// Wait on the Flux for the first result, and then close it
return result.updates()
.next()
.map(...)
.timeout(...)
.doFinally(it -> result.close());
}
You could see this being done in this sample WebFluxRest class, by the way.
Note that you are essentially closing the door to the front-end to tap into the asynchronous goodness by doing this. It'll work and allow you to wait for the result to be there as soon as it is there, but you'll lose some flexibility.

Chaining Handlers with MediatR

We are using MediatR to implement a "Pipeline" for our dotnet core WebAPI backend, trying to follow the CQRS principle.
I can't decide if I should try to implement a IPipelineBehavior chain, or if it is better to construct a new Request and call MediatR.Send from within my Handler method (for the request).
The scenario is essentially this:
User requests an action to be executed, i.e. Delete something
We have to check if that something is being used by someone else
We have to mark that something as deleted in the database
We have to actually delete the files from the file system.
Option 1 is what we have now: A DeleteRequest which is handled by one class, wherein the Handler checks if it is being used, marks it as deleted, and then sends a new TaskStartRequest with the parameters to Delete.
Option 2 is what I'm considering: A DeleteRequest which implements the marker interfaces IRequireCheck, IStartTask, with a pipeline which runs:
IPipelineBehavior<IRequireCheck> first to check if the something is being used,
IPipelineBehavior<DeleteRequest> to mark the something as deleted in database and
IPipelineBehavior<IStartTask> to start the Task.
I haven't fully figured out what Option 2 would look like, but this is the general idea.
I guess I'm mainly wondering if it is code smell to call MediatR.Send(TRequest2) within a Handler for a TRequest1.
If those are the options you're set on going with - I say Option 2. Sending requests from inside existing Mediatr handlers can be seen as a code smell. You're hiding side effects and breaking the Single Responsibility Principle. You're also coupling your requests together and you should try to avoid situations where you can't send one type of request before another.
However, I think there might be an alternative. If a delete request can't happen without the validation and marking beforehand you may be able to leverage a preprocessor (example here) for your TaskStartRequest. That way you can have a single request that does everything you need. This even mirrors your pipeline example by simply leveraging the existing Mediatr patterns.
Is there any need to break the tasks into multiple Handlers? Maybe I am missing the point in mediatr. Wouldn't this suffice?
public async Task<Result<IFailure,ISuccess>> Handle(DeleteRequest request)
{
var thing = await this.repo.GetById(request.Id);
if (thing.IsBeignUsed())
{
return Failure.BeignUsed();
}
var deleted = await this.repo.Delete(request.Id);
return deleted ? new Success(request.Id) : Failure.DbError();
}

Where to keep "currentUser" globally accessible

Almost every object in my state tree needs to have the following fields:
createdByGuid
createdAt
modifiedAt
The date fields are easy to add in the action creators. There seems to be consensus that action creators are the place where impureness are allowed, i.e. new Date().
But the currently logged in user is not easily fetched since this data lives in another slice of the state.
Example state:
profile
data
guid
firstname
...
media
items
0: guid, createdByGuid, ...
1: guid, createdByGuid, ...
drawings
items
...
When a MEDIA_ADD action is dispatched I want the action creator to augment the dispatched data with createdById. Current user needs to be fetched from profile.data.guid.
I don't want to bring the state into my action creator. Instead I can use a thunk to get hold of the state via getState(). But this seems to be a clumsy way of getting hold of a simple guid constant (constant for this session). It becomes more clumsy when essentially all of my action creators for adding data to the state needs to be thunks.
I'm inclined to create a separate global singleton object to hold this data and bring this dependency into all of my action creator modules. This seems to be a lot less disturbing dependency in terms of for example testing.
I suppose most Redux users has about the same question regarding current user. What is a good solution?
I'm working in react-native, but I suppose the question applies to most Redux applications.
If someone is interested, I went the singleton way with this. Not a true singleton per definition, but it suits my needs.
When a user logs in I handle this in an asynchronous action creator (a thunk). The thunk calls setGlobalCurrentUser() after successfully authenticating the user with the server.
To get hold of the current user I only have to import currentUserGuid() from currentUser.js and I don't end up in a dependency hell.
currentUser.js:
let _currentUserGuid;
export function currentUserGuid() {
if(!_currentUserGuid) throw new Error('currentUserGuid:: No logged in user')
return _currentUserGuid;
}
export function setGlobalCurrentUser(user) {
if(user) {
_currentUserGuid = user.get('guid')
} else {
_currentUserGuid = null
}
}

Where should I put a logic for querying extra data in CQRS command flow

I'm trying to implement simple DDD/CQRS architecture without event-sourcing for now.
Currently I need to write some code for adding a notification to a document entity (document can have multiple notifications).
I've already created a command NotificationAddCommand, ICommandService and IRepository.
Before inserting new notification through IRepository I have to query current user_id from db using NotificationAddCommand.User_name property.
I'm not sure how to do it right, because I can
Use IQuery from read-flow.
Pass user_name to domain entity and resolve user_id in the repository.
Code:
public class DocumentsCommandService : ICommandService<NotificationAddCommand>
{
private readonly IRepository<Notification, long> _notificationsRepository;
public DocumentsCommandService(
IRepository<Notification, long> notifsRepo)
{
_notificationsRepository = notifsRepo;
}
public void Handle(NotificationAddCommand command)
{
// command.user_id = Resolve(command.user_name) ??
// command.source_secret_id = Resolve(command.source_id, command.source_type) ??
foreach (var receiverId in command.Receivers)
{
var notificationEntity = _notificationsRepository.Get(0);
notificationEntity.TargetId = receiverId;
notificationEntity.Body = command.Text;
_notificationsRepository.Add(notificationEntity);
}
}
}
What if I need more complex logic before inserting? Is it ok to use IQuery or should I create additional services?
The idea of reusing your IQuery somewhat defeats the purpose of CQRS in the sense that your read-side is supposed to be optimized for pulling data for display/query purposes - meaning that it can be denormalized, distributed etc. in any way you deem necessary without being restricted by - or having implications for - the command side (a key example being that it might not be immediately consistent, while your command side obviously needs to be for integrity/validity purposes).
With that in mind, you should look to implement a contract for your write side that will resolve the necessary information for you. Driving from the consumer, that might look like this:
public DocumentsCommandService(IRepository<Notification, long> notifsRepo,
IUserIdResolver userIdResolver)
public interface IUserIdResolver
{
string ByName(string username);
}
With IUserIdResolver implemented as appropriate.
Of course, if both this and the query-side use the same low-level data access implementation (e.g. an immediately-consistent repository) that's fine - what's important is that your architecture is such that if you need to swap out where your read side gets its data for the purposes of, e.g. facilitating a slow offline process, your read and write sides are sufficiently separated that you can swap out where you're reading from without having to untangle reads from the writes.
Ultimately the most important thing is to know why you are making the architectural decisions you're making in your scenario - then you will find it much easier to make these sorts of decisions one way or another.
In a project i'm working i have similar issues. I see 3 options to solve this problem
1) What i did do is make a UserCommandRepository that has a query option. Then you would inject that repository into your service.
Since the few queries i did need were so simplistic (just returning single values) it seemed like a fine tradeoff in my case.
2) Another way of handling it is by forcing the user to just raise a command with the user_id. Then you can let him do the querying.
3) A third option is ask yourself why you need a user_id. If it's to make some relations when querying the data you could also have this handles when querying the data (or when propagating your writeDB to your readDB)

ASP.net Identity ChangePassword is inefficient

I am using ASP.net Identity 2.0 with a user id of an integer. Performing a password update is an incredibly expensive database operation with 2 (unneeded) queries both averaging 128,407 db time units, or about a 7 in the query plan, based on the amount of data I have.
Code I am calling (either async or sync are the same)
var result = await UserManager.ChangePasswordAsync(userId, oldPassword, newPassword);
// or
var result = UserManager.ChangePassword(userId, oldPassword, newPassword);
In the database this causes two large sql calls which contain in their guts
AspNetUserRoles ... WHERE ((UPPER([Extent1].[Email])) = (UPPER(#p__linq__0))) ...
query 2:
AspNetUserRoles ... WHERE ((UPPER([Extent1].[UserName])) = (UPPER(#p__linq__0))) ...
From my perspective
There is no reason to call this sql at all - a lookup by the int ID is fast, and the sql it is calling is looking up role data.
using "Upper" is probably what makes it slow, and if there is no other better solution I can add a computed index (System.Web.Providers.DefaultMembershipProvider having performance issues/deadlocks)
At a high level my question is - is there a work around for this, or can someone from the Identity team fix the code (if it is indeed broken).
Update
The same behavior can be observed for the following calls (and probably many others)
UserManager.ResetPasswordAsync
UserManager.CreateAsync
Well you can certainly do it yourself instead of calling that method.
Imagine you have, in scope, a UserManager<ApplicationUser> called userManager and a DbContext called context.
var user = await context.Users.Single(u => u.Id == knownId);
// You can skip this if you don't care about checking the old password...
if (userManager.PasswordHasher.VerifyHashedPassword(user.HashedPassword, "myOldPassword") == PasswordVerificationResult.Failed) { return; };
user.HashedPassword = userManager.PasswordHasher.HashPassword("myNewPassword");
await context.SaveChangesAsync();
If that's still not optimized enough for you, DbContext exposes a Sql method, so you could just use the password hasher to get a hash, then issue a single Update() query.
I wouldn't do either of these things unless this is really a bottleneck or you have some other good reason, though. I'm doing something similar in my application because, at least in ASP.NET Identity v1, there's no method to just change the password without checking the old one.
I believe the answer provided by #emodendroket correctly and efficiently answered my original question. Due to the implications of needing to modify numerous parts of the API in the short term I am going with a simpler (but not as good solution)
Add a computed and persisted index on email and usernames
ALTER TABLE dbo.aspnetusers ADD UpperFieldEmail AS UPPER(email) PERSISTED
CREATE NONCLUSTERED INDEX IX_aspnetusers_UpperFieldEmail ON dbo.aspnetusers(UpperFieldEmail)
ALTER TABLE dbo.aspnetusers ADD UpperFieldUsername AS UPPER(username) PERSISTED
CREATE NONCLUSTERED INDEX IX_aspnetusers_UpperFieldUsername ON dbo.aspnetusers(UpperFieldUsername)

Resources