skip to Main Content

I’m creating a subclass of the NodeJS http.Agent to get rid of the queuing behavior when it has reached the socket limit. I’ve overridden addRequest to track the number of concurrent requests per target, rejecting requests when no capacity is available to handle it.

The issue is that I also need to extend https.Agent, which is itself a subclass of http.Agent, with the same behavior. If I create an addRequest function and assign it to the prototype of my subclasses of each agent, I’m unable to reference super. Is there a reasonably DRY way to do this?

The following code is excessively simple, but hopefully illustrates the problem.

class Original {
  addRequest(req) {
    console.log(req);
  }
  /* other stuff */
}
class ExtendedOriginal extends Original {
  /* various extensions of other stuff */
}

/* Custom */
class ConcurrencyLimitedOriginal extends Original {
  addRequest(req) {
    if (this.canAddRequest(req)) {
      super.addRequest(req); // super ref! Can only exist as a method, not a function
  }
  canAddRequest(req) {
    /* various logic */
    return true;
  }
}

class ConcurrencyLimitedExtendedOriginal extends ExtendedOriginal {
  /* DRY way to have same added logic as ConcurrencyLimitedOriginal? */
}

2

Answers


  1. Chosen as BEST ANSWER

    I solved this without mixins, due to issues with getting that approach to work discussed in comments. Instead, I took advantage of Class Expressions to instead more easily define two different subclasses with separate parentage but otherwise identical implementations:

    const createConcurrencyLimitedAgentClass = (parentAgent) => 
      class extends parentAgent {
        constructor(options) {
          super(options);
          // other init logic
        }
        // other method overrides
      };
    
    const ConcurrencyLimitedHttpAgent = createConcurrencyLimitedAgentClass(Agent);
    const ConcurrencyLimitedHttpsAgent = createConcurrencyLimitedAgentClass(HttpsAgent);
    

    I'm not sure I'd call it the cleanest looking code ever, but I'm not convinced that there is a clean way to solve this given the existing class structure. Resulting structure from this approach looks like the following:

        http.Agent
        |        |
        |        https.Agent
        |        |
        |        ConcurrencyLimitedHttpsAgent
        |
        ConcurrencyLimitedHttpAgent
    

    The two concurrency limiting agents are identical in implementation except they reference a different super.


  2. I’m creating a subclass of the NodeJS http.Agent to get rid of the queuing behavior when it has reached the socket limit

    Don’t create a subclass. Just use the existing class and pass the appropriate options, in particular {maxTotalSockets: undefined}.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search