DDD / CQRS / ES Implement the aggregate member using the graph database, and also use the immediately consistent readModel as a collection of entities

annotation

I am modeling a common authorization subdomain for my application. The requirements are quite complex, as they must cope with several tenants, the hierarchical structure of the organization, resource groups, user groups, permissions, user permissions, etc. This is a mixture of RBAC (users assigned to roles, roles with permissions, permissions can execute commands) with claims-based authorization.

Problem

When checking for business rule invariants, I need to go through a “cut” of permission to find permission for the user to execute a command on a resource in the environment. Depth of circumvention of arbitrariness, in many ways.

I could simulate this using code, but it is best to imagine it using a graph database, as requests / updates in this aggregate will be faster. In addition, this will reduce the complexity of the code itself. But this requires that the graph database be immediately consistent.

However, I need to use CQRS / ES and enable the distributed architecture.

So the graph database should be

  • Directly sequential

And this leads to some disadvantages.

  • When loading events from the event store, we must restore the graph database each time
  • Or should we enter some snapshot of the graph database snapshot
  • Overhead when communicating with a graph database

But he has advantages

  • Reduced complexity of complex query execution
  • Complex queries resolve faster than with code
  • The graph database is perfect for this job.

Why this question?

In other aggregates that I modeled, I often have an EntityList or EntityHierarchy . This is basically an ordered / hierarchical set of sub-arguments. Their implementation is arbitrary. They can support anything from indexing, key-value pairs, dynamic arrays, etc. While they implement the interfaces that I announced to them. I often even have methods like findById() or findByName() for these objects (lists). These methods are similar to methods that can be executed in a database, but they are executed in memory.

Thus, why not implement a list that can be bound to a database? For example, instead of a TMemoryEntityList , I would have a TMySQLEntityList . In this case, it is desirable to have a TGraphAuthorizationScheme implementation that will live inside the TOrgAuthPolicy aggregate. As long as it behaves like a collection and that it is iterable and supports certain interfaces.

I am building my JavaScript application on Node.js. There is a built-in implementation of this LevelGraph function. Maybe I can use this too. But go on.

Sentence

I know that in DDD conditions the infrastructure should not flow in the domain. This is what I am trying to prevent. This is also one of the reasons why I asked this question, because the first time I come across such a technical need, and I ask people who are used to dealing with this problem for some tips.

Interface for the IAuthorizationScheme collection. The implementation should support deep crawl, authorization search, etc. This is the interface I’m thinking about implementing, supporting it with a graph database.

Sequence:

1 When a user asks for a command, I check it first. I find his organization and ask OrgAuthPolicyRepository download their organization corresponding to OrgAuthPolicy .

  1. OrgAuthPolicyRepository loads events from an EventStore .

  2. OrgAuthPolicyRepository creates a new OrgAuthPolicy with a TGraphAuthorizationScheme instance with dependency encapsulation.

  3. OrgAuthPolicyRepository applies all previous events to OrgAuthPolicy , which alternately raises queries in the graph database to synchronize GraphDatabase states with the aggregate.

  4. The command handler performs validation checks on business rules. Some of these may include checks with the IAuthorizationScheme aggregate.

  5. Business rules were verified and a domain event was sent.

  6. The unit processes this event and applies it to itself. This may include changes to IAuthorizationScheme .

  7. EventBus dispatched an event to all eventHandlers on the read side.

Example:

enter image description here

In summary

Is it possible / desirable to implement objects using external databases (for example, a graph database) to make their implementation easier? If so, are there any examples of such an implementation or guidelines? If not, what are the disadvantages of using such a technique?

+6
source share
1 answer

To solve your problem, I would consider the following options, going from top to bottom:

  • Reduce task complexity using a security framework or identity management solution. Some existing out of the box identity management solutions can do the job. If he is not considering structures to help you realize your own. Unfortunately, I am new to Node.js advice, any advice from you. In the Java world, which may be Apache Shiro or Spring Security . This can be a good option both in terms of cost and in terms of security.
  • Maintain a single model instead of CQRS. This eliminates the problems of consistency (if you decide to have separate resources for storing your models). From my understanding, permissions should not change often, but they will be available often. This means that you can live with one model optimized for reads, avoid consistency issues and support 2 models. To track user behavior, you can audit separately. In my experience with security auditing, additional data may be needed that is most likely not in your data model.
  • Do it with CQRS. And here, I would first review the requirements of the revision to find a way to accept final consistency instead of strong consistency. This opens up many implementation options.

Regarding the question of whether to use the embedded graphical database, it is impossible to answer without knowing your domain, budget, desired throughput and system performance, existing infrastructure, knowledge and team settings, etc. You need to estimate the costs of the solution using special Graph Database and without it. My completion is that if permission management is not the main idea of ​​your project or your project is mature enough (in terms of the number of users and R&D capabilities), then a dedicated database is unlikely to cover the costs of performing your task.

To understand that it can be beneficial to have a dedicated graph database, existing storage solutions should be taken in the opposite direction. These 2 articles explain pretty well what could be these benefits:

+2
source

All Articles