Skip to content

Middleware via hooks in the "round-trip" of a field #2602

Closed
@lancelafontaine

Description

@lancelafontaine

This issue is part-feature request and part-inquiry as to how this pattern can best be achieved:

When an argument is passed to a field, have the argument's value be accessible to only the "sub-fields" in the subsequent tree of fields that are queried from that point.

Here's an example of having a configuration value like a session ID be accessible for every field under the one in which the session is provided.

query problemDomain {
    a(configurationValue: "1"){ # before hook to set configuration value
        aa { # is aware of configurationValue "1"
            ab # is aware of configurationValue "1"
        }
        ac # is aware of configurationValue "1"
    } # after hook to unset configuration value
    b { # nothing to set
        ba { # has no configurationValue
            bb # has no configurationValue
        }
        bc # has no configurationValue
    } # nothing to unset
    c(configurationValue: "2") { # before hook to set configuration value
        ca { # is aware of configurationValue "2"
            cb # is aware of configurationValue "2"
        }
        cc # is aware of configurationValue "2"
    } # after hook to unset configuration value
}

This example relies on this propagation occurring and having a trigger or hook to stop the propagation at the end of a field's "round-trip" and unset the configuration value.

I've found this requirement conceptually similar to middleware, a useful pattern often seen in the Node.js and Elixir worlds to avoid manipulating global mutable states from any arbitrary point within the request. I can imagine a similar concept being applied here, but instead of at the request level, at the field/resolver level. Some of the use cases off the top of my head:

  • Session management (see above)
  • Logging
  • Benchmarking
  • Prefetching and caching dependent objects
  • Parsing inputs and context
  • Authentication

graphql-ruby already offers field extensions as a concept, which are similar in nature to what this is attempting to solve, but the after_resolve hook only triggers immediately after a field's resolver, not on the field's "round-trip".

From what I can tell, without a primitive, the only option for enabling this sort of pattern is to change the backing model of all GraphQL objects to be a decorator which can manually propagate the argument value through every resolver. Even then, this approach only solves the session management / configuration value use case, and doesn't address any case which relies on an explicit after_round_trip hook.

Hoping to get some feedback on the general pattern, whether there are any other viable options for enabling such use cases, and whether such a primitive would make sense alongside constructs like field extensions. Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions