Episode 61: The One Where We Discuss Symfony's HTTP Client with Nicolas Grekas

Wait, Is It Haytch or Aytch?

00:37:25 N/A download


Dave 00:15 Hi and welcome to another episode of That Podcast, I'm Dave.

Beau 00:18 And I'm Beau.

Dave 00:19 And we have a guest with us today. Hi, Nicolas Grekas.

Nicolas 00:23 Hi.

Dave 00:25 Nicolas comes from Symfony. Would you like to give us a little bit of an intro about yourself, Nicolas?

Nicolas 00:29 Yeah, sure. So I work for Symfony since six years. That's how I started doing open source also for Symfony, and since then I did not stop to send you a pull request. So right now I do a lot of contribution daily almost since six years. I used to work for Blackfire as a CTO and now since one year I work for Symfony, the company, as engineer there.

Dave 00:58 Cool. Yeah, I've seen you around quite a lot in my passing interest in Symfony. I know I can't give you any specific examples, but I have a very good impression of sort of the way you conduct yourself on PRs and things like that. Everything seems really well put together, and explained, and I don't know, it just seems like ... I have this good impression of the way you operate. So it's kind of nice to have you on the show.

Dave 01:32 One of the things we wanted to talk about was the HTTP Client component, which is new, I believe it's released now, isn't it? Was it a couple of months ago it came out?

Nicolas 01:41 Yeah, yeah.

Dave 01:42 So do you want to tell us a bit about it?

Nicolas 01:45 Yeah, sure. So I work on this, this winter and we released that two weeks ago or three weeks ago, as stable as part of Symfony 4.3. And so we wanted a client to build a Symfony Mailer. I don't even if you've heard that Symfony Mailer but you know about Swift Mailer and Swift Mailer is a kind of old piece of technology that we use in Symfony to send emails. And Fabian wanted to write a new one using modern style and of course what the style means doing HTTP calls because that's how we send emails nowadays, with providers providing APIs. And so that's how we started discussing with a client a few months ago, like maybe one year ago with Fabian and we ... Yeah, we figured that we need a new component, like being able to do HTTP calls without relying on third party packages that wouldn't provide the same backward compatibility and basically processes like Symfony does.

Beau 02:54 I know one of the things that the the larger PHP committee had was why did we need another HTTP Client? So I'm sure you've had to weather that storm and I think that might be part of what Dave was saying earlier about how you sort of present yourself and present the case for why you needed it. That sort of a thing. I haven't been on the receiving end of ... well not, I guess that's not true. A few times I've been on the receiving end of people being unhappy with the direction something's going. In my case, it was FIG. In your case it was why didn't you use FIG with PSR-18 or whatever? What has that been like to be on the receiving end of something like that?

Nicolas 03:41 So yeah, there being some surprise effects. When I opened the pull request on the GitHub repository, there had been some reactions to that. Like what you're saying, people were wondering why do we need another one? So basically the answer are several ... aspects. One of them is like the policies that I mentioned before, we really want to be able to enforce the backward compatibility premise, the way we do versioning. So you know about maybe the package principles. So build components on top of more stables components. And our opinion is that at that time no existing clients provided the stability that would allow us to, no guarantee that we would be able to build Symfony Mailer and support it for a long time with the processes and [inaudible 00:04:39].

Nicolas 04:40 So that's one part and I think it's a pretty significant one. Another one is that we have some experience with Guzzle because we used it a lot in the Blackfire player or I don't know if you're heard about the Blackfire player but it's a web crawler, some tool that is able to ... that you can program to basically code a website and any HTTP in potentially in a pretty powerful way. So this one uses ... does a lot and it's been a bit painful to use it to do [inaudible 00:05:17] crawling. So that's also part of the experience like, "Hmm, can we do better in term of experiments?" And I think we managed to do that. So that was also significant motivation. And the third one is what Beau just mentioned, which is about the FIG and the PSR. So you know Symfony is not into PSR-7 for various reasons. And so we couldn't start using, you know, PSA-18 as a first class dependency in Symfony because that would bring PSR-7 and we don't want to open that door for Symfony. We don't need PSR-7 and we want to stay free from that, yeah.

