"Create on Demand" architecture question

Hi all,

hopefully this is the right place to discuss a general architectural question.

I try to see my software system as a alternating sequence of view model compositions and commmand executions. Due to the distritubted nature of NSB systems in each operation (vm composition and command execution) there are mutliple services involved. This works well for cases where the data for the composition is already present in the service and a command execution adds or manipulates data that is then visible in the next view model composition.

As an example consider adding a position to the basket: i do a view model composition, the basket is empty. I issue the command to add something to the basket. Several services work independently an create their own data, for example one services reminds that the position is in the basket, one services adds availability information and another services calulates the price. In the next composition all these services add their respective information to the basket position and the basket is rendered with all information being tied togehter.

But I also have a cases where the data is not already present in a service when the first composition starts, becuase there does not seem to be a natural trigger for generating it. In that case when the composition starts we notice that there is no data and we then need to issue a command in turn of the composition, wait for this command to finish (ugh) and then return the data.

I will give an example for this too. Take a webshop where every customer gets specific prices for all of your many articles depending on a lot of parameters. Say you have 10000 articles and a customer gets a different price depending on the date, the time, a group and the fact wehter he ordered today already (so he might get a different price on a second order on the same day). All these parameters can easily be evaluated once a single positon is added to the basket, because the service that calculates the prices konws all the invariants. But the customer wants to see a list of products with the prices he will have to pay attached. If I have as little as 1000 customers given I have four parameters (date, time, number of same day orders, group) how can I compute all possible prices in advance? As we know “Batch jobs” are flawed and I simply do not know what prices to calculate in advance because I do not know when and how often the customer will order a specific product in a day.

There does not seem to be a good “command” that I can issue to start calculating the prices. Something like “ShowArticlePage” does not seem to be a proper command. And even if I would go with it, the command would be issued in the same moment as the customer expects the result - so the user really requests a composition. But the data for the composition needs to be “Created on demand”. But that does not seem to be a good fit for executing a command because commands should be executed purely asynchronous.

One solution would probably be to use WebSockets or something to update the prices once the calculation is done in an asynchronus manner. But we encounterd problems with it with some customers that could somehow not establish a web socket connection. So this seems to be risky as well. Polling would eventually create a lot of load to the system. Another possibility I already thought of is to just calculate the prices for a page on the fly, so not issuing a command so that the calculated prices are only used for display and not being stored at all. But that would be a hit to performance because the prices will be recalculated every time I switch throuhg the pages.

I hope I have explained my problem in an understandable way. I am really a little stuck here and I do not know how to handle the situation properly. Any thoughts are welcom.

Cheers,
Tobias.

Hi Tobias,

I think you have at least 3 options:

  1. Calculate everything on the query side

It could be slow but maybe you can play with business requirements/workarounds to increase the speed:

  • Could you calculate prices for the concrete (logged) customer? If yes then you don’t have to calculate for 1000 customers every time.
  • Could you show results using paging? If yes then you don’t have to calculate for 10000 articles every time, only for 10/50/100 - depends on the page size.
  • Could you …?

Considering above you can test the calculation time.

  • Milliseconds? Probably acceptable.
  • Seconds? Acceptable maybe with some kind of information/widget showing that something is happening - like refreshing info about Azure Costs for example.
    Minutes? Probably not acceptable.
  1. Calculate everything on the command side then the Query is the simple SELECT.

Two actions could be best to re-calculate prices for the concrete Customer:

  • Making new order by the Customer
  • Changing group by the Customer

The challenge is the date and time. It could be tricky depends how often the price must be change in time: once a second/minute/hour/12 hours?. Remember about business requirements/workarounds. In most cases there are negotiable :wink:

The action could be the Saga instance for every Customer with timeout event starting re-calculation process.

  1. Hybrid solution. Some part of data could be calculate on the Command side and some on the Query side.
  • Making new order and changing group be the user → command side
  • Date and Time → query side

In all possible solution for sure you have to deal with stale data so the business decisions are needed in case when user see some price of the article but in the meantime the price for the same article changed.

Hope hits help.
Mike

Hi Tobias,

Could you explain more about what types of products are being sold, and to which kinds of customers? I have a feeling that that context would help model things better.

Thanks,
Udi

IT consultant lesson learned -> before give a solution, make sure what is the real problem :slight_smile:

Hi Mike,

thanks a lot for your detailed answer.

Option 1, doing everything on the client side seems to be the straight forward way and the easiest to implement. But in that case the result of the calculation should not be persisted because then the query side would affect the command side, right?

Option 2 I do not see fit, because that would mean that I could determine all the discrete values of every parameter. The pricing rule system can be configured by the customer and it is rather complex. I just took out some examples to keep the explanation simple. It is for example possible to define price rules that only apply during a specific time frame (some kind of promotion on an article).

Option 3 seems appealing. Maybe it is possible to calculate a kind of base price list based on the more static rules like for every customer group and article number. If the prices have a timestamp denoting its validity it would even be possible to handle the promotions. Stuff like situation specific discounts / subsidies could then be calculated on top of that. I will definitely explore this option more.

Thanks for your help!

Cheers,
Tobias.

Hi Udi,

the products being sold are frozen meals. They are sold within companies that do have a canteen but do not cook themselves. The canteen staff orders the frozen food, puts it into a fridge and sells it to their employees. We offer the food and the whole IT platform to handle the ordering / fulfilment process.

A part of this is, that the canteen staff can define the prices of the articles that the employees have to pay. In order to do that, a set of rules can be defined that are bound to several conditions. A rule means that the list price (the price at which the meal was bought) can be increased / decreased by a fixed amount or a percentage. Conditions are for example the group an employee (called the tableguets) is in, a date range, wether the meal is served hot or cold, an article number range, a weekday (“Soup is cheaper on wednsday”). There can be any number of price rules that are applied in a pipeline. On top of the price there are discounts possible, again based on the table guest group (i. e. empleoyee, intern, guest). Some discounts are only granted once a day, so ordering two identical meals would lead to one serving costs 4€ and the second one costs 6€ because the first one is subsidized while the second is not.

I hope this provides the necessary context for a better understanding.

Thanks for your williingness to help me.

Hi,

Yeah this is the challenge working with stale data with frequently updates. In your scenario there is one more complexity:

Maybe with Option 1 could be some UI timer widget showing to the customer time frame to configure and save pricing rules. After timeout, refresh is required because base prices could changed - for example discount is over.

Hope this help.
Mike

So there is a lot of similarity here with traditional Point of Sale (PoS) behavior (NCR being one of the leaders in this space). Was consideration given to integrating one of those solutions rather than building it in-house?