Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Promise returned by FastifyInstance.register() is resolved before plugin's async registration promise has resolved #3726

@chrskrchr

Description

@chrskrchr

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

3.27.2

Plugin version

N/A

Node.js version

14.18.1

Operating system

macOS

Operating system version (i.e. 20.04, 11.3, 10)

12.2.1

Description

I suspect this may actually be a bug in avvio, but logging it here since it's easily reproduced in a Fastify server startup sequence.

We have a handful of Fastify plugins with async registration functions. Our app registers them sequentially via code like:

await fastify.register(asyncPlugin1);
await fastify.register(asyncPlugin2);
await fastify.register(asyncPlugin3);

We're running into an interesting issue where if we inject some async code in between the plugin register calls (e.g., await someOtherAsyncFunc()), the subsequent promises returned by fastify.register() appear to be resolved immediately without waiting for internal async registration promises to be resolved.

Steps to Reproduce

  1. Clone this repo: https://github.com/chrskrchr/fastify-plugin-race-condition
  2. Run npm install
  3. Run node index.js

Alternatively, run this code yourself:

import Fastify from "fastify";

function sleep(timeMs){
  return new Promise((resolve) => setTimeout(resolve, timeMs));
}

(async () => {
  const fastify = Fastify({
    logger: true,
  });

  await fastify.register(async function plugin0() {
    console.log("plugin0 register start");
    console.log("plugin0 register finish");
  });

  await fastify.register(async function plugin1() {
    console.log("plugin1 register start");

    await sleep(500);

    console.log("plugin1 register finish");
  });

  await sleep(1);

  await fastify.register(async function plugin2() {
    console.log("plugin2 register start");

    await sleep(500);

    console.log("plugin2 register finish");
  });

  console.log("starting server");

  await fastify.listen(3000);
})();

Expected Behavior

We'd expect to see the following output where all plugins complete registration prior to the server being started:

plugin0 register start
plugin0 register finish
plugin1 register start
plugin1 register finish
plugin2 register start
plugin2 register finish
starting server
{"level":30,"time":1645638489287,"pid":13851,"hostname":"AUS-CKARCHER","msg":"Server listening at http://127.0.0.1:3000"}

Instead, we see the following output where the server is started prior to plugin2 actually completing its async registration:

plugin0 register start
plugin0 register finish
plugin1 register start
plugin1 register finish
plugin2 register start
starting server
plugin2 register finish
{"level":30,"time":1645638594807,"pid":13905,"hostname":"AUS-CKARCHER","msg":"Server listening at http://127.0.0.1:3000"}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugConfirmed bughelp wantedHelp the community by contributing to this issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions