fastify/avvio

Use inside use doesn't work anymore

allevo opened this issue · 14 comments

Using fastify, this code works correctly in 0.28 (avvio version 2):

function pluginOk (fastify, opts, next) { next() }

t.test('ok', t => {
  t.plan(2)
  const fastify = Fastify()

  fastify.register(require('./index'), err => {
    t.error(err)
    fastify.register(pluginOk, err => {
      t.error(err)
    })
  })
})

In 0.30.2 (avvio version 3) the second error has this message: Impossible to load "pluginOk" plugin because the parent "" was already loaded

This behaviour is introduced by #29 on avvio version 3.

How can I rewrite the previous code in new avvio version?

what is in ./index.js?

index.js is another plugin like

function antoherPlugin(fastify, opts, next) { next() }

The problem are nested register calls. Don’t use the callbacks.

It’s already handled, you don’t have to do anything. Use another register in the main plugin.

I don't understand. My situation is like this (in fastify):

function plugin1 (fastify, opts, next) {
  setTimeout(function () { // silumate some async
    fastify.decorate('foo', 4) // decorating with the result of the async operation
  }, 100)
}

function plugin2 (fastify, opts, next) {
  console.log(fastify.foo) // using the previous set value
}

How can I register plugin2 underlining the dependency to plugin1 without wrinting a callback hell?

this doesn't work anymore

EDIT:
or

How can I write the dependency betweet plugin2 and fastify-mongodb?

function plugin2 (fastify, opts, next) {
  console.log(fastify.mongo) // use fastify-mongodb
}

Just don’t use series. It will work as expected, it will be present in any subsequent plugin that you use. The callback in register is kind of useless.

I'm very confused regarding whatever it is that has changed.

I would imagine developers would want to know that something such as a DB connection is broken before the call to fastify.listen (for example, the mongodb plugin).

My own code is currently split into a collection of plugins, each of which is registered, and then a collection of routes. This now breaks with the "already loaded" error.

Can the expected use of register be addressed somewhere in the fastify repo?

@wooliet there is no need to declare the routes after loading all the dependent plugins. This is already done for you, just call get() (etc) after the relevant register(). Error handing is centralized, if a plugin does not boot, everything stops and error.

If you need to wait for whatever reason, wrap it in a plugin.

The previous order was non-deterministic, and it caused some weird bugs. This is very deterministic. Really, you should not use the register() callback. I'll try to remove that in the next release as it's a source of confusion. You might only want to use it if you need to unwind some other state in case of error.

@mcollina I'm sorry to bother you guys with this, and I'll be glad to move this to the fastify repo if you prefer. But I think there's a communication breakdown somewhere.

Copied below is code that is representative of what used to work (fastify 0.29.2) but now (0.30.2) results in:

Error: Impossible to load "bound _after" plugin because the parent "formBodyPlugin" was already loaded

I am interested in what an updated version should look like.

const async = require('async');
const formbody = require('fastify-formbody');
const fastify = require('fastify')();

async.waterfall([
  next => plugins(next),
  next => routes(next)
], (err) => {
  if(err) process.exit(1);
  fastify.listen('9090', '0.0.0.0', err => console.log('running'));
})


function plugins(done) {
  fastify.register(formbody, {}, (err) => {
    done(err);
  });
}

function routes(done) {
  fastify.get('/ping', (req, resp) => {
    resp.code(204).send();
  });
  done();
}

@mcollina we should remove the callback definitely.
The callback makes developer confused.

Anyway,

fastify.register(require('fastify-mongodb'), {})
fastify.register(function (f, o, n) {
  var myColl = f.mongo.db.collection('my-collection') // f.mongo is defined! 
})

works for me.

@allevo at what point in that flow do you call fastify.listen?

Maybe my hangup is that I don't want to open up the port for incoming requests until I know everything has successfully initialized. But if that's not possible anymore then ok, no biggie.

@wooliet

'use strict'

fastify.register(require('fastify-mongodb'), {}) // set up the mongo connection

fastify.register(function (f, o, n) {
  // please don't drop you database in production!!!!
  return f.mongo.db.dropDatabase() // the connection is made
})

fastify.register(function setRoutes(f, o, n) {
  var myColl = f.mongo.db.collection('my-collection') // the connection is made
  f.get('/', function (req, reply) {
    reply.send(myColl.find({}).toArray())
  })
})

fastify.listen(function (err) {
  // server up if err is falsy!
})

I'll close this conversation because the issue is "resolved": the use method (aka register in fastify) keeps the same call order.

If you are other questions/issues please open another one (in fastify or avvio)