What is wrong with this Atlassian Confluence Forge use of Async Events?

416 Views Asked by At

I had to create a queue solution in my Forge app. At first, it worked brilliantly. It was easy to implement from https://developer.atlassian.com/platform/forge/runtime-reference/async-events-api/. Then — for me, out of nowhere — yesterday, suddenly my consumer was getting undefined payloads and contexts. I've been wrestling with this issue ever since. I've now removed all of the Async Events (queue) code in my app, except for a simple test setup. I still get this issue and I am starting to wonder if it is me (probably, and then most likely something with async/await/Promise), or maybe (in part also) forge.

[Update: I have created a fresh minimal app instead so I can post the full setup here]

I've created an entire new minimal implementation based on a new app created with forge create:

manifest.yml:

modules:
  macro:
    - key: queue-test-hello-world
      function: main
      title: queue-test
      description: Inserts Hello world!
  trigger:
    - key: dl-spike-one-trigger-pageviewed
      function: dl-trigger-pageviewed
      events:
        - avi:confluence:viewed:page
  function:
    - key: main
      handler: index.run
    - key: dl-trigger-pageviewed
      handler: index.dl_handleTriggerPageViewed
    - key: test-listen
      handler: index.testQueueHandler
  consumer:
    - key: test-consumer
      queue: test-updates
      resolver:
        function: test-listen
        method: test-event-listener
app:
  id: ari:cloud:ecosystem::app/c78946b8-55bf-4c2b-94fe-79dc9e1de33f
permissions:
  scopes:
    - read:confluence-content.summary
    - read:confluence-content.all
    - read:page:confluence
    - storage:app
    - read:space:confluence
    - read:confluence-props
    - write:confluence-props

src/index.jsx:

import ForgeUI, { render, Fragment, Macro, Text } from "@forge/ui";
import { Queue } from '@forge/events';
import Resolver from "@forge/resolver";

const testQueue = new Queue({ key: 'test-updates' });

const App = () => {
  return (
    <Fragment>
      <Text>Hello world!</Text>
    </Fragment>
  );
};

export const run = render(
  <Macro
    app={<App />}
  />
);

const testResolver = new Resolver();
testResolver.define("test-event-listener", async ({ eventPayload, eventContext }) => {
  console.log(`TEST event queue listener`);
  if (eventPayload === undefined || eventContext === undefined) {
    console.log(`TEST event queue listener: ERROR in QUEUE`);
   }
   else {
    console.log(`TEST event queue listener: All info about my context: ${JSON.stringify(eventContext, null, 2)}`);
    console.log(`TEST event queue listener: All info about my payload: ${JSON.stringify(eventPayload, null, 2)}`);
   }
});
export const testQueueHandler = testResolver.getDefinitions();

export async function dl_handleTriggerPageViewed( event, context) {
  console.log( `dl_handleTriggerPageViewed`);
  await testQueue.push( "Hello, world! I viewed a page!");
};

Logging:

INFO    2023-03-26T13:17:15.421Z aa532218-aaec-4829-a109-afdc513ece3d TEST event queue listener
INFO    2023-03-26T13:17:15.421Z aa532218-aaec-4829-a109-afdc513ece3d TEST event queue listener: ERROR in QUEUE

In other words, the queue mechanism is operational, but payload and event are undefined. For me, this has happened 'suddenly' and I've not been able to link it to something I have done. I get the feeling something goes wrong outside of my influence (forge itself). Which is normally not the case of course (I'm normally to blame myself) but now, I'm no longer certain.

I'm working entirely in development, in case that matters.

I would really appreciate a solution here. I'm completely stuck and have been for days now and I'm totally out of ideas what trial/error I could do. I've done everything I could think of, including but not limited to:

  • Change names
  • Uninstall/reinstall
  • Create an entire separate queue/consumer for testing (this code)
  • Try to push from an existing async function in my app instead of via the trigger handler (actually, that was the main use case to start with, the trigger handler is the simplest example I can share)
  • Try to push from a non-async render function using .then()
  • Try to push from a render function using useState()

And much more, but no luck. My queue messages aren't coming back.

1

There are 1 best solutions below

0
On

The answer is: do not use your own variable names in the function. Instead of

testResolver.define("test-event-listener", async ({ eventPayload, eventContext }) => {

it should be

testResolver.define("test-event-listener", async ({ payload, context }) => {

as the setup depends on you using those exact variable names (as also used in the examples). Answer thanks to Atlassian staff.