How to implement a Service Function Chain (SFC) in OptaPlanner? - optaplanner

I need to plan the placement of a set of virtualized functionalities over a set of servers using OptaPlanner. My functionalities needs to be executed in a specific pre-defined order, forming a Service Function Chain.
For example Let's say 2 chains are defined
F1->F2
F1->F2->F3
The goal is to place them on a set of servers while minimizing the costs (bandwidth, CPU, Storage,.. costs)
The examples I see in the OptaPlanner user guide for a set of chained planning entities include the Traveler Salesman Problem (TSP) and VRP, however in theses problems the planning entities do not need to be planned in a specific order.

If the sequence order of the functionalities is given you can just give it a bad score if the planned sequence is not correct.
e.g. (pseudorule)
rule "keepServiceFunctionChainSequence"
when
Functionality($chainId:chainId,$end:end, $orderPos:orderPos)
// find another entity in the same chain with a higher position in the order
// that starts earlier
Functionality(chainId==$chainId, orderPos>$orderPos, start.before($end), $orderPos2)
then
scoreHolder.addHardConstraintMatch(kcontext, $orderPos2-$orderPos);
end
if you have a lot of functionalities to plan and you see too many useless moves it may be smart to make an own move that moves one whole chain at once and keeps the sequence.

Related

Moqui - Associate multiple assets to an asset

The assets entity in Moqui has an associated asset field. But, we have a use case where multiple assets need to be associated with an asset.
For example, a tool(manufacturing equipment) may be used only in specified machine(manufacturing equipment). We are exploring the option to create an join entity.
Are we deviating from the best practices of framework?
Added to answer the comment from David E Jones
Business Requirement
There is a custom tool designed to manufacture a component.
This tool is technically compatible with wide range of machines in operation.
The operating cost of machines in question vary in a very wide band. So, the tool should be used only on specific machines to keep the overall cost of manufactured component within a specified band.
So, for a given tool, we intend to assign the allowed machine(s) and use only assigned machines for manufacturing.
As David remarked it is difficult to design for business requirements without detail and context, and there is relatively little to go on here.
I guess the tooling that might be set up on a particular machine could comprise a large range, related to the range of component specifications of orders for a component that might come in.
The main process to be designed here I guess would be to choose the most economically optimum machine to set up with the tooling for a particular order, and that would always vary depending on the other orders ongoing or scheduled, and the machines those orders were assigned to.
Back to your query with the above in mind, if you are defining particular toolings or tools as assets, it might comprise an approach to look at defining the assetTypeEnumId as 'tooling' or similar, and use the classEnumId across the asset types of machines and toolings to stipulate the maximum economic level of machine that the tool should be used with, etc.
Alternatively, or in addition, it might be useful to look at the AssetStandardCost entity and into setting up some enums for assetStandardCostTypeEnumId.
It would seem to me on the surface that the approach of trying to directly associate multiple toolings to multiple machines (with a range of constraints in addition) would quickly lead to exponential possibilities.
All in all, my experience would be that if you look into the existing entities they will typically suggest a variety of approaches, and later on when further requirements arise you may be glad you used what was existing rather than try and do something new.
Business requirements are difficult to design for without detail and context, but it sounds like what you really want to model is not at the Asset level but at the Product level. For asset type products the Product and related entities (like ProductAssoc) are used to define characteristics of physical items, Asset records represent the actual physical items.
One example of this is the maintenance side of things. The maintenance schedule is part of the Product definition (applicable to all assets for that product) and the maintenance history is part of the Asset side of things (applicable only to specific physical items).

How can strategic oscillation be modified so that it only takes into account certain scoring level in it's criteria?

I am using bendable scoring in my project and i have multiple levels.
The criteria behind strategic oscillation has proved itself to be quite useful for the last two levels. So a move that breaks some constraints from level N-1 but improves some constraints from level N is really good.This helps the solver to escape from local optimum and the moves that follow after this one repair the broken constraints from level N-1 and produce a new best score.
While it is really useful between the last two levels it creates a mess when it starts allowing moves that improve a lower level but for example violate level 0.
So my question is can strategic oscillation be configured so it looks only at the last two levels, does OptaPlanner have this built-in? If not how can i make this possible, i guess i would have to implement a custom forager?
I guess you'd want to create a custom FinalistPodium which is used inside the Forager. Just like an Olympic podium, it says who's number 1, who's number 2 and so forth.
See StrategicOscillationByLevelFinalistPodium.java. Here be dragons. This is very internal code, not public API. You might not want to do this.
As for getting your own plugged in, overwrite LocalSearchForagerConfig.buildForager() in your own ForagerConfig and plug it in through the programmatic API (SolverConfig etc).

Handling multiple moves in chained planning variable

I'm trying to implement a variation of the vehicle routing example where instead of customers I have "pick ups" and "drop offs". My hard constraints are:
Each associated pick up/drop off pair must be carried out by the same vehicle (e.g. if vehicle A picks up an item, that item cannot be dropped off by vehicle B).
A pick up must be carried out before it's associated drop off (e.g. you can't drop something off unless you've already picked it up).
A vehicle cannot exceed it's maximum capacity.
Other than these hard constraints my solution works much like the vehicle routing example, where each vehicle has a chain of locations (either a PickUp or a DropOff).
The problem I'm having is that using the default moves it cannot easily move both a PickUp and a DropOff to a different vehicle. For example the following change move results in an invalid state and so will be rejected:
To finish the move properly, I would need to do an additional move so that the drop off belongs to the same chain as the pickup:
It feels like the right thing to do with be to implement some kind of composite move which carries out both moves simultaneously, however I'm not sure of the best way to approach this. Has anyone come across a similar issue to this before?
I've seen users do this before. The optaplanner-examples itself doesn't have a VRPPD example yet (PD stands for Pick Up and Delivery), so you can't just copy paste.
Reuse CompositieMove, see it's static methods to build one.
What usually works: build a custom MoveListFactory (and later refactor it to a MoveIteratorFactory to scale out) and have it produce CompositeMove's of ChainedChangeMove and/or ChainedSwapMove.

Should the rule "one transaction per aggregate" be taken into consideration when modeling the domain?

