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
feat: introduce declarative function signatures #114
Conversation
Allow expressing the function signature type configuration through code instead of through `FUNCTION_SIGNATURE_TYPE` env var.
|
||
$invoker = new Invoker($target, $signatureType); |
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.
Do we not need to pass in the $signatureType
to preserve backwards compatibility here? ie GCFv1 customers today might be using non-declarative cloudevent functions in PHP
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.
It still respects the env var, I just moved it from being read here to being read within invoker.php
so I could test it properly. router.php
is hard to test because it's being used as script instead of a just declaring a function or class.
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.
There are a few reasons why this is not a good idea
- This breaks backwards compatibility
- The decision to inject the environment variable was intentional. This is a best practice (see dependency injection), as it keeps the logic of where the value comes from (e.g. the environment) separate from the class which uses the value (e.g. the Invoker)
- Having the value be injectable is more testable, as you can test the class without having to mess with environment variables.
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.
Please do not tag a release until we resolve the backwards compatibility breaking issues
|
||
$invoker = new Invoker($target, $signatureType); |
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.
There are a few reasons why this is not a good idea
- This breaks backwards compatibility
- The decision to inject the environment variable was intentional. This is a best practice (see dependency injection), as it keeps the logic of where the value comes from (e.g. the environment) separate from the class which uses the value (e.g. the Invoker)
- Having the value be injectable is more testable, as you can test the class without having to mess with environment variables.
public function __construct(callable $function, bool $marshalToCloudEventInterface = false) | ||
{ | ||
$this->marshalToCloudEventInterface = $marshalToCloudEventInterface; | ||
parent::__construct($function); |
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 not optimal because you're changing the constructor of FunctionsWrapper
, which has a $signature
parameter that is now unavailable.
This is breaking backwards compatibility and also making that parameter unavailable to users.
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.
I can add back the $signature
optional parameter.
{ | ||
$signatureType = getenv('FUNCTION_SIGNATURE_TYPE', true) ?: 'http'; |
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.
It was an intentional choice to have the environment variable passed in. Injecting the environment variables is a better practice, easier to test, more reliable than having the logic exist in the Invoker
itself. Also, this breaks backwards compatibility, if users were calling the Invoker
directly. I think we need to roll back this change.
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 issue I ran into was that I couldn't test CloudEvent functions properly with this code in router.php
, because it is just a script and I couldn't figure out how to pass it a CloudEvent request.
I can add back the signature type parameter here, and then only read the env var if it's missing. That way it is not a change to the constructor?
Can we mark these classes as internal? In general, I don't think we want people to be using these directly.
|
||
private function __construct() | ||
{ | ||
} |
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.
For more idiomatic PHP, this should be removed
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.
Sounds good!
return Registry::$fnRegistry[$name][0]; | ||
} | ||
|
||
public static function getFunctionHandle(string $name) |
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.
In general static methods are something we try to avoid. It would be better to make these methods instance methods, and instantiate the registry at runtime.
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.
Ah ok, we can use a singleton pattern instead.
Allow expressing the function signature type configuration through code
instead of through
FUNCTION_SIGNATURE_TYPE
env var. This meansthe
FUNCTION_SIGNATURE_TYPE
var can be omitted when deployinga function with a declarative function signature.
The new signature also changes to using the official CloudEventInterface from the CloudEvents SDK instead of the Function Framework's custom class.
The primary difference is
$cloudevent->getTime()
returns aDateTime
instead of astring
. This can be converted back to a string as follows:Define your Function
index.php
Run your function