How can i make all queries and mutations in Nest over WebSockets only?
Enable full WebSocket transport:
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
subscriptions: {
'graphql-ws': true
},
})
https://docs.nestjs.com/graphql/subscriptions
Related
In an NX monorepo I'm building 3 nestjs application, an auth-service + user-service and a gateway to start off with. They're all powered by apollo graphql and following the official nestjs documentation.
The issue that I'm having is that with both the user-service and auth-service up and processing requests successfully as individual servers, at the same time, the gateway throws
Couldn't load service definitions for "auth" at http://localhost:3100/apis/auth-service/graphql: 400: Bad Request
The services themselves are standard graphql applications, nothing basic.
The definitions for the gateway are as such:
{
server: {
debug: true,
playground: true,
autoSchemaFile: './apps/gateway/schema.gql',
sortSchema: true,
introspection: true,
cors: ['*'],
path: '/apis/gateway/graphql';
},
gateway: {
supergraphSdl: new IntrospectAndCompose({
subgraphHealthCheck: true,
subgraphs: [
{
name: 'user',
url: resolveSubgraphUrl('user'),
},
{
name: 'auth',
url: resolveSubgraphUrl('auth'),
},
],
}),
}
}
I have created an nx based monorepository that allows you to reproduce this issue easily, by spinning up all 3 servers in watch mode at the same time, on localhost, on different ports.
Everything is mapped as it should. Link: https://github.com/sebastiangug/nestjs-federation.git
The README contains the two commands necessary to run it as well as the same set of instructions plus the health-checks queries available from each service.
Versions used:
"#apollo/subgraph": "2.1.3",
"#apollo/federation": "0.37.1",
"#apollo/gateway": "2.1.3",
"apollo-server-express": "3.6.7",
"graphql": "16.5.0",
"#nestjs/graphql": "10.1.3",
"#nestjs/platform-express": "9.0.8",
Any ideas what I'm doing wrong here or what further configuration is necessary to achieve this?
Thank you
I am leveraging the use of AWS services for a functionality
Summary: I have a lambda that accesses a Postgres DB in RDS. Instead of directly connecting to DB, the proxy endpoint is accessed as it is architecturally advised. I have no problem generating IAM token and it is used as the password while creating the Sequelize connection.
Problem: Initially I was not using rds-proxy. In this scenario, I was making use of the execution context of lambda to reuse connections. Here I didn't close connections in lambda(It worked fine - was directly connecting to the database here). But on proxy implementation, without closing connections, there is a big spike in connections that proxy makes to the database and it is testing the limits on load. with 10req/sec I'm seeing 90 connections
On closing the connections in lambda the connections get substantially reduced to <20.
But I have nested database queries during a single lambda execution and it will be difficult to rewrite these functionalities.
Below is the Sequelize connection object written to create connection
const { Sequelize } = require('sequelize');
let proxyToken = '***latest iam token with 15min validity***';
let additionalConnectionDetails = {
host: process.env.PROXY_ENDPOINT,
schema: 'schemaname',
searchPath: 'searchpath',
dialect: 'postgres',
dialectOptions: {
prependSearchPath: true,
ssl: {
require: true,
rejectUnauthorized: false
}
},
// pool: {
// max: 2,
// min: 1,
// acquire: 3000,
// idle: 0,
// evict: 120000
// },
// // maxConcurrentQueries: 100
}
sequelize_connection = new Sequelize(dbCreds.app, dbCreds.userName, proxyToken, additionalConnectionDetails);
console.log('sequelize', sequelize_connection)
return sequelize_connection
I tried using the connection pool, but it didn't make much of a difference in lambda.
How can I reduce the number of connections established without closing connections. Any suggestions are appreciated. Thanks in advance.
Problem
In a federated nest app, a gateway collects all the schemas from other services and form a complete graph. The question is, how to re-run the schema collection after a sub-schema has been changed?
Current Workaround
Restarting the gateway solves the problem, but it does not seem like an elegant solution.
Other Resources
Apollo server supports managed federation which essentially reverts the dependency between the gateway and the services. Sadly I couldn't find anything relating it to NestJS.
When configuring gateway application with NestJS, and when already have integrated with Apollo studio, then you need not define any serviceList in GraphQLGatewayModule. This is how your module initialization should look like:
GraphQLGatewayModule.forRootAsync({
useFactory: async () => ({
gateway: {},
server: {
path: '/graphql',
},
}),
})
Following environment variables should be declared on the machine hosting your gateway application:
APOLLO_KEY: "service:<graphid>:<hash>"
APOLLO_SCHEMA_CONFIG_DELIVERY_ENDPOINT: "https://uplink.api.apollographql.com/"
Post deployment of Federated GraphQL service, you may need to run apollo/rover CLI service:push command like below to update the schema which writes to schema registry and then gets pushed to uplink URL which is polled by gateway periodically:
npx apollo service:push --graph=<graph id> --key=service:<graph id>:<hash> --variant=<environment name> --serviceName=<service name> --serviceURL=<URL of your service with /graphql path> --endpoint=<URL of your service with /graphql path>
You can add a pollIntervalInMs option to the supergraphSdl configuration.
That will automatically poll the services again in each interval.
#Module({
imports: [
GraphQLModule.forRootAsync<ApolloGatewayDriverConfig>({
driver: ApolloGatewayDriver,
useFactory: async () => ({
server: {
path: '/graphql',
cors: true
},
gateway: {
supergraphSdl: new IntrospectAndCompose({
subgraphs: [
{ name: 'example-service', url: 'http://localhost:8081/graphql' },
],
pollIntervalInMs: 15000,
})
},
})
})
],
})
export class AppModule {}
We use apollo-server-express to expose a graphql server.
For this server, we have set the introspection variable to false to hide our schema from the outer world which works fine for Graphql calls that go over rest calls.
However, when we set up a websocket connection with this same server, we manage to execute introspection queries, even though that during the instantiation of the apollo server, the introspection is explicitly set to false
the config for booting the Apollo-server looks something like this:
{
schema: <schema>,
context: <context_function>,
formatError: <format_error_function>,
debug: false,
tracing: false,
subscriptions: {
path: <graphQl_path>,
keepAlive: <keep_alive_param>,
onConnect: <connect_function>,
onDisconnect: <disconnect_function>
},
introspection: false,
playground: false
};
Did someone had a similar issue? And if yes, were you able to solve it and how?
apollo-server-express version = 2.1.0
npm version = 6.4.1
node version = 10.13.0
What ApolloServer does internally is prevent you from using the __schema and __type resolvers. I assume you could do the same thing:
export const resolvers = {
Query: {
__type() {
throw new Error('You cannot make introspection');
},
__schema() {
throw new Error('You cannot make introspection');
}
}
}
In Apollo Federation, I am facing this problem:
The gateway needs to be restarted every time we make a change in the schema of any federated service in service list.
I understand that every time a gateway starts and it collects all the schema and aggregates the data graph. But is there a way this can be handled automatically without restarting the Gateway as it will down all other unaffected GraphQL Federated services also
Apollo GraphQL , #apollo/gateway
There is an experimental poll interval you can use:
const gateway = new ApolloGateway({
serviceList: [
{ name: "products", url: "http://localhost:4002" },
{ name: "inventory", url: "http://localhost:4001" },
{ name: "accounts", url: "http://localhost:4000" }
],
debug: true,
experimental_pollInterval:3000
})
the code above will pull every 3 seconds
I don't know other ways to automatically reload the gateway other than polling.
I made a reusable docker image and i will keep updating it if new ways to reload the service emerge. For now you can use the POLL_INTERVAL env var to periodically check for changes.
Here is an example using docker-compose:
version: '3'
services:
a:
build: ./a # one service implementing federation
b:
build: ./b
gateway:
image: xmorse/apollo-federation-gateway
ports:
- 8000:80
environment:
CACHE_MAX_AGE: '5' # seconds
POLL_INTERVAL: '30' # seconds
URL_0: "http://a"
URL_1: "http://b"
You can use express to refresh your gateway's schema. ApolloGateway has a load() function that go out to fetch the schemas from implementing services. This HTTP call could potentially be part of a deployment process if something automatic is needed. I wouldn't go with polling or something too automatic. Once the implementing services are deployed, the schema is not going to change until it's updated and deployed again.
import { ApolloGateway } from '#apollo/gateway';
import { ApolloServer } from 'apollo-server-express';
import express from 'express';
const gateway = new ApolloGateway({ ...config });
const server = new ApolloServer({ gateway, subscriptions: false });
const app = express();
app.post('/refreshGateway', (request, response) => {
gateway.load();
response.sendStatus(200);
});
server.applyMiddleware({ app, path: '/' });
app.listen();
Update: The load() function now checks for the phase === 'initialized' before reloading the schema. A work around might be to use gateway.loadDynamic(false) or possibly change gateway.state.phase = 'initialized';. I'd recommend loadDyamic() because change state might cause issues down the road. I have not tested either of those solutions since I'm not working with Apollo Federation at the time of this update.