Taking into consideration the domain events pattern and this post , why do people recomend keeping one aggregate per transaction model ? There are good cases when one aggregate could change the state of another one . Even by removing an aggregate (or altering it's identity) will lead to altering the state of other aggregates that reference it. Some people say that keeping one transaction per aggregates help scalability (keeping one aggregate per server) . But doesn't this type of thinking break the fundamental characteristic about DDD : technology agnostic ?
So based on the statements above and on your experience, is it bad to design aggregates, domain events, that lead to changes in other aggregates and this will lead to having 2 or more aggregates per transaction (ex. : when a new order is placed with 100 items change the customer's state from normal to V.I.P. )?
There are several things at play here and even more trade-offs to be made.
First and foremost, you are right, you should think about the model first. Afterall, the interplay of language, model and domain is what we're doing this all for: coming up with carefully designed abstractions as a solution to a problem.
The tactical patterns - from the DDD book - are a means to an end. In that respect we shouldn't overemphasize them, eventhough they have served us well (and caused major headaches for others). They help us find "units of consistency" in the model, things that change together, a transactional boundary. And therein lies the problem, I'm afraid. When something happens and when the side effects of it happening should be visible are two different things. Yet all too often they are treated as one, and thus cause this uncomfortable feeling, to which we respond by trying to squeeze everything within the boundary, without questioning. Still, we're left with that uncomfortable feeling. There are a lot of things that logically can be treated as a "whole change", whereas physically there are multiple small changes. It takes skill and experience, or even blunt trying to know when that is the case. Not everything can be solved this way mind you.
To scale or not to scale, that is often the question. If you don't need to scale, keep things on one box, be content with a certain backup/restore strategy, you can bend the rules and affect multiple aggregates in one go. But you have to be aware you're doing just that and not take it as a given, because inevitably change is going to come and it might mess with this particular way of handling things. So, fair warning. More subtle is the question as to why you're changing multiple aggregates in one go. People often respond to that with the "your aggregate boundaries are wrong" answer. In reality it means you have more domain and model exploration to do, to uncover the true motivation for those synchronous, multi-aggregate changes. Often a UI or service is the one that has this "unreasonable" expectation. But there might be other reasons and all it might take is a different set of abstractions to solve the same problem. This is a pretty essential aspect of DDD.
The example you gave seems like something I could handle as two separate transactions: an order was placed, and as a reaction to that, because the order was placed with a 100 items, the customer was made a VIP. As MikeSW hinted at in his answer (I started writing mine after he posted his), the question is when, who, how, and why should this customer status change be observed. Basically it's the "next" behavior that dictates the consistency requirements of the previous behavior(s).
An aggregate groups related business objects while an aggregate root (AR) is the 'representative' of that aggregate. Th AR itself is an entity modeling a (bigger, more complex) domain concept. In DDD a model is always relative to a context (the bounded context - BC) i.e that model is valid only in that BC.
This allows you to define a model representative of the specific business context and you don't need to shove everything in one model only. An Order is an AR in one context, while in another is just an id.
Since an AR pretty much encapsulates all the lower concepts and business rules, it acts as a whole i.e as a transaction/unit of work. A repository always works with AR because 1) a repo always deals with business objects and 2) the AR represents the business object for a given context.
When you have a use case involving 2 or more AR the business workflow and the correct modelling of that use case is paramount. In a lot of cases those AR can be modified independently (one doesn't care about other) or an AR changes as a result of other AR behaviour.
In your example, it's pretty trivial: when the customer places an order for 100 items, a domain event is generated and published. Then you have a handler which will check if the order complies with the customer promotions rules and if it does, a command is issued which will have the result of changing the client state to VIP.
Domain events are very powerful and allows you to implement transactions but in an eventual consistent environment. The old db transaction is an implementation detail and it's usually used when persisting one AR (remember AR are treated as a logical unit but persisting one may involve multiple tables hence db transaction).
Eventual consistency is a 'feature' of domain events which fits naturally a rich domain (and the real world actually). For some cases you might need instant consistency however those are particular cases and they are related to UI rather than how Domain works. Of course, it really depends from one domain to another. In your example, the customer won't mind it became a VIP 2 seconds or 2 minutes after the order was placed instead of the same milisecond.

In a DDD architecture, where does a unique ID generation belong to?

Let's say I have a "Project" entity in my domain, that has a to have a unique ID generated (on top of the normal numeric ID) that is 2 letters + 4 digits for every Project. This id has to be unique among all the Projects.
I am having a difficult time placing this functionality, it feels like It should almost only just be placed in the repository when the Project is being saved the first time.
I am sure it doesn't belong to Application services, I am not sure if it is any of the business layers concern to be a domain service, and it feels weird to put it as infrastructure service, but it does need to check if any other Projects exist with a randomly generated [LL]-[DDDD] like code or not.
Even if I place this code around the repository.save it still has to call something from somewhere, so the question is, where should I put a service that gives me a free random Id like that?
Ids which are part of the domain should be generated by the domain.
If the domain do not define any ids you should not expose them in the domain either (strictly speaking, but it's probably easier to include them either way).
Your question mentions a 'normal ID'. I'm assuming that this is your DB's primary key and that the ID you want to generate here is for humans (although why humans would use a 2-letter+4-digit identifier is beyond me, but I've seen worse). In this case, the generation of the key is a business function and ensuring it is unique is a business rule. Both of these things are properly the responsibility of the domain objects. Given your object name, Project, and the language you use in your question, I'd suggest that maybe the Projects object should provide this service. The reason for this is that only the Projects object would have a view over all project objects you've created to check for uniqueness.
Of course, you could have an algorithm to generate this field that ensures uniqueness without having to check all projects (a good idea, btw). In which case you'd probably allow a project to generate its own ID at an appropriate time in its lifecycle (probably when it is created).
The "free random id" or ID generation is part of the infrastructure rather than the business domain so I would add that logic to a persistence layer and call that from within my repositories. e.g ProjectRepository. Assume that the Project entity would have an 'id' field in any case. You can enforce validation in the Project entity so that the id format is 2 letters and 4 digits but only do that if Project ids are different to other entity ids in your application
The first question you need to ask yourself is - why is this constraint on Project ID necessary? Does the user need to know about Project IDs?
If it's informative to the user or if you are implying a form of catalogue of projects, this is a business rule that belongs to the domain. It might require updating your domain model, and therefore refactoring your code in accordance with the new model. Actual id generation will be done by the infrastructure layer, as a new Project is added to the system, but it will use a STRATEGY that expresses the business rule and is defined in the domain layer.
If it's merely a technological requirement, but has no semantic meaning in the domain, either remove the constraint, or place it in the infrastructure layer.
In any case, the infrastructure layer can provide an infrastructure service for id generation of new project entities, which the class responsible for Project entity creation may use (for example, a Project Factory). Project Factories belong to the domain layer, even though they may use an infrastructure service.
Unique identifier generation would normally be an application concern -- these identifiers are analogous to random numbers, or time. They are an input to the deterministic parts of the system.
If you don't consider time an input value, think about it until you do - it is an important concept -- John Carmack, 1998
Ensuring that an identifier (however it was generated) satisfies some uniqueness constraint would be a domain concern, and falls into the general category of set validation.
Note Greg Young's observation:
What is the business impact of having a failure?
If the cost of a failure is small, if failures are easily detected and remedied, then it may be most practical to lean into a "best effort" design. UUID's aren't unique (finite number of bits, we're going to use them all up eventually), but at the scales we are working at the probability of collision is really small. So often, we can just live with it.
But when the impact of a failure is high....
Ensuring that some policy applies to the entire set requires being able to lock the entire set against concurrent modification.
In the easy case - each unique identifier has its own set. One way of framing how repositories work is that they give you the set of all aggregates that match the provided key, and your domain logic is responsibly for ensuring that set has at most one element in it.
In harder cases, the set itself becomes an aggregate, with its own lock, and the domain logic ensures that the each change maintains the invariant of the set. Often, this requires doing a deep analysis of the model to understand which information is actually under the authority of the set, rather than under the authority of other aggregates.