functions-framework-php icon indicating copy to clipboard operation
functions-framework-php copied to clipboard

Leverage the Symfony Runtime component

Open Nyholm opened this issue 3 years ago • 2 comments

Hey.

Sorry for a long post. The short version is that I think we should consider leveraging the Symfony Runtime component.


I do like the idea to run your application “serverless”. Maybe a big fat monolith isn’t the prime application but many small micro services are perfect for this kind of “hosting”.

As you may know I’m heavily invested in Symfony and have been working a lot with Bref. I am also the person that suggested that Google’s php API SDK should use HTTPlug back in 2016 (when it was way too early to know if HTTPlug was cool or not). And here I am suggesting that this library should use another brand new tool: Symfony Runtime component.

What I can see, this library is trying to solve a few things already solved by the Runtime component.

  1. Find the function to execute
  2. Work both on local development and in production
  3. Support a few different CloudEvents + HTTP

I can also see some drawbacks with the current architecture. (If they are big or small can be discussed, but I prefer to leave that out from this discussion)

  • A. It is coupled to guzzlehttp/psr7 (I maintain that package, but I still prefer to not couple to it)
  • B. There is a bit of logic to create PSR-7 requests and to emit them. This is not related to Google
  • C. It is not easy to avoid using PSR-7, i.e. use Symfony HTTP or just to use no request objects.

Symfony Runtime

The Runtime component is new in 5.3. It is currently in a beta release and will be released in May 2021. All new Symfony 5.3 applications will use this component. One feature is to make the application decoupled from the global scope which would make the application super portable.

The component will find the script to execute and run it (1). It will also make sure you can use normal Apache/Nginx locally and some other cool runtime in production (2) without any changes to the application.

If you are updating from a native app or Symfony 5.2 you may just wrap your front controller in an anonymous function and you are ready to go.

Proof of concept

I’ve created a proof of concept package that is working just like this library: https://github.com/php-runtime/google-cloud

As you notice, there is very little code. It is basically just 200 lines plus the CloudEvent value objects. This code is the only thing that is “Google specific”. This makes the google package easier to maintain and less prone to have bugs.

This package (and the runtime component) addresses the drawbacks I pointed out (A, B, C) and still provides all the features (1, 2, 3). An extra bonus is that it will work out of the box for any Symfony 5.3 application. See the readme for details. There is also no extra config to enable use of CloudEvents.

The negative things

If this library were to move to use Symfony Runtime and towards something that is similar to the proof of concept, there are some things that may be considered negative.

Issue: One may think that you don’t want to have “Symfony” in your vendor folder if you are building a small micro service.

Comment: The Runtime component has about 750 lines of code, that should be compared to Guzzle PSR-7 which has over 3300 lines. Symfony is also a great choice for building small and fast applications. A Symfony application does not need to be big and full of features. Most of my applications do not have forms and or the security component.

Issue: One may think this library will be harder to install and use if the users are given too many options (i.e. when using PSR-18 the user has to select and install the HTTP client themselves). Could we run something out of the box?

Comment: Installing php-runtime/google-cloud will make sure the application work out of the box for both Symfony 5.3 applications and native applications. If you want to use Laravel or PSR-7 then yes, you have to install one additional package. That package will register automatically, no configuration required.

Issue: We want full control over our library and cannot trust Symfony to keep supporting features that are critical to our users.

Comment: That is understandable, but very defensive. I understand this attitude towards most packages/organizations, but Symfony has a long history of being stable software with release schedules, at least monthly bug fix releases and up to 6 years of security fixes. Compare Symfony with Guzzle and you almost have two opposites.

Issue: The Symfony Runtime component is “experimental”.

Comment: Yes, and it will be until November 2021. This means that it does not have the strict BC promise as other components have. We do our best to avoid all BC breaks, but if we find a flaw that cannot be fixed without a BC break we are allowed to still fix that flaw.


The Runtime component is very unknown at the moment. Mostly because it is not released and there has been very little talk about it so far (it is about to change). But I do believe this is going to be widely adopted in the PHP world, not only for Symfony applications. Mostly because it is super helpful for users when they want to try Google Cloud, React, RoadRunner, Bref, Swoole etc.

Nyholm avatar May 15 '21 07:05 Nyholm

Hi @Nyholm! Good to hear from you as always. Thanks for your work on this, and for posting such a thorough comment. I am curious if other users find this to be a big win. If so, I will be more incentivised to use it. I look forward to experimenting with the runtime you provided!

Overall I think it's an awesome concept and really appreciate you taking the time to write up a prototype. We are already in beta, so BC breaking changes are discouraged. When we go GA, which will happen before the Symfony Runtime moves from experimental, BC breaking changes will be impossible. So we'll have to keep that in mind if this is to be used.

Out of the three advantages [A, B, C], I agree with [B]. Ideally the creation/emission of PSR-7 requests would not be part of this library. But of the other two advantages, [A] feels like switching out one HTTP library for another, and [C] is not something I see as a need. Of the issues listed in "The negative things", I had many of the same thoughts. Specifically, we want minimal dependencies and we want full control. Also, we cannot use the dependency while it is in an experimental stage.

Another issue I see is the lack of a function name. Your example uses anonymous functions, but the other GCF languages map the function's deployment name to the language function name. This allows users to have multiple functions in a single file (not a huge advantage) and also helps make debugging easier. We will need this to follow the existing interface if we're to use it. I assume that's something we could work around, however.

If anyone else is using this and would find it useful, please +1 the issue description or comment here that you'd like to see it! I am very curious what the community response is here!

bshaffer avatar May 19 '21 21:05 bshaffer

Thank you. I'm happy that you will keep the Runtime component on your mind. I'll try to answer a few things that I feel should be commented:

[A] feels like switching out one HTTP library for another

Not really. Im not suggesting to add any HTTP library. =)

Specifically, we want minimal dependencies and we want full control. Also, we cannot use the dependency while it is in an experimental stage.

I understand that. As a maintainer of both Symfony and Guzzle I would recommend to use Symfony as a dependency because:

  • It is a team of 10+ people that is actively maintaining it every week. (+ all the "normal" contributors)
  • Solid release plan and security fixes
  • They are using LTS releases
  • The dependency we are talking about is less than 1/3 of guzzle in size

Another issue I see is the lack of a function name.

Interesting. I saw this as a big win. When I write an application for AWS Lambda, I have few front controllers. One for handle S3 events, one for SQS and then 3 different php files to handle my 3 different routes. Ie, no environment variable that magically maps to a function name.

If anyone else is using this and would find it useful, please +1 the issue description

Great idea. Please do.

Give it a month or two for people to start using it. PHP annotated monthly mentioned the Google runtime yesterday and I've already got a few private email asking me about it and how I used GCF to deploy applications. I need to blog about it and write more blog posts to help users. (ie, sessions, warmup and read-only filesystem etc)


Unrelated side note: We are soon to release guzzehttp/psr7 v2.

Nyholm avatar May 21 '21 11:05 Nyholm

It's been a few years since this issue was opened, because the framework is being used in Cloud Functions as a GA offering there's a larger inherent risk, especially as the framework has been stable for so long that Hyrum's law may be taking effect.

We're happy to re-assess if anyone is passionate about this and is running into production limitations without an abstraction layer, but until then I'm going to mark this one as not planned.

Thanks!

josephlewis42 avatar Sep 27 '23 20:09 josephlewis42