120 lines
5.4 KiB
Plaintext
120 lines
5.4 KiB
Plaintext
[[geode-functions]]
|
|
== Function Implementations & Executions
|
|
:geode-name: {apache-geode-name}
|
|
|
|
|
|
This chapter is about using {geode-name} in a Spring context for distributed computing use cases.
|
|
|
|
=== Background
|
|
|
|
Distributed computing, particularly in conjunction with data access and mutation operations, is a very effective
|
|
and efficient use of clustered computing resources. This is similar to {wikipedia-docs}/MapReduce[MapReduce].
|
|
|
|
A naively conceived query returning potentially hundreds of thousands (or even millions) of rows of data in a result set
|
|
to the application that queried and requested the data can be very costly, especially under load. Therefore, it is
|
|
typically more efficient to move the processing and computations on the predicated data set to where the data resides,
|
|
perform the required computations, summarize the results, and then send the reduced data set back to the client.
|
|
|
|
Additionally, when the computations are handled in parallel, across the cluster of computing resources, the operation
|
|
can be performed much more quickly. This typically involves intelligently organizing the data using various partitioning
|
|
(a.k.a. sharding) strategies to uniformly balance the data set across the cluster.
|
|
|
|
{geode-name} addresses this very important application concern in its
|
|
{apache-geode-docs}/developing/function_exec/chapter_overview.html[Function execution] framework.
|
|
|
|
Spring Data for {geode-name} {spring-data-geode-docs-html}/#function-annotations[builds] on this Function execution
|
|
framework by letting developers {spring-data-geode-docs-html}/#function-implementation[implement]
|
|
and {spring-data-geode-docs-html}/#function-execution[execute] {geode-name} functions with a simple POJO-based
|
|
annotation configuration model.
|
|
|
|
TIP: See {spring-data-geode-docs-html}/#_implementation_vs_execution[the section about implementation versus execution]
|
|
for the difference between Function implementation and execution.
|
|
|
|
Taking this a step further, Spring Boot for {geode-name} auto-configures and enables both Function implementation
|
|
and execution out-of-the-box. Therefore, you can immediately begin writing Functions and invoking them without having to
|
|
worry about all the necessary plumbing to begin with. You can rest assured that it works as expected.
|
|
|
|
=== Applying Functions
|
|
|
|
Earlier, when we talked about <<geode-caching-provider,caching>>, we described a `FinancialLoanApplicationService` class
|
|
that could process eligibility when someone (represented by a `Person` object) applied for a financial loan.
|
|
|
|
This can be a very resource intensive and expensive operation, since it might involve collecting credit and employment
|
|
history, gathering information on outstanding loans, and so on. We applied caching in order to not have to recompute
|
|
or redetermine eligibility every time a loan office may want to review the decision with the customer.
|
|
|
|
But, what about the process of computing eligibility in the first place?
|
|
|
|
Currently, the application's `FinancialLoanApplicationService` class seems to be designed to fetch the data and perform
|
|
the eligibility determination in place. However, it might be far better to distribute the processing and even determine
|
|
eligibility for a larger group of people all at once, especially when multiple, related people are involved in a single
|
|
decision, as is typically the case.
|
|
|
|
We can implement an `EligibilityDeterminationFunction` class by using SDG:
|
|
|
|
.Function implementation
|
|
====
|
|
[source,java]
|
|
----
|
|
@Component
|
|
class EligibilityDeterminationFunction {
|
|
|
|
@GemfireFunction(HA = true, hasResult = true, optimizeForWrite=true)
|
|
public EligibilityDecision determineEligibility(FunctionContext functionContext, Person person, Timespan timespan) {
|
|
// ...
|
|
}
|
|
}
|
|
----
|
|
====
|
|
|
|
By using the SDG {spring-data-geode-javadoc}/org/springframework/data/gemfire/function/annotation/GemfireFunction.html[`@GemfireFunction`]
|
|
annotation, we can implement our Function as a POJO method. SDG appropriately handles registering this POJO method
|
|
as a proper Function with {geode-name}.
|
|
|
|
If we now want to call this function from our Spring Boot `ClientCache` application, we can define
|
|
a function execution interface with a method name that matches the function name and that targets the execution
|
|
on the `EligibilityDecisions` Region:
|
|
|
|
.Function execution
|
|
====
|
|
[source,java]
|
|
----
|
|
@OnRegion("EligibilityDecisions")
|
|
interface EligibilityDeterminationExecution {
|
|
|
|
EligibilityDecision determineEligibility(Person person, Timespan timespan);
|
|
|
|
}
|
|
----
|
|
====
|
|
|
|
We can then inject an instance of the `EligibilityDeterminationExecution` interface into our
|
|
`FinancialLoanApplicationService`, as we would any other object or Spring bean:
|
|
|
|
.Function use
|
|
====
|
|
[source,java]
|
|
----
|
|
@Service
|
|
class FinancialLoanApplicationService {
|
|
|
|
private final EligibilityDeterminationExecution execution;
|
|
|
|
public LoanApplicationService(EligibilityDeterminationExecution execution) {
|
|
this.execution = execution;
|
|
}
|
|
|
|
@Cacheable("EligibilityDecisions")
|
|
EligibilityDecision processEligibility(Person person, Timespan timespan) {
|
|
return this.execution.determineEligibility(person, timespan);
|
|
}
|
|
}
|
|
----
|
|
====
|
|
|
|
As with caching, no additional configuration is required to enable and find your application Function implementations
|
|
and executions. You can simply build and run. Spring Boot for {geode-name} handles the rest.
|
|
|
|
TIP: It is common to "implement" and register your application Functions on the server and "execute" them from
|
|
the client.
|