-
Notifications
You must be signed in to change notification settings - Fork 177
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
[BREAKING]: Change internal layers stack to be value-based instead of type-based #789
Merged
Commits on Mar 18, 2022
-
Change internal layers stack to be value-based instead of type-based
This is very proof-of-concept currently, but wanted to put the code up to get initial feedback/ideas. Here's the gist: * I define 3 abstract subtypes of `Layer` in the Layers module: `InitialLayer`, `RequestLayer`, and `ConnectionLayer`; these correspond to the types of arguments the layer would receive when overloading `request`; `InitialLayer` => `request(method, url, headers, body), `RequestLayer` => `request(url, req, body)`, and `ConnectionLayer` => `request(io, req, body)`. I feel like these are useful abstract types to help distinguish the different _kinds_ of layers based on the arguments they receive in different parts of the overall stack. I feel like it hopefully also solves the "how do I insert my layer in the appropriate level of the stack" because you just pick which abstract layer to subtype * Custom layers are then required to: * be concrete types * must subtype one of the 3 abstract layer types mentioned * must have a constructor of the form: `Layer(next::Layer; kw...) * must have a field to store the `next::Layer` argument * must overload: `request(x::MyLayer, args...; kw...)` where `args` will depend on which abstract layer `MyLayer` subtypes * in the overloaded `request` method, it must, at some point, call `request(layer.next, args...; kw...)` to move to the next layer in the stack * the final requirement is the custom layer must overload `Layers.keywordforlayer(::Val{:kw}) = MyLayer` where `:kw` is a keyword argument "hook" or trigger that will result in `MyLayer` being inserted into the stack What I like about this approach so far: * It feels more straightforward to define my own custom layer: pick which level of the stack I want it in, subtype that abstract layer, register a keyword argument that will include my layer, then define my own `request` overload; we can define all the current HTTP layers in terms of this machinery, custom packages could define their own layers and they all are treated just like any HTTP.jl-baked layer * It also feels like it would be easier to create my own custom "http client"; what I mean by this is that I feel like it's common for API packages to basically have their own `AWS.get`/`AWS.post`/`AWS.put` wrapper methods that eventually call `HTTP.get`/`HTTP.post`/etc., but in between, they're adding custom headers, validating targets, and whatever. A lot of that is _like_ a custom layer, but by having your own `AWS.get`/`AWS.post` wrapper methods, you can _ensure_ certain layers are included; and with this approach that's straightforward because they can indeed make their own custom layer as described above, and then just ensure every `HTTP.request` call includes the new keyword argument to "hook in" their custom layer Potential downsides: * Relying on a global keyword registry; i.e. there's potential for clashes if two different packages try to overload `Layers.keywordforlayer(::Val{:readtimeout}) = ...`. Whichever package is loaded last will "pirate" the keyword arg and overwrite the previous method. We could potentially add some extra safety around this by having another `clientenv=:default` keyword and then devs could overload `Layers.keywordforlayer(::Val{:default}, ::Val{:readtimeout}) = ...` but that feels a tad icky. I also don't expect there to be even dozens of total keywords/layers to process, so with that in mind, it also lowers the risk of clash. * The previous layer functionality allowed specifying the _exact_ layer you wanted your custom layer to be inserted before; do we think that level of specificity/granularity is really necessary? I'm kind of going on a gut feel here that what you really want control over is _what kind of args_ your overloaded `request` method will receive and that's what my 3 new abstract layer subtypes aim to solve. So you can pick 1 of 3 different _general_ layers of where your custom layer gets inserted, but don't have control over anything more specific in terms of what layer comes before/after * One thing I noticed is that the current `stack` function actually has some hard-coded logic that checks keyword arguments and _conditionally_ will include layers based on the _value_ of the keyword arg. We could potentially handle that in the proposed scheme by saying that your custom `Layer(next; kw...)` constructor can return the `nothing` value, in which case, no layer will be inserted. That would give, for example, the `TimeoutLayer` the chance to check if the `readtimeout > 0` before returning a `TimeoutLayer` or `nothing`
Configuration menu - View commit details
-
Copy full SHA for 2f17156 - Browse repository at this point
Copy the full SHA 2f17156View commit details -
Configuration menu - View commit details
-
Copy full SHA for 747f725 - Browse repository at this point
Copy the full SHA 747f725View commit details -
Configuration menu - View commit details
-
Copy full SHA for ee3aec8 - Browse repository at this point
Copy the full SHA ee3aec8View commit details -
Configuration menu - View commit details
-
Copy full SHA for ad7c1a7 - Browse repository at this point
Copy the full SHA ad7c1a7View commit details -
Configuration menu - View commit details
-
Copy full SHA for 65188ed - Browse repository at this point
Copy the full SHA 65188edView commit details -
Configuration menu - View commit details
-
Copy full SHA for 3e7677b - Browse repository at this point
Copy the full SHA 3e7677bView commit details -
Configuration menu - View commit details
-
Copy full SHA for 206b847 - Browse repository at this point
Copy the full SHA 206b847View commit details -
Configuration menu - View commit details
-
Copy full SHA for ede2391 - Browse repository at this point
Copy the full SHA ede2391View commit details -
Configuration menu - View commit details
-
Copy full SHA for 4e9b8fe - Browse repository at this point
Copy the full SHA 4e9b8feView commit details -
Another refactor to move layers to a more functional architecture and
drastically reduce the interface requirements
Configuration menu - View commit details
-
Copy full SHA for 60d4d73 - Browse repository at this point
Copy the full SHA 60d4d73View commit details -
Configuration menu - View commit details
-
Copy full SHA for a9473b4 - Browse repository at this point
Copy the full SHA a9473b4View commit details -
Configuration menu - View commit details
-
Copy full SHA for acc0727 - Browse repository at this point
Copy the full SHA acc0727View commit details -
Configuration menu - View commit details
-
Copy full SHA for a0e904c - Browse repository at this point
Copy the full SHA a0e904cView commit details -
Configuration menu - View commit details
-
Copy full SHA for 9aebfea - Browse repository at this point
Copy the full SHA 9aebfeaView commit details
Commits on Mar 22, 2022
-
Co-authored-by: mattBrzezinski <matt.brzezinski@invenia.ca>
Configuration menu - View commit details
-
Copy full SHA for 131e7e5 - Browse repository at this point
Copy the full SHA 131e7e5View commit details -
Co-authored-by: mattBrzezinski <matt.brzezinski@invenia.ca>
Configuration menu - View commit details
-
Copy full SHA for 08e8a6c - Browse repository at this point
Copy the full SHA 08e8a6cView commit details -
Co-authored-by: mattBrzezinski <matt.brzezinski@invenia.ca>
Configuration menu - View commit details
-
Copy full SHA for a317e43 - Browse repository at this point
Copy the full SHA a317e43View commit details -
Co-authored-by: mattBrzezinski <matt.brzezinski@invenia.ca>
Configuration menu - View commit details
-
Copy full SHA for 45e5a5a - Browse repository at this point
Copy the full SHA 45e5a5aView commit details -
Update src/DefaultHeadersRequest.jl
Co-authored-by: mattBrzezinski <matt.brzezinski@invenia.ca>
Configuration menu - View commit details
-
Copy full SHA for 3ea2c8b - Browse repository at this point
Copy the full SHA 3ea2c8bView commit details
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.