Make graphql id fields globally unique
The GraphQL::ID_TYPE
we use in GraphQL should be globally unique, but right now we're just dropping in the database id.
I think we should start being consistent, and build a real, globally unique id we can decode and use to find a single object (preferably using the BatchModelLoader
).
This will also allow us write cleaner mutations that require an ID like that to load their object: https://graphql-ruby.org/mutations/mutation_classes.html#auto-loading-arguments
Since all of our types are now a Types::BaseObject
, I think we could introduce an id
method, that would take precedence over the PresentedClass#id
method.
Roughly like this:
app/graphql/types/base_object.rb
:
def id
GitlabSchema.id_from_object(object)
end
app/graphql/gitlab_schema.rb
:
def self.id_from_object(object)
Base64.encode("#{object.class.name}-#{object.id}"
end
def self.object_from_id(object_id, _context)
class_name, id = Base64.decode(object_id).split("-")
return unless class_name.present? && id.present?
Gitlab::Graphql::Loaders::BatchModelLoader.new(class_name.constantize, id).find
rescue NameError
raise Gitlab::Graphql::InvalidId, "Invalid Graphql ID"
end
We'll need to double check any fields that already take an ID_TYPE
argument.