Dave 06:08 Yeah I mean the first point you made really sort of ... and I understood it when it all came about. Particularly it's very easy, but because Guzzle is so popular and other libraries are using it, it's very easy to get version and constraint problems where all you need is a couple of libraries that you are consuming to require Guzzle and then all of a sudden they've got to keep up with the version changes. Although, I'll be honest, Guzzle has stabilized what I'd say recently, but I think that it's really important to think about the way of how relying on stable components and as Symfony ... Symfony is going be at the core ... as Symfony in the framework sense or in the largest sense rather than not talking about an individual component here or there, but using a lot of Symfony components together at the same time and you need a ... Something stable to rely on and it comes packaged together, doesn't it, in a way. I think it's a very sensible decision.

Dave 07:12 Yeah. I'm interested to know what sort of advanced features you might have. You said you think you could do a few things better than Guzzle. To what sort of extra things can we expect from the HTTP client?

Nicolas 07:24 So the client is built for Async and HTTP too. So I have some crazy experiments and crazy [inaudible 00:07:35]. I mean crazy because I was surprised by the results. Just using the quite simple API you are able, using the Symfony has to be planned to do a lot of queries concurrently using ... doing streaming and multiplexing and so on. And the API is just simple compared to promises. I think it's more flexible as ... because no promises add some design overhead that's needed and that's a good way of doing things. But when your application is full of callbacks and promises everywhere, sometimes you lose your mind to understand what's going on. And I think that the client provides some generators.

Nicolas 08:18 So basically it's doing things the reverse way instead of putting your occurred inside callbacks, it allows you to iterate over. I had network activity from the outside of ... yeah, all the clients. So you know, maybe React PHP and, and AMPHP. So that's two Async frameworks and they also have this kind of difference what ReactPHP is doing callbacks everywhere and AMPHPis using codings and generators and, and Symfony, to be clear, is more on the side of AMPHP in this regard.

Dave 08:56 Okay. That sounds cool. So you mentioned that ... going back to the requirement for the Mailer component, my understanding is that ... does it come, does it ship with a number of providers out of the box? The Mailer component?

Nicolas 09:15 Yes. Not technically out of the box because we split the providers-

Dave 09:21 Okay [crosstalk 00:09:21] simply provides ...

Nicolas 09:22 Yes. But out of the box they are, you can just require, let's say the same grade or the mentioned bridge and those would actually send through.

Dave 09:33 Okay. And for those same sort of reasons like stability and stuff, did you choose to create the bridge to use the Symfony HTTP Client rather than say, use the SDKs that some of those providers might provide?

Nicolas 09:48 Yeah, absolutely. That's what we would do, yeah.

Dave 09:49 That makes sense to me. My personal experience is quite often been that the APIs that they provide usually do enough for me with a bare HTTP call-

Nicolas 09:59 Mm-hmm (affirmative).

Dave 10:01 -quite often. It's very rarely that I've ever wanted to use some of the more advanced features of the the mail providers if you like, that might require or might make you want to use the SDKs. So I've usually ended up writing my own transports, if you like, for SwiftMailer. We called them transports for SwiftMailer, didn't we?

Nicolas 10:20 Yeah.

Dave 10:23 So that's, that's kind of cool. I'm pleased about that and sometimes it feels like the SDKs, particularly in PHP, I don't know, I might be doing some people a disservice with this, but sometimes I feel that some of these providers, they tend to have an SDK for PHP, but sometimes it's a bit of a second class citizen that may be generated from some eight documents or something and then somebody comes along and checks it briefly, but they spend more time on the JavaScript SDK.

Dave 10:54 Probably gets the most effort from those providers. So again, I'm just a, generally, I try to stay away from them if I can and just use the API with the HTTP Client manually. So that's cool. So also, what else can you tell us about the HTTP Client?

