thecodingmachine / graphqlite

Use PHP Attributes/Annotations to declare your GraphQL API

Home Page:https://graphqlite.thecodingmachine.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Mutability concerns

oprypkhantc opened this issue · comments

Currently many of the classes are mutable, including fields and types. While this has been working so far for us, we've never actually tested it on production so there might be bugs related to it. And unfortunately, even if there are none, graphqlite doesn't (and shouldn't) have tests coverage for it so it might become an issue in the future after any changes.

We've had prior instances where a previous (mutable) state under very specific conditions was shared between multiple requests/jobs and you have to go through heaps of hell to debug it, fix it and hope the business wasn't affected too much. That's why I'm worried about graphqlite's usage of mutability.

This is somewhat fine for SchemaFactory and field descriptors, because it's only executed once prior to handling requests, but with everything else - i.e. types & fields, this is a concern. I propose replacing mutable classes with immutable ones - starting with things that can actually break, i.e. types / fields / property resolvers etc. I believe those aren't part of the public API, so it won't be a breaking change.

After refactoring the important parts, I would have refactored the rest - i.e. field descriptors, schema factory etc, although this would definitely be a breaking change and is not as important.

Thoughts? As always I'll PR the necessary changes.

Decreasing our mutability footprint is certainly welcomed! Do you have any ideas on how you'd go about this right now? My only concern would be around adding additional abstraction layers, further complicating the business logic.

@oojacoboo No ideas right now as I haven't looked much into it. With property resolvers I think changes should be minimal - just pass the object as the first argument, dropping both setObject and getObject. This should not add any abstractions and even reduce the number of them, but it's a breaking change for middlewares that set a custom resolver and actually use the arguments. I don't think there's any real way of avoiding it - resolvers might be userland closures and we don't know if they use the arguments or not.

The rest I'm not sure yet. Would this kind of breaking change be fine? And if so, should we also target other mutability as well since a breaking change is needed anyway? I'm mainly talking about InputFieldDescriptor, QueryFieldDescriptor and SchemaFactory as those contribute a lot to mutability. Those can have all of the set methods replaced with with, similar PSR's packages.

With the SchemaFactory, is there really a need for this to be immutable? Can you think of any valid cases where this is going to be reused, even within an asyc server? A BC break here is going to be significantly more disruptive, as this would affect all installations. Unless we wanted to take a long deprecation route and introduce a new immutable factory method for construction of the Schema, with a plan to eventually remove mutable support.

I think a BC break on InputFieldDescriptor and QueryFieldDescriptor is fine. That will break any custom middleware that's mutating these. But that should be a much smaller percentage of users affected. We'll obviously version it appropriately.

No, I don't think it's really worth it to disrupt all installations. I believe there's a reason for SchemaFactory to be immutable and have public properties - for cases like mine where you need multiple schemas with few differences and possibly custom instantiation, but that's a different story.

We have a Schema\Builder service. I'm sure you can just handle that in a similar fashion with the SchemaFactory being mutable.