Search code examples
javascriptfirebasegoogle-cloud-functionsdiscord.js

How to handle listeners in Cloud Function | Discord.js


I'm using Discord.js to create a bot with Firebase's Cloud Functions. Users access functions from the application client and operate the Discord Bot.

In the code below, discord_test is called and a client.on listener is added. This will return the response after client.login() is called.

exports.discord_test = functions.https.onCall(async (data, context) => {
    console.log("1");
    client.on("ready", async () => {
        console.log("3");
        const snap = await db.collection(colName).doc(docName).get().catch((e) => {
            console.error(e);
        });
        console.log("4");
    });

    console.log("2");
    await client.login(token.token);
});

As you can see, I have set up a log that outputs 1 to 4. It is assumed that numbers 1 to 4 are called in order.

Run this multiple times and the result will look like this:

1st time:

Function execution started

Callable request verification passed

1

2

Function execution took 2220 ms, finished with status code: 200

3

4 wasn't called.

2nd time:

Function execution started

Callable request verification passed

1

2

Function execution took 1689 ms, finished with status code: 200

3 and 4 weren't called.

The timing when I execute firebase deploy --only functions (About 10 minutes after the 2nd time)

3

4

3rd time:

Function execution started

Callable request verification passed

1

2

Function execution took 2100 ms, finished with status code: 200

No matter how long I wait after this, 3 and 4 will never be called.


From this result, we can see the function written in the second argument of client.on() will be suddenly blocked at some times and suddenly loaded at other times.

Of course, I understand that this is the listener, so there is nothing strange about the timing being off.

So, what I would like to ask is how much time the Cloud Function retains for this listener, and why the processing is interrupted midway through.

It's very strange that client.on() is loaded when I deploy.


Solution

  • There are a few issues with your code from my POV:

    1. you are mixing use of async and .then()/.catch(). This is not technically wrong but frequently will not behave the way you expect it to. If you know enough about async/await and .then()/.catch() to mix them, then you wouldn't mix them. If you don't know enough, then you shouldn't mix them 😁
    2. Cloud Functions are not meant to be "long running". The longest one will run for is 5 minutes, at which point it will be shut down by the Cloud Function engine. They are not appropriate to operate a "bot".
    3. Your CF code is not returning a value to the CF engine, so it is not able to properly determine when your asynchronous code completes. This leaves your code to the mercy of the CF engine. You want to return a value or a Promise as a clear indication that your CF code is done. Doug covers this fact in Learn JavaScript Promises (Pt. 2) with a Firestore Trigger in Cloud Functions