Nicolas 11:12 Yeah, so I'm very happy. I just finished the document and I tweeted about that. So there was a lot of things in the documentation to explain that. Just saying for people that want to have a look later, to be honest in familiar component, we just need to do basic HTTP calls like one directional, request response, you don't need to add concurrency and so on. So of course I went further than just what we strictly required for the medical component because I think it was a ... it's nice to have a Symfony component that provides and covers all the advanced ... the simple ones and the advanced use cases also for HTTP .

Nicolas 11:53 So yeah, in terms of performance, there is the API that is lazy by default, which the laziness is the way to achieve, you know, concurrency because you start request and nothing happens yet. And then you read the responses and suddenly all requests that you sent before are all monitored together. And so that's part of the concurrency framework design of the component. And this way it works.

Nicolas 12:20 There's another thing that I discovered. This week I didn't expect it, Which is a another performance benefit from ... the design of it is that when you do second show, like a synchronous requests, it's still faster. And I discovered that it was surprising and I wondered why. And the answer is pretty simple and it's that the client is able to keep the connection open between calls. And I think no other clients have that design that allows that so that you open the front, you do first request to let's say the GitHub API and then the TCP connection takes time to open the first time because you need to do DNS resolution, necessary association, and so on. And the second time you don't need to do that anymore with the client. So I think that's nice side effect of the design of the component. Yeah, I'm very happy with that. So I did not do any benchmarks yet. And we have some, some to do out actually.

Dave 13:23 Okay. So just to be clear, are you using just raw sockets for this or ... so you don't use a cURL multi or anything like that?

Nicolas 13:32 Oh sure. So yes and our two implementation for transport. One is cURL and that's the most advanced one because you know, of course the grant basically is just a rubber one cURL is the product for a thing. And the second implementation is based on fopen. The HTTP is two in rubber and this one is basic. You cannot do that in fopen.

Dave 13:57 Yeah. So no persistent connections or anything like that?

Nicolas 14:03 Yeah.

Dave 14:03 With that, just with the cURL implementation.

Nicolas 14:03 Sure, yeah.

Dave 14:03 That makes sense. So things like ... so you mentioned HTTP/2 support. How much of that is Symfony and how much is that is cURL? Is that ...

Nicolas 14:14 Technically it's only cURL and Symfony's providing the designer that-

Dave 14:22 The API too.

Nicolas 14:23 Yeah. Yeah, exactly. The API. So the API is compatible with that. That's quite not the case on let's say PSR-18 which is the PSR that [inaudible 00:14:35] for a recommendation that is built by the PHP-FIG and PSR-18 is almost not compatible. I mean it's not compatible with HTTP/2 or if it is, it doesn't have rush concurrency at all. The design doesn't allow a concurrence request. So it's only for simple request response, synchronous ones. So yeah, that's why the design is very important to give you access to the load of the features.

Dave 15:03 Yeah, that sounds pretty cool.

Beau 15:05 I think I saw a ... something on Twitter from you relatively recently about wishing that your ... wishing that you could ship just interfaces, no concrete classes and just provide traits. Did you ... is that part of HTTP Client? Did you do that with HTTP Client in some sense?

Nicolas 15:29 Yes. Absolutely.

Beau 15:30 Can you go into more detail about that? Cause I think I've seen people-

Nicolas 15:34 Yeah, sure.

Beau 15:35 -asking about that too. Why is it done this way? How do I extend it if it's all traits, that sort of thing.

Nicolas 15:40 Okay so that's Symfony Contracts, I don't know if you've heard about that. So since for the tools, like six months ago we released Symfony Contracts and Symfony Contracts is exactly this project I had. So it's only interfaces wordings around that to explain how some implementation must behave. So like a specification for the implementation and traits to ship some default implementation for some behaviors that are described as words.

Nicolas 16:14 So the ... that happens for a translation because I did that a few months ago, but that happens also for HTTP Client. So HTTP Client is really two things because the implementation is decoupled from the contract, from the abstraction of it. So there are two packages actually for HTTP Client. One is the Symfony Contracts HTTP Client or Symfony HTTP Client Contracts, that's the name of the package.

