1

I am using eventual consistency and domain events in DDD an I have encountered the following issue.

When creating domain object using factory I can generate a GUID, but cannot get a DB generated ID in order to return a valid ID as a part of the response.

Is it possible and how to get DB generated ID using domain events, upon persisting domain object in a same transaction and avoid waiting for eventual consistency.

DB generated ID is a part of the same aggregate root and repository.

mko
  • 6,638
  • 12
  • 67
  • 118
  • Why do you need those database IDs? – Constantin Galbenu Jul 24 '17 at 13:04
  • For example user posts rest api request to create an object of some type, and in rest api response user expects the id of that new object (in a user friendly format, not guid) – mko Jul 24 '17 at 14:29
  • See [here](https://stackoverflow.com/questions/9543715/generating-human-readable-usable-short-but-unique-ids) how to represent GUID's in human readable way – kayess Jul 24 '17 at 14:45
  • Sure, but i need integer as an ID – mko Jul 24 '17 at 14:48
  • [Here](https://stackoverflow.com/questions/1353555/represent-a-guid-as-a-set-of-integers) and [here](https://stackoverflow.com/questions/2920696/how-generate-unique-integers-based-on-guids). – kayess Jul 24 '17 at 14:54
  • Alough it is a good idea, i dont think it will work to provide unique object id. Guid to int cannot provide 100% uniqueness. – mko Jul 24 '17 at 16:28

2 Answers2

0

I think you can have two options:

  1. If the object creation is not expensive, you don't have to be eventual consistent. Create the object in DB and return the generated ID.

  2. If expensive, break object creation to small units. The root object should be created simple and quick to be persisted in DB and return the generated ID. Let the other child objects/aggregates to be created eventual consistent via events/messages.

alltej
  • 6,787
  • 10
  • 46
  • 87
0

The approach that I have seen that seems to work best is to have a SQL db server with a single integral IDENTITY column to issue the ID's, which you need to do before actually even create the entity (when create the commands for example if you're using CQRS too). This approach is actually quite simple to do and support and only requires one additional table (or not even that) in your db. This is not an uncommon practice and relieves your bc from the responsibility of owning logic of ID generation (in certain case this can be quite useful).

CAUTION: as with all things in our software world this has a number of trade-offs:

  1. It can guarantee ordering but the sequence of id's may have gaps if a certain operation with one id fails and you retry your action. This is only important if you care about ordering the creation of your entities :)
  2. This impacts performance as you have a single bottleneck (honestly you need to have a really large traffic for this to be a noticeable problem so I would not consider this a big problem)
  3. It may be a security concern in certain contexts depending on how this id is used.

I have to say that all points above are quite niche and I don't expect to really be a problem.

For reference and more information about this practice you can read about Twitter's Snowflake project. Snowflake generated sequential guid-like 64-bit integral id's but a lot, if not all, of the principles still apply in this case. There are a lot of information and best practices about this practice in a lot of articles discussing Snowflake.

Regards, Savvas

Savvas Kleanthous
  • 2,695
  • 17
  • 18