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.
The answer is: do not use your own variable names in the function. Instead of
it should be
as the setup depends on you using those exact variable names (as also used in the examples). Answer thanks to Atlassian staff.