Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How are DataLoader promises deferred so that batching can occur? #1423

Open
sangaline opened this issue May 25, 2022 · 3 comments
Open

How are DataLoader promises deferred so that batching can occur? #1423

sangaline opened this issue May 25, 2022 · 3 comments

Comments

@sangaline
Copy link

I'm using SyncExecutor from graphql-core and ImmediateScheduler from the promise library with graphene v2.1.8. My understanding is that these should synchronously and immediately execute any promises when they are created. If I use a dataloader outside of graphene resolvers, I see evidence of this immediate execution:

from promise import Promise
from promise.dataloader import DataLoader

def batch_load_fn(keys):
    print('Keys:', keys)
    return Promise.resolve(keys)

loader = DataLoader(batch_load_fn=batch_load_fn)
loader.load_many([1, 2, 3])
loader.load(4)
loader.load(5)
loader.load(6)

outputs:

Keys: [1]
Keys: [2]
Keys: [3]
Keys: [4]
Keys: [5]
Keys: [6]

The batch_load_fn is called individually for each key with no batching. When I run the same code inside of a graphene resolver, I get

Keys: [1, 2, 3, 4, 5, 6]

which indicates that the promises aren't executing immediately and batching does happen. This is obviously desirable, and the point of using dataloaders in the first place, but I'm having trouble understanding the mechanism by which it is happening.

What is graphene or graphql-core doing to prevent the immediate synchronous execution of these promises so that dataloader batching can occur?

@vineeth-cnbr
Copy link

vineeth-cnbr commented Jan 20, 2023

Was there any resolution for this issue?

@vineeth-cnbr
Copy link

I realized my issue was that my dataloader was being re-initialised in the middleware every time a new resolver was called. Used this to resolve that issue and that worked

@lzhoucs
Copy link

lzhoucs commented Nov 18, 2023

@sangaline I ran into similar problem recently and it seems if we use the dataloader outside of graphene resolvers, we need to wrap the operations inside a function, and then chain it to a promise if we want the batch to work properly (called once with all arguments instead of individually with each argument). Something like this worked for me:

def fn(arg):
  loader = DataLoader(batch_load_fn=batch_load_fn)
  loader.load_many([1, 2, 3])
  loader.load(4)
  loader.load(5)
  loader.load(6)

Promise.resolve(None).then(fn)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants