Closed sathishsoundharajan closed 5 years ago
I can elaborate on this later, but here are some initial thoughts.
hapi plugins cater to microservices because if they're written well they can trivially be deployed together or separately. Often it's desirable to deploy them together until they need to scale independently. Each plugin can represent a service. You compose your server by attaching those services/plugins to hapi connections. In order to achieve this, each plugin should rely almost exclusively on plugin options for configuration.
Sharing DB connections and other resources is a very important thing. The general approach I take is for each service/plugin to declare the resources it needs (likely using a server decoration). Then during server initialization (the onPreStart
server extension) those resources are doled-out. At that point it's possible that multiple plugins/services share the same resource. A reasonable example of this can be seen in a plugin I wrote named dogwater.
A note on caching. I suggest using catbox for caching. Write cacheable routines as hapi server methods. Server methods can be configured to cache results in various different ways. The caches themselves will be defined in your server configuration, and each will have its own name. If you want your services (each of which defining its own server methods) to use different caches, pass the names of those caches into the plugin as plugin options. Keep your plugin's code and your server's configuration decoupled in this way so that the service cares how it's configured but not how it's deployed.
Here's a boilerplate (somewhat unfinished) I often use that has a good separation between server and plugin: https://github.com/devinivy/boilerplate-api. The server only exists to help with development or for a reasonable standalone deployment.
Not sure if this is useful but @geek and I just put together a workshop on microservices which we recently gave at midwestjs. Here is the workshop if you are interested. Some of the examples are hapi but this may be what you are looking for. https://github.com/lloydbenson/microservices-workshop.
Yeah, not sure how I failed to mention seneca and the chairo plugin!
@devinivy Thanks for the breif explanation. @lloydbenson Thanks for the workshop.
There are some new patterns I've been playing with that make building large apps easier. The problem is to find the time to write about it. For example, I use a process runner to create the hapi server and load plugins into it, where each plugin is created as a connectionless plugin that creates its own internal connection. By @hueniverse
I got this info from him on via Sideway Hapijs Q/A session.
I was more keen on how he was able to separate and share those plugins.
P.S: I have lot question about senecajs. Need to look on it more.
Hello guys please take a look at this project it is using Hapi internally and you can add Hapi plugins to it
It is based on GraphQL and it can help you to work with microservices and merge GraphQL Schema from all microservicess added.
@gapi namespace: https://github.com/Stradivario/gapi
@gapi microservices starter project https://github.com/Stradivario/gapi-starter-microservices
example microservice https://github.com/Stradivario/gapi-starter-microservices/blob/master/src/app/microservices/findUser.microservice.ts
import {
GraphQLInt,
GraphQLNonNull,
GapiController,
Type,
Query,
GapiModule,
Bootstrap,
ConfigService,
GapiServerModule,
Container
} from '@gapi/core';
import { UserType } from '../types/user.type';
import { UserService } from '../core/services/user/user.service';
import { CoreModule } from '../core/core.module';
@GapiController()
export class UserQueriesController {
constructor(
private userService: UserService
) {}
@Type(UserType)
@Query({
id: {
type: new GraphQLNonNull(GraphQLInt)
}
})
findUser(root, { id }, context): UserType {
return this.userService.findUser(id);
}
}
@GapiModule({
imports: [
CoreModule,
GapiServerModule.forRoot({
...Container.get(ConfigService).APP_CONFIG,
port: 10000
})
],
controllers: [UserQueriesController]
})
export class AppModule {}
example Hapi Plugin can be found here https://github.com/Stradivario/gapi-voyager/blob/master/development/gapi-voyager-plugin.ts
import { GapiVoyagerConfig } from "./gapi-voyager-config";
import { GapiModule, GapiHapiPlugin, GapiHapiPluginInterface } from '@gapi/core';
import renderVoyagerPage from 'graphql-voyager/middleware/render-voyager-page';
@GapiHapiPlugin()
export class VoyagerGapiHapiPlugin implements GapiHapiPluginInterface {
name = 'VoyagerGapiHapiPlugin';
version = '1.0.0';
constructor(
private config: GapiVoyagerConfig
) {}
async register(server, options) {
server.route({
method: 'GET',
path: this.config.path,
handler: this.handler.bind(this)
});
}
async handler(_request, reply) {
return await renderVoyagerPage({ endpointUrl: this.config.endpointUrl });
}
}
Regards, Kristiyan Tachev
Hi Folks, Does someone have an idea of how to rewrite my monolithic Hapi.js Application into Microservice ??
My App uses 2 databases,
I googled a lot about Microservice and its pattern, seen examples using Express & Docker. Incase of express, every API is an express application with Associated docker container.
My Questions are