Nicolas 16:39 And the other one is that is the Symfony HTTP Client component. And so the component is the implementation. It requires the contract and the contract contains only interfaces, minimum while and a few trades. Just because when you add the word surround interfaces and saying, "Oh this must be like that and that in this situation." This can be coded in traits. But actually the traits is just a good way to start with junk. You don't have to use them at all to call the correct implementation. It's just easier. So that just the tool.

Dave 17:20 Like a reference implementation.

Nicolas 17:21 Yes, absolutely.

Beau 17:23 So are the traits actually shipped next to the interfaces in the contract?

Nicolas 17:28 Yes, absolutely.

Beau 17:29 Okay.

Nicolas 17:29 Yup.

Dave 17:31 Man, I like that. That sounds good. It's very easy to confuse the words contracts with API isn't it? And API is literally the interface to the thing and the contract is involves far more than the API. The contract is an agreed way of behaving. So an API literally boils down to this is the call I make, whereas the contract is, this is the call you can make and this is how you can expect me to behave or expect me to work. You know, we forget that sometimes. So that sounds really good to me. I like that.

Beau 18:07 How have you found actually working with it in real life? What kind of tooling do you have in place? I haven't done a whole lot with traits in the past, but I've seen different projects use them to varying degrees of success. You know, the actual tooling. There is no relationship between a trait and an interface. You can't have a trait implement an interface for example. Have you run into any like gotchas with that? Or have people in the real world now come back with situations where things don't work quite as you had hoped?

Nicolas 18:43 So about the traits you mean?

Beau 18:45 Yeah.

Nicolas 18:46 So traits. Is there a concept that ... is there a way to shape their behavior? I think that's quite important to understand what it means. And the behavior is something that should be functional in, you know, in terms of functional programming, it should be, it should have no side effects. That's what being functional means daily in this context. And so a trade should just be a way to process something, input processing output and the processing. And implementation is a trait, right?

Nicolas 19:15 And so a lot of objective oriented concepts disappear and don't exist in the trait world. So that's I think the difficult thing that people don't get first and need some understanding and experience because it's just unexpected. People would say, "Well we'd like to have a trait be able to implement on interface." Like you said, but it doesn't make sense actually. It's just a behavior.

Beau 19:39 But the traits have the same functions or at least a subset of the functions exposed by the interface, right?

Nicolas 19:46 Yeah. Right. But it's just a coincidence. It's a nice one because it makes things easy to wire by default. But actually when you import the trait, when you use a trait, you can change the name of a [inaudible 00:19:57] . You can change its visibility. So it's basically like copy and paste. And if you want to change the signature, it's pretty easy. You import that as a private method, even if it's public in the trait. And then you write the implementation in some public API that the class you need provides. So that works also this way.

Nicolas 20:18 And I like this quite much. It's a better way to me or it ... maybe not better, but it's a simpler way then designing, you know, interfaces to provide extensibility. Someone asks this question on Synchrony, so there's an issue where I play to give my opinion and that topic, why isn't there some extensibility interface to be able to create a plugin inside the Http? So I know the internal interface for building plugin should be client interface and so why do you should try it and so and so that was the question.

Nicolas 20:57 And basically the reason is that because it's simpler to ship that because you don't need to build that design that I don't know what it could look like actually. The design to provide like plugin system and the trait to just provide the implementation for things that are not obvious and then people do what they want. And so that's one aspect. And another one is fundamental and bottom view. It's more complex actually to maintain a design than to maintain behaviors. Even behaviors don't have side effects. That's the big red flag. If you create a trait and the trait has side effects, you're completely out of a track and yeah it is maintenance and it doesn't force me to think a period of time about things. I don't, I can't answer now.

Dave 21:53 I have a question.

Nicolas 21:54 Yeah?

Dave 21:55 For somebody like me who may be a couple of years behind on Symfony releases and what's the ... what does the dependency graph look like for the HTTP component? Does it, does the component rely on the contracts and is there anything deeper than that thereafter?

Nicolas 22:09 So that's a critical part of the design or sort of the component. We want every component to have as few dependencies as possible. And that's the case for the client. So the client has only three lines in therequire Composer file and one is PHP-7, that one.

Dave 22:24 Okay.

Nicolas 22:27 The other one is like the contracts Symfony HTTP Client contracts because that's the main ... so actually we use, and then there's another one which is a very technical one. Boring one. Less Symfony policy for PHP-7.3 which is not, you know, it's just there because we want to be able to throw JSON exception and turning that means. Yeah.

Dave 22:46 Yeah. Okay. That's cool. Cause I mean it took me a while to get onto Symfony 3 and I'm going to be stuck there for a little while longer.

Nicolas 22:55 Yeah. You can move to Symfony 2 and PHP-7.1, you can use the client even if you're still in Symfony 3.

Dave 23:01 Yeah, yeah. Oh yeah. I'm well ahead on. I'm always fine keeping up with the PHP versions. Just Symfony versions are a little bit more difficult for me.

Beau 23:13 I'm trying to double check here to make sure that I'm following correctly and it looks like the translation package has a trait in the contract.

Nicolas 23:25 Yes.

Beau 23:26 But I don't see any traits in HTTP Client.

Nicolas 23:28 You're right. Actually I had ... there was a trait this winter, but we moved it to the components.

Beau 23:37 Okay.

Nicolas 23:38 So yes, actually for the, I didn't remember exactly, but for the contracts of the client, there is no need for ... We don't simply need implementation for ...

Beau 23:47 Okay. I just want to make sure I understand cause I when I saw you talk about this, it sounded interesting. So I was curious how you are actually distributing it and then I wanted to look at it more and couldn't see it. So, okay cool. It's pretty neat.

Nicolas 24:02 Okay. So another thing that is in the composer.json file Is the provide section. I don't know if you want to look at that and the provide section. We are ... so it's a way to declare what this component provides in terms of abstraction and three of them that are listed out, maybe two of them in front of three and there was a third one in front of four that is going to be released in a few months.

Nicolas 24:25 So one is the Symfony HTTP Client implementation right? So we declare that these implements the contracts, which is obvious and there's another one which is the PSR HTTP Client implementation. So this is advertising that we implement PSR-18 so actually we are doing improvement on PSR- 18

Beau 24:47 I actually noticed that and I brought this up to Dave as soon as I saw it, I had done a search for PSR-18 on GitHub, just out of curiosity. And I noticed Symfony popped up at the top and I'm like, "Wow. After all of that, Symfony's still at the top on PSR-18 which is pretty awesome." So, so you actually have a PSR-18 implementation or is it just advertising?

Nicolas 25:15 No, we do have ... actually it's pretty simple once we have the contract, the contract is more powerful, much more powerful than PSR-18 so then when you have something powerful, you can very easily implement PSR-18. If you have a look, it's a very quite simple class with a few lines of code to do queries the the PSR-18 way using the HTTP Client interface implementation.

Beau 25:39 I mentioned PSR-7 bridge. Does this actually use the PSR-7 bridge or [crosstalk 00:25:45] or not even?

Nicolas 25:45 You don't have to use the bridge. The bridge is for bridging PSR-7 and Http Foundation.

Beau 25:51 Okay.

Nicolas 25:51 But yeah, then you need to have some restaurants, factories and twin factories because that's the way PSR-7 works and from that we have ... there was a package that I'm told yesterday we created which is called Nyholm PSR-7 and it's very straightforward implementation of PSR-7 and PSR-17 and so if you have it, we use it by default. We detect it and we use that so that ... actually you don't have to provide the factors. So that's, yeah. Actually when you use PSR-18 it's like you open a door and the door comes with like numbers, like what I'm using now and numbers means [inaudible 00:26:31]. Then you have 10 objects before being able to do a request. So yeah. Okay. Yeah, we try make that simple also.

