JBooker10 / node-iex-cloud

node wrapper for iex-cloud
20 stars 5 forks source link

`batchSymbols` fails on 3rd call #8

Closed leedavidcs closed 4 years ago

leedavidcs commented 4 years ago

Hi.

When calling batchSymbols, I get an error: Error: Not Found when it is invoked for the 3rd time. This does not happen for single symbols using symbol.

When overwriting fetch to output the request info, I see that the 3rd request has a bad url.

const debugFetch = (info) => {
    console.log(info);
    return fetch(info);
};

const iex = new IEXCloudClient(debugFetch, {...

Output (3 urls are logged at the top):

https://sandbox.iexapis.com/stable/stock/market/batch/batch?symbols=googl&types=balance-sheet,book,cash-flow,ceo-compensation,company,earnings,estimates,financials&range=1m&last=0&token=*****
https://sandbox.iexapis.com/stable/stock/market/batch/batch?symbols=googl&types=fund-ownership,income,largest-trades,logo,news,options,peers,price&range=1m&last=0&token=*****
https://sandbox.iexapis.com/stable/stock//batch?types=quote&range=1m&last=0&token=*****
Error: Not Found
    at IEXRequest.<anonymous> (/home/leedavidcs/projects/app_root/node_modules/node-iex-cloud/lib/request.js:128:35)
    at step (/home/leedavidcs/projects/app_root/node_modules/node-iex-cloud/lib/request.js:32:23)
    at Object.next (/home/leedavidcs/projects/app_root/node_modules/node-iex-cloud/lib/request.js:13:53)
    at fulfilled (/home/leedavidcs/projects/app_root/node_modules/node-iex-cloud/lib/request.js:4:58)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:94:5)

This seems to only happen when the 3rd call is made from the same IEXCloudClient instance. So, I can work around this by creating a new IEXCloudClient instance every batch request.

JBooker10 commented 4 years ago

Thanks for noticing, I'm having trouble reproducing this issue. Based on the request mentioned above, it seems like you are chaining the methods as shown below and making the calls sequentially. I've tried to reproduce the behavior and it's working as expected. Could you show me your code on the very last call? Appreciate the find.

iex
  .batchSymbols("googl")
  .batch()
  .balanceSheet()
  .book()
  .cashFlow()
  .ceoCompensation()
  .company()
  .earnings()
  .estimates()
  .financials()
  .range()
  .then(res => console.log(res));

iex
  .batchSymbols("googl")
  .batch()
  .fundOwnership()
  .income()
  .largestTrades()
  .logo()
  .news()
  .options()
  .peers()
  .price()
  .range()
  .then(res => console.log(res));

iex
  .symbol()
  .batch()
  .quote()
  .range("1m", 0)
  .then(res => console.log(res));
leedavidcs commented 4 years ago

@JBooker10 Thanks for the quick reply.

This isn't my exact code, but I've reproduced the error here minimally:

import fetch from "isomorphic-unfetch";
import { IEXCloudClient } from "node-iex-cloud";

const debugFetch = (requestInfo: RequestInfo) => {
    console.log(requestInfo);

    return fetch(requestInfo);
};

const iex = new IEXCloudClient(debugFetch, {
    sandbox: true,
    publishable: "***",
    version: "stable"
});

const doTheThing = () => {
    const batch1 = iex.batchSymbols("googl").batch().company();
    const batch2 = iex.batchSymbols("googl").batch().company();
    const batch3 = iex.batchSymbols("googl").batch().company();

    Promise.all(
        [batch1, batch2, batch3].map((batch) => batch.range())
    ).then(() => process.exit(0));
};

doTheThing();

Interestingly, it seems like this crashes on the 2nd call. However, it seems to work when I do not wrap it all within a Promise.all, and await them individually.

I guess I should a void making multiple requests at the same time (also since IEX Cloud has request limits).

Should this be documented somewhere instead?

JBooker10 commented 4 years ago

If you chain the .range() method on the variables themselves instead of when mapping them out this should work with no side effects. But yes it does return a 429 Too Many Requests when you're making many request at a time.

example:


const doTheThing = () => {
  const batch1 = iex
    .batchSymbols("googl")
    .batch()
    .company()
    .range();
  const batch2 = iex
    .batchSymbols("googl")
    .batch()
    .company()
    .range();
  const batch3 = iex
    .batchSymbols("googl")
    .batch()
    .company()
    .range();

  Promise.all([batch1, batch2, batch3].map(batch => batch)).then(() =>
    process.exit(0)
  );
};
leedavidcs commented 4 years ago

@JBooker10 Gotcha. Well, I'm good to resolve this issue in that case. Thanks!