The following migration steps assume that you have an existing Heroku account. If not, see Get started on Heroku today. The migration also requires the Heroku CLI.
If you’re new to Heroku or need a refresher, see How Heroku Works.
Migrating to the Reference Functions Framework includes these one-time setup steps, which are detailed in the guide:
- Copying and deploying Reference Functions Framework metadata and source to your SFDX project and the language-specific proxy and build artifacts to your functions.
- Creating and configuring Heroku apps for each function.
- Updating Salesforce Function Apex API references to Reference Functions Framework Apex APIs.
- Creating and configuring the authentication and authorization connected apps and their associated permission sets.
- Creating
FunctionReference_mdt
custom metadata type records for each function. - Creating a remote site setting for each function.
After migrating to the Reference Functions Framework, test the function and integration development as usual.
This repository also includes examples of Reference Functions Framework Java and Typescript implementations.
Example Apex invocations:
- Apex class
InvokeJavaFunction
invokes aJava
function. - Apex class
InvokeTypescriptFunction
invokes aTypescript
function.
Example metadata and source includes:
- Apex Class in
force-app/main/default/classes/
- Custom Metadata in
force-app/main/default/customMetadata/
- Visualforce Pages in
force-app/main/default/pages/
- Permission Sets in
force-app/main/default/permissionsets/
- Remote Site Settings in
force-app/main/default/remoteSiteSettings/
Note
Example source and metadata is intended to illustrate Reference Functions Framework implementations for Java and Typescript functions and may be excluded from copying to your SFDX project.
Before migrating your Salesforce Functions to the Reference Functions Framework, review example metadata and source.
Metadata and source include:
- Apex Classes in
force-app/main/default/classes/functions/
- Apex Triggers in
force-app/main/default/triggers/functions/
- Custom Objects in
force-app/main/default/objects/
See language specific-instructions:
See language-specific instructions:
Update functions.Function
Salesforce Function API references by removing the functions
. Apex namespace. For example, functions.Function.get()
becomes Function.get()
.
See Example of Apex Changes.
The Reference Functions Framework’s Function.get()
API must resolve to a FunctionReference_mdt
record. The reference given to get()
is the Object Name
of the FunctionReference_mdt
record.
The Function.get()
API supports existing Salesforce Function references with the .
delimiter: Function.get(<project>.<function>)
. The framework also supports the _
delimiter: <project>_<function>
.
The framework doesn’t require a project
qualifier: Function.get(<function>)
.
The Function.get(<namespace>, <function>)
API supports a namespace. If a namespace isn’t provided,it defaults to the Salesforce org’s namespace.
For cross-namespace support, that is, invoking a function in another namespace, you must set the Protected Component
field to false
on the function’s FunctionReference_mdt
record.
public void invoke() {
// Note: functions.Function is now Function
Function javaFunction = Function.get('sfhxhello.javafunction');
// Sync
// Note: functions.FunctionInvocation is now FunctionInvocation
FunctionInvocation invocation = javaFunction.invoke(JSON.serialize(params));
// Async
invocation = javaFunction.invoke(JSON.serialize(params), new MyCallback());
}
// Note: functions.FunctionCallback is now FunctionCallback
public class MyCallback implements FunctionCallback {
// Note: functions.FunctionInvocation is now FunctionInvocation
public void handleResponse(FunctionInvocation invocation) {
System.debug(invocation.getStatus().name() + ': ' + invocation.getResponse());
}
}
You must create a separate Heroku app for each function and configure its deployment. It’s recommended to deploy apps in Private Spaces.
For enterprise-grade security, use Private Spaces as a secure container for your Heroku apps. A Private Space, part of Heroku Enterprise, is a network-isolated group of apps and data services with a dedicated runtime environment. You can provision it in a geographic region you specify. With Private Spaces, you can build modern apps with the powerful Heroku developer experience and get enterprise-grade secure network topologies. Private Spaces enables your Heroku applications to securely connect to on-premises systems on your corporate network and other cloud services, including Salesforce.
See language-specific instructions:
Create an authorization connected app that the proxy uses to create access tokens for associated functions. A function uses the token for Salesforce org access.
This connected app and session-based permission set created in the next step determines what a function is authorized to do, for example, invoke Salesforce APIs.
You can create a connected app for each function or use a single connected app for all functions. To ensure isolation, configure a connected app for each lifecycle stage, production, sandbox, and scratch orgs.
This document refers to this connected app as the authorization or authZ connected app.
Complete the following steps in Setup of your Salesforce org:
- Create an RSA self-signed certificate used to generate an access token for a function. You upload the certificate to the connected app in the next step.
- To validate function callers, create an internal JWT-based connected app for the proxy:
- On the App Manager page, click New Connected App.
- Fill in the Connected App required fields. For a function-specific connected app, name it to associate to its function, for example, “Java Function Authorization”. For a connected app used for multiple functions, name it “Functions Authorization”.
- Select Enable OAuth Settings and enter an arbitrary callback URL such as http://localhost:1717/OauthRedirect.
- Select Use Digital Signatures and upload the certificate file (.crt) created in Step 1.
- Add the following scopes:
- Manage user data via APIs: allows the proxy to access Salesforce’s OAuth APIs
- Perform requests at any time: allows the proxy to create an authorization token for function’s Salesforce org access.
- On the Manage or Edit Policies page, set Permitted Users to Admin-approved users are pre-authorized. This setting enables assigning a permission set to who can access this connected app.
- On the Manage Consumer Details page, reveal and copy the **Consumer Key **value, also referred to as Issuer.
Note
In a later step, you need the Consumer Key and certificate key file to use as config vars,CONSUMER_KEY
andENCODED_PRIVATE_KEY
, for each of your Heroku apps.
For more information on creating a JWT connected app, see OAuth 2.0 JWT Bearer Flow for Server-to-Server Integration.
Keep Connected Apps secure by periodically rotating your consumer key. For more information, see Rotate the Consumer Key and Consumer Secret of a Connected App.
After the proxy creates a function token, the proxy activates assigned session-based permission sets. These permission sets authorize specific capabilities, such as access to Standard and Custom objects.
You can create a session-based permission set for each function, or you can create a single session-based permission set for all functions. A permission set group, referencing multiple session-based permission sets, is also supported.
A session-based permission set or a permission set group is associated to functions via a function’s FunctionReference.PermissionSetOrGroup__c
custom metadata field.
This document refers to this permission set as the authorization or authZ permission set.
To grant Edit access to the AsyncFunctionInvocationRequest__c
custom object, you must deploy it before creating the authorization, session-based permission set.
The Reference Functions Framework uses AsyncFunctionInvocationRequest__c
for asynchronous function requests.
$ sfdx force:source:deploy -p force-app/main/default/objects/AsyncFunctionInvocationRequest__c/
...
=== Deployed Source
FULL NAME TYPE PROJECT PATH
───────────────────────────────────────────────── ──────────── ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
AsyncFunctionInvocationRequest__c.CallbackType__c CustomField force-app/main/default/objects/AsyncFunctionInvocationRequest__c/fields/CallbackType__c.field-meta.xml
AsyncFunctionInvocationRequest__c.Callback__c CustomField force-app/main/default/objects/AsyncFunctionInvocationRequest__c/fields/Callback__c.field-meta.xml
AsyncFunctionInvocationRequest__c.Context__c CustomField force-app/main/default/objects/AsyncFunctionInvocationRequest__c/fields/Context__c.field-meta.xml
AsyncFunctionInvocationRequest__c.ExtraInfo__c CustomField force-app/main/default/objects/AsyncFunctionInvocationRequest__c/fields/ExtraInfo__c.field-meta.xml
AsyncFunctionInvocationRequest__c.RequestId__c CustomField force-app/main/default/objects/AsyncFunctionInvocationRequest__c/fields/RequestId__c.field-meta.xml
AsyncFunctionInvocationRequest__c.Request__c CustomField force-app/main/default/objects/AsyncFunctionInvocationRequest__c/fields/Request__c.field-meta.xml
AsyncFunctionInvocationRequest__c.Response__c CustomField force-app/main/default/objects/AsyncFunctionInvocationRequest__c/fields/Response__c.field-meta.xml
AsyncFunctionInvocationRequest__c.StatusCode__c CustomField force-app/main/default/objects/AsyncFunctionInvocationRequest__c/fields/StatusCode__c.field-meta.xml
AsyncFunctionInvocationRequest__c.Status__c CustomField force-app/main/default/objects/AsyncFunctionInvocationRequest__c/fields/Status__c.field-meta.xml
AsyncFunctionInvocationRequest__c CustomObject force-app/main/default/objects/AsyncFunctionInvocationRequest__c/AsyncFunctionInvocationRequest__c.object-meta.xml
Complete the following steps in Setup of your Salesforce org:
- On the Permission Sets page, click New to create a permission set.
- Provide a name and enable Session Activation Required. For a function-specific permission set, name it to associate to its function, for example, “Java Function Authorization”.
- Under Assigned Connected Apps, assign the authorization connected app created earlier.
- Under Object Settings, assign Edit access to
Async Function Invocation Requests
, which is required for asynchronous function invocation responses.- Ensure Edit access to the fields:
ExtraInfo__c
,Response__c
,Status__c
, andStatusCode__c
.
- Ensure Edit access to the fields:
- Enable other app and system settings that the function needs. The example
Java
andTypescript
functions require Read access to the Account object. - Under Manage Assignments, assign function-invoking users to the permission set.
For Apex Batch, Scheduled Flows, and other Automated Process User invocations, ensure the Automated Process user is assigned to the authentication connected app.
To set and view field-level security via Permission Sets, see Set Field-Level Security for a Field on Permission Sets Instead of Profiles During Field Creation (Beta).
The Reference Functions Framework uses this connected app to generate a token included in each function payload. The proxy uses the token to authenticate function requests. Function requests must originate from the authenticated Salesforce org. Function-invoking users must also have authorized access to this connected app via a permission set and assignment.
This document refers to this connected app as the authentication or authN connected app.
Complete the following steps in Setup of your Salesforce org:
- On the Certificate and Key Management page, create a self-signed certificate used to generate an access token to validate function callers. After creating it, download the certificate.
You must create a self-signed certificate via Certificate and Key Management as it’s referenced in the Reference Functions Framework API’s
FunctionsMetadataAuthProvider
class. - For the proxy to validate function callers, create an internal JWT-based connected app:
- On the App Manager page, click New Connected App.
- Fill in the connected app required fields. For example, the name as “Functions Authentication”
- Select Use Digital Signatures and upload the certificate file (.crt) created in Step 1.
- Add the following scopes:
- Manage user data via APIs: activates session-based permission sets.
- Access custom permissions: activates session-based permission sets.
- Access the identity URL service: allows the proxy to verify function request callers
- Perform requests at any time: allows the proxy to create an authorization token for function’s Salesforce org access.
- On the Manage or Edit Policies page, set Permitted Users to Admin-approved users are pre-authorized.
- On the Manage Consumer Details page, reveal and copy the Consumer Key value, also referred to as Issuer.
The Certificate name and Consumer Key are stored in each function’s associated FunctionReference__mdt
custom metadata.
See Create a Connected App -> Enable OAuth Settings for API Integration.
Keep Connected Apps secure by periodically rotating your consumer key. For more information, see Rotate the Consumer Key and Consumer Secret of a Connected App.
You need a permission set to grant function-invoking users access to the authentication connected app created earlier.
This document refers to this permission set as the authentication or authN permission set.
Complete the following steps in Setup of your Salesforce org:
- On the Permission Sets page, click New to create a permission set.
- Provide a name, for example, “Functions Authentication”. Do not check Session Activation Required for this permission set.
- Under Assigned Connected Apps, assign the authentication connected app and all authorization connected apps created earlier.
- Under Manage Assignments, assign function-invoking users to the permission set.
For Apex Batch, Scheduled Flows, and other Automated Process User invocations, ensure the Automated Process user is assigned to the authentication connected app.
You need the authorization connected app’s consumer key and certificate key file for this step.
See language-specific instructions:
See language-specific instructions:
When switching between functions, update the remote
to the target function:
$ heroku git:remote -a javafunction
set git remote heroku to https://git.heroku.com/javafunction.git
$ git push heroku main
...
See language-specific instructions:
The FunctionReference__mdt
custom metadata types represent the functions in your Salesforce org. The Function.get('<myproject>.<function>')
API references a FunctionReference__mdt
custom metadata record.
The FunctionReference__mdt
custom metadata type enables each function to have custom platform behavior. Custom behavior can include associating session-based permission sets that are activated on the function’s access token to authorize specific Org access.
FunctionReference__mdt
custom metadata fields include:
ConsumerKey__c
: Consumer key of the authentication connected app used by theFunctionsMetadataAuthProvider
Apex class.Certificate__c
: Name of the certificate associated with the authentication connected app used by theFunctionsMetadataAuthProvider
Apex class.Endpoint__c
: URL of the function.PermissionSetOrGroup__c
: (Optional) the session-based permission set API name activated on function’s token grant function access. If a permission set isn’t associated, you must assign function-invoking users access toAsyncFunctionInvocationRequest__c
via another permission set.
For cross-namespace support, that is, invoking a function in another namespace, you must set the Protected Component
field to false
on the function’s FunctionReference_mdt
record. To prevent cross-namespace invocations, set Protected Component
to true
.
For each function, create a FunctionReference__mdt
custom metadata record:
- Capture your function’s URL.
# Once an app is deployed, you can get the URL via the CLI. If not, you can still set
# metadata if you know the name of your app, in this example it was `javafunction`.
# Set function URL in FunctionReference Custom Metadata
$ heroku apps:info -s | grep web_url | cut -d= -f2
https://javafunction.herokuapp.com/
- Create a
FunctionReference__mdt
metadata file.
In the example, sffxhello
is the project name in FunctionReference.sfhxhello_javafunction.md-meta.xml
. Change it to your own project in the sfdx-project.json#name
value.
The Reference Functions Framework doesn’t require a project name as a function qualifier. If a Salesforce org’s source and metadata span multiple repositories, use a project name to ensure that FunctionReference__mdt
records are unique.
$ cat force-app/main/default/customMetadata/FunctionReference.sfhxhello_javafunction.md-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<CustomMetadata xmlns="http://soap.sforce.com/2006/04/metadata" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<label>Java Function</label>
<protected>false</protected>
<values>
<field>Endpoint__c</field>
<value xsi:type="xsd:string">https://javafunction.herokuapp.com</value>
</values>
<values>
<field>PermissionSetOrGroup__c</field>
<value xsi:type="xsd:string">JavaFunction</value>
</values>
<values>
<field>ConsumerKey__c</field>
<value xsi:type="xsd:string">3MVG9i...</value>
</values>
<values>
<field>Certificate__c</field>
<value xsi:type="xsd:string">Functions_Internal_Cert</value>
</values>
</CustomMetadata>
A remote site setting permits Apex callouts to the registered URL. For each function, create a remote site setting in Setup or with the Metadata API, shown in the example.
Additionally, to create an authentication token, create a remote site setting for the Salesforce org’s domain.
# Used to generate an authentication token in Apex. The token is sent with the function payload and used by the
# proxy to authenticate the request.
$ cat force-app/main/default/remoteSiteSettings/ThisOrg.remoteSite-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<RemoteSiteSetting xmlns="http://soap.sforce.com/2006/04/metadata">
<disableProtocolSecurity>false</disableProtocolSecurity>
<isActive>true</isActive>
<url>https://mycompany.my.salesforce.com</url>
</RemoteSiteSetting>
# Access to function
$ cat force-app/main/default/remoteSiteSettings/JavaFunction.remoteSite-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<RemoteSiteSetting xmlns="http://soap.sforce.com/2006/04/metadata">
<disableProtocolSecurity>false</disableProtocolSecurity>
<isActive>true</isActive>
<url>https://javafunction.herokuapp.com</url>
</RemoteSiteSetting>
$ cat force-app/main/default/remoteSiteSettings/TypescriptFunction.remoteSite-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<RemoteSiteSetting xmlns="http://soap.sforce.com/2006/04/metadata">
<disableProtocolSecurity>false</disableProtocolSecurity>
<isActive>true</isActive>
<url>https://typescriptfunction.herokuapp.com</url>
</RemoteSiteSetting>
Deploy the following to your Salesforce org:
- Reference Functions Framework APIs: Apex Classes, Apex Trigger, Custom Objects
- Integrations: Apex,
FunctionReference__mdt
Custom Metadata, and so on.
Before deploying, ensure that force-app/main/default/customMetadata/FunctionReference.sfhxhello_javafunction.md-meta.xml
and force-app/main/default/customMetadata/FunctionReference.sfhxhello_typescriptfunction.md-meta.xml
fields are set to your function endpoint and Salesforce org settings, like the connected app consumer key and certificate.
$ sfdx force:source:deploy -p force-app/
Deploying v57.0 metadata to [email protected] using the v57.0 SOAP API
Deploy ID: 0AfB000000pmfwpKAA
DEPLOY PROGRESS | ████████████████████████████████████████ | 48/48 Components
=== Deployed Source
FULL NAME TYPE PROJECT PATH
───────────────────────────────────────────────── ───────────────── ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Function ApexClass force-app/main/default/classes/functions/Function.cls
Function ApexClass force-app/main/default/classes/functions/Function.cls-meta.xml
FunctionCallback ApexClass force-app/main/default/classes/functions/FunctionCallback.cls
FunctionCallback ApexClass force-app/main/default/classes/functions/FunctionCallback.cls-meta.xml
FunctionCallbackQueueable ApexClass force-app/main/default/classes/functions/FunctionCallbackQueueable.cls
FunctionCallbackQueueable ApexClass force-app/main/default/classes/functions/FunctionCallbackQueueable.cls-meta.xml
...
AsyncResponseHandlerTrigger ApexTrigger force-app/main/default/triggers/functions/AsyncResponseHandlerTrigger.trigger
AsyncResponseHandlerTrigger ApexTrigger force-app/main/default/triggers/functions/AsyncResponseHandlerTrigger.trigger-meta.xml
..
AsyncFunctionInvocationRequest__c CustomObject force-app/main/default/objects/AsyncFunctionInvocationRequest__c/AsyncFunctionInvocationRequest__c.object-meta.xml
FunctionReference__mdt CustomObject force-app/main/default/objects/FunctionReference__mdt/FunctionReference__mdt.object-meta.xml
...
Deploy Succeeded.
Here’s example Apex code that invokes a function using Reference Function Framework APIs.
// Invoke sync function
public static void invokeSync() {
// Get reference to function
Function javafunction = Function.get('mynamespace', 'sfhxhello_javafunction');
Map<String,String> params = new Map<String,String>();
// Invoke sync...
FunctionInvocation invocation = javafunction.invoke(JSON.serialize(params));
}
// Invoke async function
public static void invokeAsync() {
// Get reference to function
Function javafunction = Function.get(''mynamespace'', 'sfhxhello_javafunction');
Map<String,String> params = new Map<String,String>();
// Aync invoke
FunctionInvocation invocation = javaFunction.invoke(JSON.serialize(params), new Callback('sfhxhello_javafunction'));
}
// Callback
public class Callback implements FunctionCallback {
String functionName;
Callback(String functionName) {
this.functionName = functionName;
}
public void handleResponse(FunctionInvocation invocation) {
System.debug(invocation.getStatus().name() + ': ' + invocation.getResponse());
}
}
See language-specific examples:
See InvokeJavaFunction and InvokeTypescriptFunction.
For convenience, you can invoke InvokeJavaFunction
and InvokeTypescriptFunction
via Visualforce pages. See pages/ directory. You can configure Visualforce pages as List View buttons.
See language-specific instructions:
The Reference Functions Framework provides testing utilities to mock authentication token generation, FunctionReference_mdt
lookup, and function callout responses.
force-app/main/default/classes/functions/tests/
├── FunctionInvocationCalloutMocks.cls
├── FunctionsTestAuthProviderMocks.cls
└── FunctionsTestDataFactory.cls
InvokeJavaFunctionTest.cls is an example of how to test function invocations. For example, the following snippet demonstrates using FunctionInvocationCalloutMocks
to mock the function response. It uses FunctionsTestAuthProviderMocks.FakeAuthProvider
to mock the authentication token generation.
@isTest
static void testInvoke_sync() {
String responseBody='{}';
Test.setMock(HttpCalloutMock.class,FunctionInvocationCalloutMocks.respondSuccess(responseBody));
Test.startTest();
FunctionInvocation invocation=InvokeJavaFunction.invokeSyncWork(new FunctionsTestAuthProviderMocks.FakeAuthProvider());
Test.stopTest();
// Asserts
...
}
For more information, see Testing HTTP Callouts.
Here’s an example of an Apex test run that displays detailed code coverage results in human-readable form.
$ sfdx apex run test --code-coverage --result-format human --detailed-coverage
=== Test Summary
NAME VALUE
─────────────────── ────────────────────────
Outcome Passed
Tests Ran 10
Pass Rate 100%
Fail Rate 0%
Skip Rate 0%
Test Run Id 707B0000024qbxR
Test Execution Time 4497 ms
Org Id 00DB0000000gJmXMAU
Username [email protected]
Org Wide Coverage 73%
=== Apex Code Coverage for Test Run 707B0000024qbxR
TEST NAME CLASS BEING TESTED OUTCOME PERCENT MESSAGE RUNTIME (MS)
─────────────────────────────────────────────────────── ───────────────────────────────────── ─────── ─────── ─────── ────────────
<log output deleted>
InvokeJavaFunctionTest.testInvoke_sync Function Pass 60% 143
InvokeJavaFunctionTest.testInvoke_sync FunctionInvocationRequest Pass 79% 143
=== Apex Code Coverage by Class
CLASSES PERCENT UNCOVERED LINES
───────────────────────────────────── ─────── ─────────────────────
FunctionReferenceMetadataProviderImpl 100%
FunctionInvocationImpl 86% 40,42,55,56,90...
FunctionInvocationErrorImpl 71% 14,15
InvokeJavaFunction 69% 8,10,12,14,15...
FunctionCallbackQueueable 100%
Function 93% 35,37,56,73,74...
FunctionErrorType 0%
FunctionInvocationStatus 0%
FunctionInvocationRequest 80% 45,113,116,119,122...
AsyncResponseHandlerTrigger 89% 11,32
Heroku offers a variety of dyno types to support apps of all sizes, from small-scale projects to high-traffic production services. For more information, see Dyno Types.
If a function encounters Memory quota exceeded
, resize the function’s dyno type to a larger dyno size with increased memory and CPU characteristics.
- 2023-04-06T19:13:35.124858+00:00 heroku[web.1]: Process running mem=591M(115.5%)
- 2023-04-06T19:13:35.126587+00:00 heroku[web.1]: Error R14 (Memory quota exceeded)
You can scale Heroku apps to run on multiple dynos simultaneously, except on Eco or Basic dynos. You can scale your app’s dyno formation up and down manually from the Heroku Dashboard or CLI.
You can also configure Heroku Autoscaling for Performance-tier dynos, and for dynos running in Private Spaces. Threshold autoscaling adds or removes web dynos from your app automatically based on current request latency.
For more information, see Scaling Your Dyno Formation
Dynos have default scaling characteristics per dyno type. For more information, see Default Scaling Limits.
Heroku Add-ons provide several add-on options to schedule, scale, and manage your dyno usage to your app's needs.
To check the health of a deployed function, use the <function-url>/healthcheck
API. The x-org-id-18
header must match the app’s env/config var ORG_ID_18
value.
$ curl -H "x-org-id-18: 00DDH00000000002AQ" https://javafunction.herokuapp.com/healthcheck
"OK"
If a function process dies, then /healthcheck
attempts to restart the function.
Example function logs:
14:03:18.113 INFO [RUNTIME] c.s.f.p.c.HealthCheckController - [healthcheck-1680811398112]: Received /healthcheck request
14:03:18.119 INFO [RUNTIME] c.s.f.p.s.InvokeFunctionService - [healthcheck-1680811398112]: Invoking function https://javafunction.herokuapp.com...
14:03:18.141 INFO [RUNTIME] c.s.f.p.s.InvokeFunctionService - [healthcheck-1680811398112]: Invoked function https://javafunction.herokuapp.com in 18ms
14:03:18.142 WARN [RUNTIME] c.s.f.p.c.HealthCheckController - [healthcheck-1680811398112]: Received /healthcheck exception: I/O error on POST request for "https://javafunction.herokuapp.com": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused)
14:03:18.142 INFO [RUNTIME] c.s.f.p.c.HealthCheckController - [healthcheck-1680811398112]: Attempting to restart function...
14:03:18.142 INFO [RUNTIME] c.s.f.p.service.StartFunctionService - Starting function w/ args: /app/.jdk/bin/java -XX:+UseContainerSupport -Xmx671m -XX:CICompilerCount=2 -Dfile.encoding=UTF-8 -jar /app/proxy/target/sf-fx-runtime-java-runtime-1.1.3-jar-with-dependencies.jar serve /app -h 0.0.0.0 -p 8080
14:03:18.145 INFO [RUNTIME] c.s.f.p.service.StartFunctionService - Started function started on port 8080, process pid 134600
...
14:03:20.688 INFO [RUNTIME] c.s.f.j.r.c.AbstractDetectorCommandImpl - Found 1 function(s) after 399ms.
14:03:20.689 INFO [RUNTIME] c.s.f.j.r.commands.ServeCommandImpl - Found function: com.example.JavafunctionFunction
14:03:20.715 INFO [RUNTIME] io.undertow - starting server: Undertow - 2.2.19.Final
...
14:03:21.145 INFO [RUNTIME] c.s.f.p.c.HealthCheckController - [healthcheck-1680811398112]: Retrying function /healthcheck...
14:03:21.145 INFO [RUNTIME] c.s.f.p.s.InvokeFunctionService - [healthcheck-1680811398112]: Invoking function https://javafunction.herokuapp.com...
14:03:21.237 INFO [RUNTIME] c.s.f.p.s.InvokeFunctionService - [healthcheck-1680811398112]: Invoked function https://javafunction.herokuapp.com in 91ms
Efficiently manage your Salesforce org’s storage by deleting obsolete AsyncFunctionInvocationRequest__c
records.
$ sfdx data query --query "SELECT Id, LastModifiedDate FROM AsyncFunctionInvocationRequest__c ORDER BY LastModifiedDate"
ID LASTMODIFIEDDATE
────────────────── ────────────────────────────
a00B000000Otu7cIAB 2023-04-06T19:13:00.000+0000
Total number of records retrieved: 1.
Querying Data... done
# Delete obsolete record
$ sfdx data delete record --sobject AsyncFunctionInvocationRequest__c --record-id a00B000000Otu7cIAB
Successfully deleted record: a00B000000Otu7cIAB.
Deleting Record... Success
Background jobs can dramatically improve the scalability of a web app by enabling it to offload slow or CPU-intensive tasks from its front-end. This helps ensure that the front-end can handle incoming web requests promptly, reducing the likelihood of performance issues that occur when requests become backlogged.
For more information, see Worker Dynos, Background Jobs and Queueing.
Heroku provides three managed data services all available to Salesforce Functions apps:
- Heroku Postgres
- Heroku Data for Redis
- Apache Kafka on Heroku
For more information, see Databases & Data Management.
Heroku Shield is a set of Heroku platform services that offer additional security features needed for building high compliance applications. Use Heroku Shield to build HIPAA or PCI-compliant apps for regulated industries, such as healthcare, life sciences, or financial services. Heroku Shield simplifies the complexity associated with regulatory compliance, so you can enjoy same great developer experience when building, deploying, and managing your high compliance apps.
For more information, see Heroku Shield.