Beau 26:45 Yeah. Cool.

Dave 26:48 Yeah, I'm yet to use it, but I do intend to have a good look at it at some point. So I think, I think Beau wanted to ask you a few questions about Symfony. You mentioned earlier on that you are now working for Symfony the company. What did you want to get into on that Beau?

Beau 27:05 Oh I was just curious how that that is going. I was still a part of Blackfire when Blackfire was a part of Sensio, as was Symfony, but I sort of lost track about how things have sort of gone. It seems like an interesting project to sort of extract Symfony from Sensio since then, Sensio has been acquired by somebody else. I was just curious how that whole process has gone down, what things have changed for you, what sort of things have changed for Symfony itself? What kind of impact does it had maybe on like the events too? Cause I think the Symfony events and all of the Sensio or the Symfony live events and SymfonyCon those are all a part of the Symfony organization now, right? Yeah.

Nicolas 27:54 Yes. So because SensioLabs was about to be acquired in France, Fabian split Blackfire and Symfony as separate companies. So that's when we would not acquire these business units. So now the business units are independent companies and small team went to each company, so I didn't go into the Blackfire boat, but into the Symfony one. So Symfony as a mission, which is supporting and supporting Symfony and also making money like being sustainable. That's the minimum. And maybe make money if it's, you know, success is always good thing. We started with and we still just have the business of the events. So that's part of things that create some revenue for and support my salary. So my contributions. And we also have a certification, which is part of the business of Symfony. The company, it's not creating much revenue, but we ... it's part of Symfony's. So it's doing stuff out of SymfonyLabs.

Nicolas 29:05 There is a SymfonyCloud. So SymfonyCloud, I don't know if you've heard about that, but it's a hosting. So we are providing hosting for Symfony projects are using some platform as a service offer. So if you want to provide to host to Symfony project, SymfonyCloud might be the best option in terms of efficiency. It's just turned out to host Symfony projects and Symfony projects are not only about PHP nowadays. So actually this provides a way to host ... go binary's and nodejs binary's side by side next to the Symfony and the PHP thing. So there was of course [inaudible 00:29:45]. So yeah, so that's part of the business. It's kind of the beginning of this story. So SymfonyCloud is growing and we hope it is going to be much, much more bigger than it is now. So we are betting on it and we are doing more conferences.

Nicolas 30:02 And for Symfony it means that ... for Symfony the open source project, it means that nothing changes. Basically I'm still doing contributions to Symfony, the open source and part of my time is consult by Symfony the company. And I also have business objective in terms of business actually. So yeah, I think that's for the best of the open source project. Having some you know, company that is caring about making the community active, providing professional services around that like the one I mentioned.

Beau 30:39 Cool. And so you haven't noticed any changes for the better or for the worse? As far as the project goes, it seems like the project is still quite healthy between Messenger and HTTP Client and Mailer. A bunch of brand new big components are coming out. I mean it seems like things are still going ahead as well as they have been, from the outside anyway.

Nicolas 31:07 Yeah. Symfony, the opensource project is, well it's crazy active, I mean I go away for one day and I have 50 emails from different people that do both fixes and report bugs and do pull requests and move things forward. It's quite incredible actually. So sometimes I'm like, "Eh, I'm the only one pushing things forward. I spend my weekend, my evenings." I totally, I'm not the only one. Fabien does it and a few other people are very active. And then I go on holiday for two weeks and then I look at my inbox and I say, "Wow, I don't need to be here because the boat is moving forward on its own."

Nicolas 31:40 So yeah, I'm just adding my contribution of course. But Symfony is crazy active, and I think that there's a lot of reasons of why that ... but I think the project is pretty wide structured-

Beau 31:54 Mm-hmm (affirmative).

Nicolas 31:54 -to be able to accept contributions quite easy compared to a open source project. I think.

Dave 32:01 Yeah, I think it's quite interesting. I mean only time will tell how it goes, but I think a proactive approach to this ... I mean, you could draw some parallels. It's difficult quite because of Symfony's popularity now, but you could draw some parallels to Rogue Wave's acquisition of as end. You know, that happened a few years ago, right? And a few months ago they literally sort of like dropped Zend Framework. Is that right?

Beau 32:29 Mm-hmm (affirmative).Yeah.

Dave 32:30 You know, and that's kinda like that. That's the sad way, isn't it? You know, they acquired Zend and let's face it, they didn't acquire Zend for Zend Framework did they? They acquired Zend for the the service. .. Provide insight of the business, possibly Zend Studio, I don't know though, I don't really know what's after that but ... and I'm ... in this kind of manner, they could have looked at doing something like that along the lines of separate out Zend framework into another company at that point rather than going two years down the line of probably some wishy washy experience. And then eventually them just sort of like cutting the framework loose so cutting the opensource project loose further down the line rather than ... so I think, I think this approach definitely has its merits and I hope it goes really well for you.

Beau 33:25 Mm-hmm (affirmative).

Dave 33:27 I get the impression it will just like I say, just from the way I've seen you conduct things or conduct your business. I'm sure you'll have much success. So yeah.

Nicolas 33:39 I hope too.

Beau 33:41 So as far as events, I think you were in South America recently. There was a ... was it a Symfony Live event?

Nicolas 33:47 Yeah for Symfony Live I was in South America.

Beau 33:51 Yeah, and I think there was ... was there one in Asia this year too?

Nicolas 33:55 It was not a Symfony live. In October, Fabien went there to do a meetup.

Beau 34:02 Ah, okay.

Nicolas 34:02 It's like a pre-Symfony Liveevent to see, to feel the community there and see how much traction-

Beau 34:09 Mm-hmm (affirmative).

Nicolas 34:10 -there could be to create maybe.

Beau 34:13 But there isn't going to be one in the U.S. this year or is there?

Nicolas 34:17 No, not this year. We would like to make one in one year from now. And actually we're looking for help for that because you know, having heard from local people is always very important. So if there is anyone on the east coast, especially, that could provide us some venue or any kind of support would be super happy to.

Beau 34:41 Cool. Yeah, I think that, well, both Dave and I are longtime Symfony users. I think that Dave maybe predates me by a little while, but my very first conference was a Symfony live in Portland while one of my very first conferences with Symfony live in Portland. Definitely the first one I spoke at. So I have a special place in my heart for Symfony Live events in the U.S. so I'm happy to hear that it's on the table at least for next year still.

Nicolas 35:14 Yeah.

Dave 35:14 Yeah, that was my, that was my first speaking engagement as well. Was that conference in Portland.

Nicolas 35:21 Cool. Cool. So we need to make one?

Beau 35:23 Yes. Yup. Nice. Cool. Well, did you have anything else you wanted to talk about Nicolas or did you Dave?

Dave 35:32 Oh, I'm good. I wanted to let Nicolas do the talking-

Beau 35:36 Yeah.

Nicolas 35:36 Yeah?

Dave 35:36 -so I hadn't really planned on talking about anything.

Nicolas 35:41 Sound good. Thank you. Thank you very much. I was very happy to be here.

Dave 35:44 Yeah. So thanks for coming on. Yeah. And keep up the good work. Like I said I get the feeling your avatar on GitHub. You've got a really big smile on but maybe I'm just imagining that-

Nicolas 35:54 Yeah, yeah.

Dave 35:55 -And maybe that's part of it. You know, every time I opened a PR there's like this really nice smiley avatar.

Nicolas 36:00 It's my superpower.

Dave 36:02 Yeah.

Nicolas 36:02 The smiley is my superpower.

Dave 36:04 Yeah, no, definitely. It's good. It's far better than something dreary or you know or all just random, I think it's nice.

Nicolas 36:13 Sometimes I post comments and I'm upset by the way the conversation is going, but I still have a smile so that's-

Dave 36:19 That's right. Yeah.

Beau 36:23 Cool. All right, well if nobody has anything else, I guess we can call this one a wrap.