33
Views
10
Comments
Call a Server action, after client evaluation, at Start, in Reactive. Best way?

Hi!

I have a theoretical question about how is the correct way to proceed, according to the good practices of Outsystems, but also in the most optimal way.

I have a Client Side var called "NeedToRefresh". A Webblock should evaluate this var when it loads, and if "NeedToRefresh = True", then it should call to a Server Action. Which is the right way? I have two options:

  1. OnInitialize, evaluate the Client side var, and call to the Server Action.
  2. Create a FetchData, fetch it "At Start", evaluate the client side var, and decide if need run the Server Action

None convinces me at all, 

  • option 1 execute (if client side var is true) a Server action in OnInitialize, and OS best practice says you shouldn't. But if Client side var = False, don't runs server action, and is more optimal.
  • option 2 comply with OS best practices "don't runs server action OnInitialize", but calls to server side (Fetch data runs on server side) only to evaluate a client side var, and decide if runs Server Actions. That server call (fetch data) is unnecessary if var = False.


What do you think should be the correct way?


I have an Option 3, that is run a setTimeout OnReady with 0ms of time, in which I evaluate NeedToRefresh var, and if it's "true" call to a ScreenAction that runs server action... but it's a little tricky.


Regards,
Carlos.

Rank: #70

Hi Carlos,


Is the NeedToRefresh variable an input parameter?

Because if that is the case, you can control with an If on the parent screen / block whether to render the block (and do the query) or not (and not do the query).


If your case is the NeedToRefresh starts at False when you first render the block and it eventually comes True, you can set the query to run only on Demand, like this, so it doesn't run when the block is first rendered:



And then you add the OnParamatersChanged to refresh your query according to the NeedsToRefresh is True or False.


Hope it helps.


Cheers,

João

Rank: #668

Hi João ,

Thanks a lot for your answer, what you mention it's a good (an ingenious) solution, maybe solve my scenario making some changes in our code (but maybe It's a little too much elaborate, plays with OnParametersChange and control de rendering in parent).

So, as the question is theoretical to know how to proceed based on good practices, we are going to assume that - is a Client Side Variable

- I need to call to a server action (not aggregate)

- I need evaluate inside WB if ShouldRefresh = true or not (to call or not to the server action). This way the controll is encapsulated and I don't need to control in all the pages that use this WB.


How should we procced? In OnInitialize or FetchingData At Start? Or maybe Joao answer is only and right way?


Regards,

Rank: #70

Hi Carlos,


I think it's great to see developers paying attention to NFR's such as performance, so kudos for that.

When I have had to deal with scenarios such as the one you mentioned, I used the solution I mentioned above (with Data Action instead of the Aggregate, but the principle is the same).



In this way, no extra calls are made and it is easy to read the code and maintain it. It is actually a common pattern I think.


Cheers,

João 

Rank: #668


Thanks again for answer. 

I understand that this patterns works for paramters "change", but, what if is the first time you load the webblock and parameters don't change? Maybe I have not explain me right. I'm try to exaplain it better.

I need to evaluate "Value" input var to perform or not calling to CalcValue server action. Not when parameters change, in the first load of Webblock (because loads with the page, and value is a pre-calculated value that is stored in client side vars, so that when I navigate between pages I don't need to recalc it again, only assing it to the webblock, that is in header in all pages).

if I make as in the screenshot I performing a server call in OnInitialize (wrong), but only sometimes, when value = 5...

If I perform this evaluation in a DataAction, data action is in server side, so I'm calling unnecesary to server side to evaluate a value that I could evaluete in client side

"Value" is used to show the number in expression.

I don't know how apply your first answer to this case, input parameter don't change in the first load. Even if I encapsulate this webblock into another to try to control de input parameters, in the first load of webblock (this case) input paramters don't change.

I don't know if I have explain me propertly.


Thansk again.

Rank: #70

Hi Carlos,


If that is the case, why don't you control from the parent if the webblock should be rendered (and the query runs) or not rendered (and the query does not run)?

Taking your example of value = 5, I would enclose the web block in an If with the condition Value = 5:


In this case, you can control if value under 5 my block runs (and its data action runs as weel) or not.

Hope it helps.


Cheers,

João

Rank: #668

Hi Joao,

In my particular case, WB should be allways render (it's a notification counter in header page); with your Idea, I could make a copy of webblock, in one make the server action call, in another not, and evaluate with an "if" which wb I should render.

But the main question in the post is thoerical: How should we procced, according Outsystems best practices in this situations, in whitch I should evaluate a client variable when webbblock loads first time to decide if call to server action or not... Both ways (OnInitialize and DataAction) are not 100% optimal and correct... This is really the main doubt (regardless of my particular case)


Best regards,
Carlos.

Rank: #70

Hi Carlos,


You already mention the good practices and rightfully so, now it's about finding a way to implement your requirements trying to respect them as best as you can.


In your case, I would do a block #1 which receives a value and then would have an if showing the block #1.1 which does the query or the block #1.2 that does not.

In this way, you respect the good practices, don't run queries unnecessarily and from a reusability standpoint it is simple as you just have to use block #1.


Cheers,

João


Hi! 

Your question is tricky Carlos!! 

I think that the most performant way will depend on the case itself: 

If the need to refresh is frequent, the data action with fetch option "At Start" is probably the best way as it takes advantage of the parallel processing.

If the need to refresh is occasional, then if the server action is called from  "OnInitialize" action it will not greatly degrade the performance in a normal use. In this case the server action should be built in a way it only do what is absolutely necessary, avoiding doing things like updates to the DB or complex calculations. 

 Best Regards

Graça


Rank: #668

Hi!

Yes @Maria, my question is tricky, but It is a common case (you need to evaluate something before server call at wb load), which does not have a direct way to solve it (solve it right), and you have to do some trick. I think should be an event "before" call DataAction call, and there you could change or cancel dataAction call. As there is no such thing, you have to break some of the best practices rules (depending on the case) or do a trick, always with common sense.

@Joao, mixing you idea, I think the best way to solve it could be this:

1. Extract calc data to another wb, that always calc data at start in dataaction, and assign result to Client.Calculate data

2. Nest CalcBlock into original webblock, evaluating if should be loaded with an if

This way, you only have one "showing wb", and calc data is only re-calculated if need it, and if so, the reasignation of Client.CalculatedData change automatically the "block" input value, so it's autorefresh it. What do you think?


Anyway, all of this is a little tricky, should be an easy way to do this right. Or evaluate the impact of making OnInitialize or DataAction, as @Maria says, even if you are breaking some rule.


Carlos.

Rank: #70

Hi Carlos,


Sometimes indeed you need to choose which one good practice to "break" according to the one that has less impact for you, I agree.

In this case, the solution you propose it sounds good! It is very similar to the one I had proposed and I think it would allow you to optimize performance and reusability.


Cheers,

João