How does graphql apollo server uses memcached as a cache system? - express

Following apollo documentation, I'm unable to get data from memcached with telnet commands. It seems like the data is cached because when I resend the same request the datasource doesn't call the APIs.
const server = new ApolloServer({
typeDefs,
resolvers,
cache: new MemcachedCache(
'127.0.0.1:11211',
{ retries: 10, retry: 10000 }, // Options
),
dataSources: () => ({
moviesAPI: new MoviesAPI(),
}),
});
I tried a manual implementation of memcached inside a dummy project and I was able to set/get data in the telnet interface.
Is the memcached queried by graphql or do we need to do it manually in the resolvers ?
Any help is welcome

The option to pass a cache into ApolloServer's initialization is optionl. With that being said , the cache highly downsized the speed of your database fetches.You have to pass the given cache in the initialization of any dataSource class, like this:
class DogCustomDataSource extends CustomDataSource{
constructor(models){
....
}
initialize({context,cache}){
this.context=context
this.cache=cache
}
}
Yes, you are right , subsequently, you have to set and delete objects to the cache in the methods of your dataSource, like this:
async get(id,{ttlInSeconds}={}){
.....
await this.cache.set("yourKey","yourValue",{ttl:ttlInSeconds})
//or
await this.cache.del("yourKey")
.....
}

Related

How can i pass express Request and Response objects into graphql-yoga context using the createYoga function?

I want to pass the express req and res object to my context because i want to use express-sessions to do session-based-auth because the default requests from the context does not know about sessions. Here is what I have tried
app.use("/graphql", (req, res) => {
return createYoga({
context: ({ params }) => {
return {
req,
params,
res,
prisma,
redis: redisClient,
};
},
graphiql: true,
landingPage: false,
cors: false,
schema,
});
});
But if i try this it seems like the request is not going through.
According to the docs, while running in node.js and express runtime, the context will automatically have the request and response.
Server Context
When creating the server instance, GraphQL Yoga accepts an additional
object from your base server framework or library that will be merged
with the default context. Node.js (standalone, express and Next.js
etc.)
If you are using GraphQL Yoga as a standalone server with createServer
from the http(s) module or exposing it as a middleware as we show in
the express or Next.js integration recipes.
req - Node.js IncomingMessage object
res - Node.js ServerResponse object
The req and res objects are added to the initial context object.
const serverContext = { ...defaultContext, req, res }
Thus, when using #graphql-yoga/node, it is possible to access
context.req and context.res within the GraphQL resolvers or the user
context factory function.
However, we recommend avoiding using context.req and context.res
wherever possible and instead favor context.request, as it is more
future-proof and platform independent (as Node.js HTTP servers adopt
the Fetch Response API).
I did try this out and the context does have the req and res objects.

How to handle JWT authentication with RxDB?

I have a local RxDB database and I want to connect it with CouchDB. Everything seems to works fine except for authentication. I have no idea how to add it differently then inserting credentials in database url:
database.tasks.sync({
remote: `http://${username}:${pass}#127.0.0.1:5984/tododb`,
});
I would like to use JWT auth but can't find how to add a token to sync request. I found only some solutions for PouchDB (pouchdb-authentication plugin) but can't get it working with RxDB.
RxDB is tightly coupled with PouchDB and uses its sync implementation under the hood. To my understanding, the only way to add custom headers to a remote PouchDB instance (which is what is created for you when you pass a url as the remote argument in sync), is to intercept the HTTP request:
var db = new PouchDB('http://example.com/dbname', {
fetch: function (url, opts) {
opts.headers.set('X-Some-Special-Header', 'foo');
return PouchDB.fetch(url, opts);
}
});
PouchDB replication documentation (sync) also states that:
The remoteDB can either be a string or a PouchDB object. If you have a fetch override on a remote database, you will want to use PouchDB objects instead of strings, so that the options are used.
Luckily, RxDB's Rx.Collection.sync does not only accept an server url as the remote argument, but also another RxCollection or a PouchDB-instance.
RxDB even reexport the internally used PouchDB module, so you do not have to install PouchDB as a direct dependency.
import { ..., PouchDB } from 'rxdb';
// ...
const remotePouch = new PouchDB('http://27.0.0.1:5984/tododb', {
fetch: function (url, opts) {
opts.headers.set('Authorization', `Bearer ${getYourJWTToken()}`)
return PouchDB.fetch(url, opts);
}
})
database.tasks.sync({
remote: remotePouch,
});

