Product events are generated when users perform actions in Atlassian products. Apps can subscribe to a list of product events using a trigger in the manifest.
Events are passed to your app via the event
parameter.
1 2export async function run(event, context) { console.log("event: " + JSON.stringify(event)); return true; }
To receive a product event with a Forge app, your Jira projects or Confluence spaces must be accessible by the default user group. This is because the system user created for your Forge app is only a member of the default user group. If a restricted Jira project or Confluence space generates a product event, your Forge app is unable to receive the event.
To learn more about this issue and for updates on when this behavior is improved, see the FRGE-212 Jira issue.
There are two types of retry events:
Install the latest Forge events package by running:
npm i @forge/events
You can request a retry for a product event trigger by returning an InvocationError
object. This is defined in the @forge/events
package
You can only retry an event for a maximum of four times.
Additional options can be included in the InvocationError
via a RetryOptions
object, allowing you to provide more information about what went wrong and configure the retry.
Event payload schema
1 2RetryOptions { retryAfter: number // retry trigger after in seconds retryReason: InvocationErrorCode // reason why the error occured retryData: any // additional data to assist retry logic } enum InvocationErrorCode { // There was a rate limit upstream that caused the Application to fail. FUNCTION_UPSTREAM_RATE_LIMITED = "FUNCTION_UPSTREAM_RATE_LIMITED", // Some application level error occurred and a retry is warranted FUNCTION_RETRY_REQUEST = "FUNCTION_RETRY_REQUEST" }
retryAfter limitation
The maximum retryAfter
value is 900
seconds (15 minutes). Any retryAfter
values exceeding this limit are lowered to 900
seconds.
retryReason values
Value | Description |
---|---|
FUNCTION_UPSTREAM_RATE_LIMITED | Rate limit upstream that caused the app to fail |
FUNCTION_RETRY_REQUEST | Unclassified error occurred during the app that the developer would like to retry |
Example for requesting a retry
In the following sample code, the app calls an upstream Jira Product API and is rate limited. A retry is requested with a timeout that is equal to the backoff time provided by the Jira Product API and the retry reason is FUNCTION_UPSTREAM_RATE_LIMITED
as there was an upstream dependency that was rate limited.
1 2import {InvocationError, InvocationErrorCode} from '@forge/events' import {asApp, route} from '@forge/api' export async function run(event, context) { const userName = 'john'; const response = await asApp().requestJira(route`/rest/api/3/user/search?query=${userName}`, { headers: { 'Accept': 'application/json' } }); if(response.headers.has('Retry-After')){ return new InvocationError({ // The App can request the retry to happen after a certain time period elapses retryAfter: parseInt(response.headers.get('Retry-After')), // The App should provide a reason as to why they are retrying. // This reason will be feedback to the event payload on the retry // and is to help the developer discern the initial failure reason. retryReason: InvocationErrorCode.FUNCTION_UPSTREAM_RATE_LIMITED, retryData: { userName: userName } }); } }
Example for handling a retry
In the following sample code the app checks whether or not the retryContext
field
exists in the event payload. If it exists, it means that the app is currently handling
a retry and the app can handle the retry accordingly. The app can request another retry
if another retryable error occurs, but note that the event can only be retried up to 4 times.
Properties
There will be one extra object retryContext
in the event payload for a retry. This object contains three properties:
retryCount
: number of times (max 4) the app requested for retryretryReason:
reason why the error occurredretryData
: additional data to assist retry logic1 2import { RetryOptions, InvocationError, InvocationErrorCode } from "@forge/events" export async function onIssueCreated(event, context) { try { // retryContext will be populated if this is a retry if (event.retryContext) { const { retryCount, retryReason, retryData } = event.retryContext; handleRetry(retryCount, retryReason, retryData, event); } else { handleEvent(event); } } catch(error) { // If the event is retryable, the App can request for another retry // although, note that the maximum number of retries is 4 if (e instanceof RetryableException) { const retryOptions: RetryOptions = { retryAfter: calculateBackOffTime(event.retryContext), retryReason: InvocationErrorCode.FUNCTION_RETRY_REQUEST, retryData: getRetryData(e, event) } return new InvocationError(retryOptions); } } }
Platform level errors cannot be captured by the app. Examples include timeouts and Out of memory(OOM) errors. If a platform error occurs, the Forge platform will automatically retry the event on behalf of you.
retryReason values
Value | Description |
---|---|
FUNCTION_OUT_OF_MEMORY | The function ran out of memory (allocated by Forge Platform/Lambda) in the previous attempt |
FUNCTION_TIME_OUT | The function timed out during the previous attempt |
FUNCTION_PLATFORM_RATE_LIMITED | An infrastructure Quota/Rate Limit occurred during the previous attempt at running the function |
FUNCTION_PLATFORM_UNKNOWN_ERROR | An undefined error occurred during the previous attempt at running the function |
When using product events, your Forge app must have permission from the site admin to access
the data it provides within the event payload. The OAuth scope required is documented under
each product event. Note, running the forge lint
command picks up these required scopes.
See Permissions for detailed information about each scope. See Add scopes to call an Atlassian REST API to add new scopes to your app.
Rate this page: