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

improvement: add async?/1 to source protocol #146

Merged
merged 4 commits into from
Oct 31, 2022

Conversation

zachdaniel
Copy link
Contributor

@zachdaniel zachdaniel commented Oct 12, 2022

In order to make dataloaders easier to use in test, I've added an async?/1 function to the souurce protocol. In async_safely/3 (which is now async_safely/4) we default to async?: true meaning this should be backwards compatible with any direct usage of that function.

I've also added what would seem to me to be the proper default behavior for ecto and KV, which is that ecto will run synchronously if the repo is in a transaction, and KV is configurable at startup.

Feel free to tear it apart. This does seem pretty necessary for writing tests against absinthe in general, though :)

This is slightly orthoganal to #134 because its per-source

Addresses some if not all of #129

@zachdaniel
Copy link
Contributor Author

@benwilson512 if you have a few to look at this/let me know what it would take to get this over the line it would be great.

Copy link
Contributor

@benwilson512 benwilson512 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm 💯 with the need to do this. However I think this requires a major version bump due to the introduction of a new protocol fun.

Returns wether or not the source should be running synchronously or asynchronously
"""
@spec async?(t) :: boolean
def async?(source)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So my only concern here is that this is functionally a breaking change right? Any other 3rd party protocol impl will error now that this is here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, absolutely. that is the main reason this was opened as a draft actually. There may be a way around it, which would cause them simply to warn instead of raise, which would be to do something like:

if function_exported?(Dataloader.impl_for(module), :async?, 1) do
  ....
end

But that also adds a concrete performance overhead for other users. To prevent breaking this in the future again, if additional options are needed, we could make it options/1 instead of async?/1 that way if more options are added we don't need a major release.

def options(dataloader) do
  [
    async?: false
  ]
end

@benwilson512
Copy link
Contributor

Also can you rebase off of main to remove the then ?

@zachdaniel
Copy link
Contributor Author

@benwilson512
Copy link
Contributor

Ah apologies it got removed elsewhere. With the release of 1.14 we can probably move supported versions up to ~> 1.12

@zachdaniel
Copy link
Contributor Author

Yeah, that makes sense! I don't think me changing the matrix in my PR will change what builds for the PR (IIRC it uses main's github.yml file not the PR's github file, to avoid things like exfiltrating secrets). I'm happy to make that change in this PR, but it might make sense as a separate PR.

Do we feel like requiring a major version update is acceptable for this? Or do we want to find a more creative solution?

@zachdaniel
Copy link
Contributor Author

Hey @benwilson512 so if a major version number is out of the question, how about allowing application configuration to determine async? Its unideal because I'd have to ask my users to put this in their application env when testing with AshGraphql, but would be a potential compromise. i.e Application.get_env(:dataloader, dataloader, async?) (I don't think we have their otp app here to look up the config there?)

@benwilson512
Copy link
Contributor

@zachdaniel OK here is my current thinking. I am going to make a PR that basically just has dataloader accept an async: false option that forces everything to be async false. Then folks can update their Dataloader.new calls to set that option based on repo.in_transaction?. This will be the backwards compatible patch version solution.

THEN we'll go ahead and get this PR across the finish line and this will be the 2.0 version that can handle async on a more granular level depending on the source.

Thoughts?

@zachdaniel
Copy link
Contributor Author

Sounds like a plan to me :D

@benwilson512
Copy link
Contributor

I think from a code standpoint, I'm gonna go ahead and merge this into master, set the 2.0-pre version, and then checkout v1 and edit the code back to get rid of the protocol impl. That way your code gets attributed properly instead of me copying and pasting 85% of what you wrote.

@benwilson512 benwilson512 marked this pull request as ready for review October 31, 2022 03:00
@benwilson512 benwilson512 merged commit da57acf into absinthe-graphql:master Oct 31, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants