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

Add configuration option for batch keys that are a Set rather than $ReadOnlyArray #265

Merged
merged 6 commits into from
May 17, 2021

Conversation

kkellyy
Copy link
Contributor

@kkellyy kkellyy commented May 13, 2021

Problem

There are cases where a batch key might not be an Array collection type, but rather a Set type. In these cases, flow needs to define the type of newKey differently. Currently, a function that defines a batch endpoint with a Set batch parameter will fail.

Solution

Allow users to set isBatchKeyASet: true to change the way the generated dataloader determines the type for newKey to work with a Set.

Here is a simple example of this typing working in the flow repl. This solution relies on Set<T>.has(), which accepts a parameter of type T.

Verification

make test passes. I've added some unit tests to verify it is behaving properly.
I also added a contrived example to examples/swapi.

@kkellyy kkellyy requested review from magicmark and gyDBD May 13, 2021 23:05
Copy link
Contributor

@gyDBD gyDBD left a comment

Choose a reason for hiding this comment

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

testing in swapi looks good!

schema.json Outdated
@@ -93,6 +93,10 @@
"isResponseDictionary": {
"type": "boolean",
"description": "(Optional) Set to true if the batch resource returns the results as a dictionary with key mapped to values (instead of a list of items). If this option is supplied `reorderResultsByKey` should not be. Default: false"
},
"uniqueBatchKeys": {
Copy link
Contributor

@gyDBD gyDBD May 14, 2021

Choose a reason for hiding this comment

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

uniqueBatchKeys confused me a little bit. (uniqueBatchKeys makes me feel I should input what's the unique batch keys, not whether batchkey is unique.) would something like isBatchKeyASet be better?
and I like the description of commaSeparatedBatchKey a lot, so maybe we could follow that and do

"description": "(Optional) Set to true if the interface of the resource takes the batch key as a set (rather than an array as is more common). Default: false" 

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great suggestion. I was really struggling with what to call this option haha. I like yours better for sure.

@kkellyy kkellyy requested a review from gyDBD May 14, 2021 17:20
Copy link
Contributor

@gyDBD gyDBD left a comment

Choose a reason for hiding this comment

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

LGTM, cc @ATRAN2

Comment on lines 53 to 60
let newKeyType = `${resourceConfig.newKey}: $ElementType<$PropertyType<${resourceArgs}, '${resourceConfig.batchKey}'>, 0>`;

if (resourceConfig.isBatchKeyASet) {
newKeyType = `${resourceConfig.newKey}: ${getNewKeyTypeFromBatchKeySetType(
resourceConfig.batchKey,
resourceArgs,
)}`;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

may be worth a comment explaining "batchKey could be part of an array or a set" or something to explain what's going on here in the default / branching case?

return `\
$Call<
ExtractArg,
[$PropertyType<$PropertyType<${resourceArgs}, '${batchKey}'>, 'has'>]
Copy link
Collaborator

Choose a reason for hiding this comment

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

doesn't has return a boolean rather than the underlying value?

https://github.com/facebook/flow/blob/388ea046bb7ca6f64fda17637daae8a3440ae0b2/lib/core.js#L600

slightly confused here sorry!

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, finding a solution here wasn't easy/obvious, even when I was pairing on it with @ATRAN2. This is extracting the arg type of has() (T) similarly to how the code extracts the batchKey arg type to the batch resource function (ie Set<T> in this case) itself.

Copy link
Collaborator

Choose a reason for hiding this comment

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

ohhhh this is the type of the newKey, sorry i'm being dumb

looks good, nice approach :) 👍

Copy link
Collaborator

@magicmark magicmark left a comment

Choose a reason for hiding this comment

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

looking good!

Could you build the swapi examples and commit the newly generated files?

(should add this step to the contribution guide)

https://github.com/Yelp/dataloader-codegen/tree/master/examples/swapi

would like to see the generated output of this

schema.json Outdated
},
"isBatchKeyASet": {
"type": "boolean",
"description": "(Optional) Set to true if the interface of the resource takes the batch key as a set (rather than an array). Default: false"
Copy link

Choose a reason for hiding this comment

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

Might help to also note in the description what swagger flag can cause this to need to be True, so maybe a
when uniqueItems: true in the swagger spec

@kkellyy
Copy link
Contributor Author

kkellyy commented May 14, 2021

looking good!

Could you build the swapi examples and commit the newly generated files?

(should add this step to the contribution guide)

https://github.com/Yelp/dataloader-codegen/tree/master/examples/swapi

would like to see the generated output of this

It already is, no? Or is there more I needed to check-in?

@magicmark
Copy link
Collaborator

It already is, no? Or is there more I needed to check-in?

ah missed this, thanks!

We don't really have tests for the flow types here I don't think - but we can use the swapi example. Could we add a resolver that fetches something using this new option, and verify that flow doesn't blow up?

thanks!!

@kkellyy kkellyy requested a review from magicmark May 14, 2021 22:43
@kkellyy
Copy link
Contributor Author

kkellyy commented May 14, 2021

It already is, no? Or is there more I needed to check-in?

ah missed this, thanks!

We don't really have tests for the flow types here I don't think - but we can use the swapi example. Could we add a resolver that fetches something using this new option, and verify that flow doesn't blow up?

thanks!!

Done! also dataloader-codegen/examples/swapi (unique_set_batchkeys) $ node_modules/.bin/flow check returns 0 errors, so flow seems happy. If I switch to a string, it errors properly as well:

Error ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ swapi-server.js:81:74

Cannot call swapiLoaders.getFilms.load with object literal bound to key because string [1] is incompatible with
number [2] in property film_id.

     swapi-server.js
     78│         }
     79│
     80│         async title() {
 [1] 81│             const response = await swapiLoaders.getFilms.load({ film_id: 'foo' });
     82│
     83│             if (response instanceof Error) {
     84│                 return response;

     swapi.js
 [2] 81│     getFilms: ({| film_ids: Set<number> |}) => Promise<$ReadOnlyArray<SWAPI_Film>>,

Found 1 error

@kkellyy
Copy link
Contributor Author

kkellyy commented May 14, 2021

Oh also output from swapi-server.js:

dataloader-codegen/examples/swapi (unique_set_batchkeys*) $ node build/swapi-server.js                                                130 ↵
{
    "data": {
        "alderaan": {
            "name": "Alderaan",
            "climate": "temperate",
            "diameter": "12500"
        },
        "hoth": {
            "name": "Hoth"
        },
        "dagobah": {
            "name": "Dagobah"
        },
        "meh": {
            "title": "A New Hope",
            "episodeNumber": 4,
            "director": "George Lucas"
        },
        "theBest": {
            "title": "The Phantom Menace",
            "episodeNumber": 1,
            "director": "George Lucas"
        }
    }
}

Copy link
Collaborator

@magicmark magicmark left a comment

Choose a reason for hiding this comment

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

Tidy work!

Love the links to tryflow and flowdefs in the PR description, helped me a lot 👍

@magicmark
Copy link
Collaborator

Could you update the docs too? https://github.com/Yelp/dataloader-codegen/blob/HEAD/API_DOCS.md

Copy link
Collaborator

@magicmark magicmark left a comment

Choose a reason for hiding this comment

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

lg2m!

@kkellyy kkellyy merged commit 0aaa906 into Yelp:master May 17, 2021
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.

4 participants