How to create dynamically multiple graphql endpoints on expressjs - nodejs

I'm creating an API where I want to create dynamically multiple graphql endpoints according to the user's preferences without restarting the server.
In general is something very simple, the user will specify the graphql schema and the resolvers, and after the user will push a button to generate a graphql endpoint which will be under the mydomain/randomString
The only code that I can provide so far is how am I creating a graphql endpoint in my expressjs app, which happens on one of the initial files that run when the nodejs server starts.
const {ApolloServer, gql} = require('apollo-server-express');
const typeDefs = gql(fs.readFileSync('./server/graphql/schema.graphql', {encoding: 'utf-8'}));
const resolvers = require ('./server/graphql/resolvers');
const graphqlServer = new ApolloServer({
typeDefs
,resolvers
,engine: {
apiKey: "aRandomString"
}
,introspection: true
// ,context: ({req}) => ({user: req.user && db.users.get(req.user.sub)})
});
After the user generates the endpoint, he/she will be able to query on that graphql endpoint.

InversifyJS: dependency instantiation per HTTP Request

I'm using Inversify.JS in a project with Express. I would like to create a connection to a Neo4J Database, and this process has two objets:
The driver object - Could be shared across the application and created one time only
The session object - Each HTTP request should create a session against the driver, whose lifecyle is the same as the http request lifecycle (as long as the request ends, the connection is destroyed)
Without Insersify.JS, this problem is solved using a simple algorithm:
exports.getSession = function (context) { // 'context' is the http request
if(context.neo4jSession) {
return context.neo4jSession;
}
else {
context.neo4jSession = driver.session();
return context.neo4jSession;
}
};
(example: https://github.com/neo4j-examples/neo4j-movies-template/blob/master/api/neo4j/dbUtils.js#L13-L21)
To create a static dependency for the driver, I can inject a constant:
container.bind<DbDriver>("DbDriver").toConstantValue(new Neo4JDbDriver());
How can I create a dependency instantiated only once per request and retrieve them from the container?
I suspect I must invoke the container on a middleware like this:
this._express.use((request, response, next) => {
// get the container and create an instance of the Neo4JSession for the request lifecycle
next();
});
Thanks in advance.
I see two solutions to your problem.
use inRequestScope() for DbDriver dependency. (available since 4.5.0 version). It will work if you use single composition root for one http request. In other words you call container.get() only once per http request.
create child container, attach it to response.locals._container and register DbDriver as singleton.
let appContainer = new Container()
appContainer.bind(SomeDependencySymbol).to(SomeDependencyImpl);
function injectContainerMiddleware(request, response, next) {
let requestContainer = appContainer.createChildContainer();
requestContainer.bind<DbDriver>("DbDriver").toConstantValue(new Neo4JDbDriver());
response.locals._container = requestContainer;
next();
}
express.use(injectContainerMiddleware); //insert injectContainerMiddleware before any other request handler functions
In this example you can retrieve DbDriver from response.locals._container in any request handler/middleware function registered after injectContainerMiddleware and you will get the same instance of DbDriver
This will work, but I'm not sure how performant it is. Additionally I guess that you may need to somehow dispose requestContainer (unbind all dependencies and remove reference to parent container) after http request is done.

How to subscribe sailsjs rabbitmq-adapter

I have followed the steps explained in https://www.npmjs.com/package/sails-rabbitmq. And When I persist the data in Message DataModel, it gets saved in MongoDB as well as in RabbitMQ ( CloudAMQP.com ). But i am seeing this error message in the sails lift console.
sails-rabbitmq: waiting for orm hook to load before binding persistence handlers...
Any tips for avoiding this warning message?
As well my subscription program in api/services is not getting invoked.. For testing purpose, invoked this service from a sails controller, yet,
Message.getSubscribeSocket({ where: { stream: 'random' } })
.then(function (socket) {
socket.on('data', function (data) {
var message = JSON.parse(data);
// see, I told you it was "low-level"
// ...
});
});
Thanks in advance for your guidance