Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Understand how to use Fastify plugin #1056

Closed
SkyTik opened this issue Sep 12, 2024 · 6 comments
Closed

Understand how to use Fastify plugin #1056

SkyTik opened this issue Sep 12, 2024 · 6 comments
Labels
question Further information is requested

Comments

@SkyTik
Copy link

SkyTik commented Sep 12, 2024

What are you trying to achieve, or the steps to reproduce?

I'm studying Fastify and register plugin with @fastify/redis like this

app.register(redisPlugin, {
  client: initRedis(app.config.REDIS_INTERNAL__HOST, app.config.REDIS_INTERNAL__PASS),
  closeClient: true,
});

And register route:

import { FastifyInstance, FastifyPluginAsync } from "fastify";

import v1Routes from "./v1/index.js";

const routes: FastifyPluginAsync = async (fastify: FastifyInstance): Promise<void> => {
  fastify.register(v1Routes, { prefix: "/v1" });
};

export default routes;

and inside v1 route

const v1Routes: FastifyPluginAsync = async (fastify: FastifyInstance): Promise<void> => {
  fastify.register(seedlogsRoutes, { prefix: "/seedlogs" });
};

route with controller

const orderRoutes: FastifyPluginAsync = async (fastify: FastifyInstance) => {
 fastify.get("/", getOrders);
};

export default orderRoutes;

with getOrders function, I can access Redis like this:

const getOrders = async (request: FastifyRequest, reply: FastifyReply) => {
  const redis = request.server.redis;
  await redis.set("orders", "abc");
  const orders = await redis.get("orders");
  return { message: "Orders", orders };
};

But what if I want to access Redis from an inner service, how can I access Redis from the
FastifyInstance, like

const cacheOrder = async (order) => {
  await redis.set("order",order)
}

Should I init a client before passing it to the plugin and reuse it wherever does not have access to the FastifyInstance?

import redis from "./cache/redis.js"

I searched on Google but still can not find any satisfactory answer.
Many thanks

Context

  • node version: 20.14.0
  • fastify version: 4.28.1
  • os: Mac
@dosubot dosubot bot added the question Further information is requested label Sep 12, 2024
@metcoder95
Copy link
Member

What do you mean exactly with an inner service?

When decorating a FastifyInstance, you can access the different decorations through the this context of the decoration.

Then, you can do things like:

fastifyInstance.decorate('service', function (..args) {
  await this.otherDecorator();
  // do your thing
})

So the reference to the main fastifyInstance is preserved and you can use it across decorators.

@SkyTik
Copy link
Author

SkyTik commented Sep 13, 2024

my flow is Route -> Controller -> Service, the Controller look like this

const getOrders = async (request: FastifyRequest, reply: FastifyReply) => {
  const redis = request.server.redis;
  await redis.set("orders", "abc");
  const orders = await redis.get("orders");
  return { message: "Orders", orders };
};

I can easily access the Redis via server, now I want to modify the Controller into this

const getOrders = async (request: FastifyRequest, reply: FastifyReply) => {
  const order = request.body;
  const newOrder = await createOrder(order);
  await cacheOrderDetail(order)
  return { message: "Orders", orders };
};

const cacheOrderDetail = (order) => {
 // how can I access Redis in this function
}

In Express, I only need to import the Redis client.

@metcoder95
Copy link
Member

metcoder95 commented Sep 13, 2024

I'd say that it is mostly up to you; you can also import and reference it there directly, or follow a Dependency Injection pattern.

fastify.decorate('cacheOrderDetail', cacheOrderDetail(fastify.redis));

// later in code

fastify.cacheOrderDetail(order);

It will depend on what methodology, or principles are you following within your application structure

@SkyTik
Copy link
Author

SkyTik commented Sep 13, 2024

Still I do not understand why I need plugin if I can import the client directly in code

@climba03003
Copy link
Member

climba03003 commented Sep 13, 2024

We are not restricting developer to use the plugin, you can use the controller just like normal import.

The benefit of plugin is that,

  1. Database / Resource is managed inside a single place and binded to the application lifecycle.
  2. Ensure the singleton of instance
  3. Encapsulation Context

I knows that you can achieve it with many different way.
The plugin only offer you one of the solution.

@SkyTik
Copy link
Author

SkyTik commented Sep 13, 2024

Thank you, I'm looking into DI to achieve my purpose.

@SkyTik SkyTik closed this as completed Sep 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants