Как изменить соединения с БД на лету с GraphQL? - PullRequest
0 голосов
/ 03 октября 2019

У нас есть настройка сервера GraphQL, которая использует один и тот же набор вызовов GraphQL в разных клиентских системах. Эти клиенты имеют одинаковые точные таблицы / структуры, которые не меняются.

Я хотел бы сделать вызовы GraphQL, которые указывают, какое соединение с БД использовать. ИЛИ, если есть аналогичная альтернатива с GraphQL, у меня все на слух.

Я уже некоторое время занимаюсь поиском, поиском на форумах и сканированием документов ...

1 Ответ

0 голосов
/ 08 октября 2019

Одним из возможных решений является создание директивы .

const typeDefs = gql`

  directive @db(client: DbClient) on FIELD_DEFINITION

  type DbClient {
     DB_CLIENT_1
     DB_CLIENT_2
  } 

  type Query {
    users: [User] @db
  }
`;

// Directive


// db client connection config 
const dbConnectionConfig = {
   DEFAULT : {...},
   DB_CLIENT_1: {...},
   DB_CLIENT_2: {...}
}

class DbClientDirective extends SchemaDirectiveVisitor {
  public visitFieldDefinition(field) {
    const { resolve = defaultFieldResolver } = field;
    const { client } = this.args;

    field.args.push({
      name: 'client',
      type: GraphQLString
    });

    field.resolve = async function (
      source,
      { client, ...otherArgs },
      context,
      info,
    ) {


      let connectionConfig = dbConnectionConfig.DEFAULT;
      if(Object.prototype.hasOwnProperty.call(dbConnectionConfig, client)) {
        connectionConfig = dbConnectionConfig[client];
      }

      /**
       create a DB client with the given config. Even you can persist the DB connection is a hashMap such that you don't need to establish a new connection every time.
      **/

      const dbSession = new DbClient(connectionConfig);

      // put the dbSession in a context such that it can be used by the resolver.

      context.dbSession = dbSession;
      return resolve.call(this, source, otherArgs, context, info);
    };

    field.type = GraphQLString;
  }
}
// UserResolver.js

const UserResolver = {
  Query: {
    users(async (parent, args, context, info) => {
      const dbSession = context.dbSession;
      // use the dbSession to fetch the results. Note, here resolve need not to know about the db client details.

      return dbSession.findAll();
    }
}


const resolvers = merge(
  UserResolver
);

const server = new ApolloServer({
  typeDefs,
  resolvers,
  schemaDirectives: {
    date: DbClientDirective
  }
});

server.listen().then(({ url }) => {
  console.log(`? Server ready at ${url}`);
});

Теперь вы можете передать клиентский аргумент в запрос пользователя, чтобы указать, какая БДподключение для использования.

Пример 1 - это будет использовать DEFAULT в качестве клиента БД

query {
   users {
      name
      userId 
   }
}

Пример 2 - это будет использовать DB_CLIENT_1 в качестве клиента БД

query {
   users(client: DB_CLIENT_1) {
      name
      userId 
   }
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...