api.global versus api.local
Introduction
Before using api.local or api.global, check if you can create an element for that purpose.
The api.global
and api.local
are hashmaps that are populated in the memory of each server node. Variable api.local
is initialized to an empty Map before calculation of every item while api.global
is (if the api.retainGlobal
variable is set to true
) initialized to an empty Map before the calculation of the first item. Old projects: If the api.retainGlobal
variable is not set, then api.global
behaves the same way as api.local
and therefore it is deprecated practice and api.local
should be used.
Calculation Flows Specifics
api.global
persists between Calculation Flow (CF) logic executions and is stored within the globalFormulaState
property of the CF object. If you do not want to share the global cache between logic executions, use the api.local instead, or add api.retainGlobal = false
at the beginning of CF logics.
Note: api.global
data in Calculation Flows (in the globalFormulaState
property) is stored as a String. Use the jsonDecode(String)
to convert it back to the Groovy object (a Map).
Example:
def cf = api.find( "CF", Filter.equal("uniqueName", "ScheduleCalculations"), Filter.equal("draft", "false") ).first() def config = api.jsonDecode(cf.configuration).entries.get(0)?.globalFormulaState return config.lastCalculationDate
Usage examples are documented at Caching Strategies in Configuration.
If any of the variables api.global
or api.local
holds a lot of data, these variables should not be returned as an element result since the data gets usually persisted for each calculated record.
api.global
By setting api.retainGlobal = true
you can instruct the formula engine to keep the hash map in between logic runs. It works between line items and, in case of Quotes, Agreements/Promotions, Rebate Agreements and Claims, between the header and the line items (but only in the pre-phase, not in the post-phase). The values are also carried forward between two list calculation passes (i.e., form initial run to dirty item run; ONLY in non-distributed mode.).
Remember that for distributed calculations api.global
is populated on each server node and each thread independently. So if you store there the results of some data queries, those queries will get executed on every node (and not once as one may think).
You should always:
- Cache some reasonable amount of data to be used for multiple items. Storing big data causes bad performance when recalculating a single item.
Since Vesper 6.0, the maximum string size of JSON serialized api.global content that is passed on to dirty passes is limited to 2MB. This is configurable in pricefx-config.xml (maxGlobalsSize). - Define a constant to be used in many elements of the logic.
When api.global
should not be used:
- For passing values to functions. These functions would later become difficult to use. Consider passing values to a function as regular function parameters.
For old projects created before Manhattan 4.0 release: make sure api.retainGlobal is set to true by default. Since if not set, the variable to true
in the first element of the logic; otherwise the value of api.global
will get lost. This was a common error that caused performance issues when values which should be cached for all items were calculated for every item.
See also:
api.local
Before using api.local
, consider creating a new element (possibly with the Display option = None) and store the value there. Performance-wise it is identical since both api.getElement
and api.local
are represented by HashMaps. You will also debug the value more easily: as elements result(s) of a logic test. You also will not need to call api.trace
to debug the value. Last but not least, it will also help you avoid potential naming clash of the api.local
key.
So api.local
should be used only in the following scenarios:
- If you set
api.local
in some element and you then need to change the value in some other element (try to avoid it though). - You need to store multiple calculated values and you do not want to return Maps as an element result. For example, you calculate a price at certain place and want to set a price reason text at once. In that case, the element typically returns the price and sets the price reason as e.g.,
api.local.reason
.
When api.local
should not be used:
- For passing values to functions. These functions would later become difficult to use. Consider passing values to a function as function parameters.
Found an issue in documentation? Write to us.
Â