简体   繁体   中英

Heroku Postgres connections increase without reuse

First time setting up Heroku's postgres service with the "free tier". I use heroku to host a koa server with pg database. The server communicates over knexjs to the database. I'm not sure if I am using knexjs incorrectly because everytime I run a query, it creates a new connection as seen via Heroku's dashboard and eventually run out of connections. Also, I noticed they were internal ips (ie 10.1...) that were primarily consuming my connections. If I kill them, then my connections drop to 0. My knex query is as follows:

For cache purposes, I have a class initiated on each connection (only useful if there were multiple queries run during the same client request).

import knexDefault from "knex";
import { development, production } from "../ConfigKnex";
import { ENVTRANS } from "./Consts";

const { ISDEV } = ENVTRANS;
export class KnexCache(){
  knex = knexDefault(ISDEV ? development : production);
  transaction = this.knex.transaction.bind(this.knex);
  constructor(private cache: Map<string, any> = new Map()) {}
  private CacheIt(action: ActionTypes, table: string, props: any, fn: any) {
        let tm = this.cache.get(table);
        if (!tm) {
            tm = new Map<string, any>();
            this.cache.set(table, tm);
        }
        const key = `${action}|${JSON.stringify(props)}`;
        let res = tm.get(key);
        if (res) return res;
        res = fn();
        tm.set(key, res);
        return res;
    }
  async SelectAsync<T>(
        table: string,
        where: Partial<T>,
        db = this.knex,
    ): Promise<T[]> {
        return this.CacheIt("SelectAsync", table, { where }, () =>
            db(table).where(where).select(),
        );
    }
  ...
}

I use GraphQL (hence ApolloServer) to create a new KnexCache on each connection.

const server = new ApolloServer({
    typeDefs,
    resolvers,
    // schemaDirectives,
    debug: ISDEV,
    tracing: ISDEV,
    playground: {
        settings: {
            "request.credentials": "include",
        },
    },
    context: async (context) => {
        context.k = new KnexCache();
        return context as Context;
    },
});

And call it in my resolver

export const resolvers = {
  Query: {
    GetData: async (p, a, c, i) => {
      const { k } = c;
      return k.SelectAsync<TABLETYPE>("TABLENAME", { id: "someId" });
    },
  },
};

Everything works but am I improperly using knex in such a way that it keeps the connections alive and/or preventing connection reuse? How can "fix" the code to properly reuse connections from knex's connection pool?

I figured it out. Since I was creating a new class for each connection, a new knex connection would be established for each visitor. I tried making the knex properties static but apparently in javascript, static properties can only be accessed by static methods... Thus, I moved the knex properties outside of the class and converted them into export const .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM