Skip to content
This repository was archived by the owner on Aug 18, 2021. It is now read-only.

Make internal calls

Gustavo Denis edited this page Oct 31, 2019 · 1 revision
Main > Using Liquid for building your application > Make internal calls

A well designed microservice (as well as any software component) is organized as a collaboration of internal, specialized classes.

Therefore, Liquid provides primitives to facilitate calls among such internal classes yet preserving the high level of abstraction for the business logic.

Take a look at related key concepts of Liquid
Business Logic Separation
Encapsulated Domain Logic
Business Error Handling
Business Logic Separation

#Directly (via factory) One LightService class can call other LightService class seamlessly while sharing the same transactional/contextual environment of the external (API) endpoints provided by the microservice.

[HttpPost("/{departmentId}")]
public IActionResult Update(string departmentId, [FromBody] GoalViewModel goal)
{
    ...

    var response = Factory<GoalService>().Update(departmentId, goal);

    ...
}

public class GoalService: LightService
{
    public async Task<DomainResponse> Update(string departmentId, GoalViewModel goalVM)
    {
        ...

        //Internal call made directly via factory
        goal = FactoryDelegate<AprovalService>().PrepareAprovers(goal);

        ...
    }
}

public class AprovalService: LightService
{
    public GoalModel PrepareAprovers(GoalModel goal)
    {
        ...

        if (goal.Approvers.Count == 0)
            //This business error is added to the context of the calling controller (and sent back to the API client)
            AddBusinessError("NO_APROVERS_FOUND_FOR_THIS_SCOPE");

        ...
    }
}
See how this is done in Liquid Hotel360 sample application.

#Asynchronously (via Message Bus) If an internal call must be processed asynchronously and reliably, that is, must be processed even if the microservice crashes, then the best way to do that is the microservice sending itself a (persisted) message via a Message Bus.

Take this sample code where an event is sent via REST and processed asynchronously as if the REST client had sent the message directly through the Message Bus.

[HttpPost("/{basketId}/renew")]
public IActionResult RenewEvent(string basketId)
{
    ...

    var response = Factory<BasketService>().ReceiveRenewEvent(basketId);

    ...
}

public class BasketService: LightService
{
    public async Task<DomainResponse> ReceiveRenewEvent(string basketId)
    {
        ...

        //Send a message to itself
        await new MessageBus<AzureServiceBus>("SHOP", "basket_renews").SendToQueue(renewMessage);
 
       ...
    }
}

[MessageBus("SHOP")]
public class BasketWorker: LightWorker
{
    [Queue("basket_renews", 1)]
    public void ProcessRenewEvent(RenewMessage msg)
    {             
        ...
        
        //Process the message sent by itself
        var response = Factory<BasketService>().ProcessRenewEvent(msg.basketId);

        ...

    }
}
See how this is done in Liquid Hotel360 sample application.

Clone this wiki locally