Product events

Product events

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
2
export 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.

Arguments

  • event: a payload detailing the event. See the documentation for an event for a detailed description of its payload.
  • context: additional information about the context the event occurred in.
    • installContext: an identifier for the Atlassian site the app is installed in.

Retry product events

There are two types of retry events:

  1. Retry app level errors
  2. Retry platform level errors

Install the latest Forge events package by running: npm i @forge/events

1. Retry for app level errors

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
2
RetryOptions {
  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

ValueDescription
FUNCTION_UPSTREAM_RATE_LIMITEDRate limit upstream that caused the app to fail
FUNCTION_RETRY_REQUESTUnclassified 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
2
import {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 retry
  • retryReason: reason why the error occurred
  • retryData: additional data to assist retry logic
`retryReason` and `retryData` will be populated with the same values as were given when requesting the retry with `InvocationError`.
1
2
import { 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);
    }
  }
}

2. Retry for platform level errors

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

ValueDescription
FUNCTION_OUT_OF_MEMORYThe function ran out of memory (allocated by Forge Platform/Lambda) in the previous attempt
FUNCTION_TIME_OUTThe function timed out during the previous attempt
FUNCTION_PLATFORM_RATE_LIMITEDAn infrastructure Quota/Rate Limit occurred during the previous attempt at running the function
FUNCTION_PLATFORM_UNKNOWN_ERRORAn undefined error occurred during the previous attempt at running the function

OAuth 2.0 scopes

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.

Known issues

  • Product events larger than 200 kB are not delivered. This limit may change without notice.

Rate this page: