-
Notifications
You must be signed in to change notification settings - Fork 3
RFC: Stable API for Google Cloud Function Integration #28
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
base: main
Are you sure you want to change the base?
Conversation
pothos was added to `/example` directory to give a slightly more complex usage visualization and give a more accessible layer into accessing contexts from within query resolvers
update build pipeline to correctly output type definitions, sourcemaps, and cjs/esm modules
update `/example`directory to remove unneeded bundler configuration and conform to new integration API
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The API changes seem pretty reasonable to me. Since this is a pretty significant change, you can consider releasing an alpha
(maybe land this to a next
branch) to try it out and field feedback from others who might be using it.
}; | ||
}>({}); | ||
|
||
builder.queryType(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this line doing? Is .queryType()
effectful?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually from Photos, the schema builder, it's what you call for it to initialize a root Query
on the GraphQL schema.
Honestly, Pothos is only there because I needed something I was familiar with to validate that the context
was being correctly piped through the handler and reaching the field resolver.
We can revert to schema-first approach of the previous example
directory to avoid confusion between what's pertinent to Apollo Server
Co-authored-by: Trevor Scheer <[email protected]>
Co-authored-by: Trevor Scheer <[email protected]>
Co-authored-by: Trevor Scheer <[email protected]>
Co-authored-by: Trevor Scheer <[email protected]>
Co-authored-by: Trevor Scheer <[email protected]>
I'm sorry this has been on hold for so long, that's on me. I meant for this to also include the integration test suites we have on most of other packages, but never got around to actually delving into it. From what I've saw until now, |
All good! The good news is I got the integration tests running against the repo. If you'd like, we can switch to |
We can surely switch to it, have been using it on some personal stuff as well, and it does work well with prerelease publishing flows. |
Summary
This is an exploratory attempt at an API design for
@as-integrations/google-cloud-functions
that addresses the problems with the current implementation and some of the limitations imposed by the Google Cloud Functions Framework.The problem
Considering
@as-integrations/google-cloud-functions
as the library code for server applications, any application trying to use the integration today has to follow a very specific bundling process that involves:functionTarget
either using a hard-coded string or through an environment variable;This all stems from the fact that Google Cloud Functions is incapable of following module imports in order to look for the function signature it should run (I would really like to be wrong about this, but as far as I know, and based on a series of tests trying to see this pattern works, this is what I've observed).
How it works now?
The way this works now is by implementing the function target as a string in the
http
method provided by@google-cloud/functions-framework
internally with the function handler:That string is taken from the
options
object supplied when starting the Apollo Server instance on the server application:When bundled correctly, we end up with something like this:
The current implementation is heavily dependent on setting up custom bundler rules outside library scope to make sure the function signature is "visible" to Google Cloud Functions (the recommended setup from the
/examples
directory).Furthermore, when supplied with an environment variable, we need more custom rules to ensure that the bundler replaces the
process.env
call with the actual value on the bundled code.Proposed solution
When thinking about serverless function composition, we often think about having control over an explicitly declared function handler. This is a pattern currently shared with all major cloud providers that offer FaaS solutions (with the exception of a few differences between function parameters and runtime specificity):
With this in mind, the proposed solution is to export three core functions that will help the developer compose their own handler:
requestProxy
,responseProxy
andstartServer
.This approach extracts away the handler function from inside the library code, giving the developer more control over the handler implementation, while still keeping the amount of setup needed to have a functional instance of Apollo Server to a minimum.
This is an example of the most basic implementation:
Just like in the current library implementation, the server instance is initiated outside the request handler (starting once per container, not once per request). The developer can still pass on custom context properties using the
options
object fromstartServer
.startServer
will now also return an object containing the created server instance, and the provided options. This object is used to pipe theserver
andoptions
back torequestProxy
in order to enable the usage ofexecuteHTTPGraphQLRequest
.Compared to the current, this implementation gives some hard to ignore advantages:
Why is this an "RFC"?
While I believe this is a clear improvement over the current implementation for this specific integration, it is also somewhat dissonant from the current API implementation, which makes this a breaking change.
Since this is an attempt at stabilizing an API proposal before a v1 release of this integration, I would like to request some community feedback from both users and maintainers of other integrations in this space, in order to decide if we should go forward with this approach.
It is also likely that I could have overlooked some fundamental aspect of how Google Cloud Functions works while trying different approaches around the current API implementation. If someone identifies that this is the case, don't hesitate to reach out.