在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(OpenSource Name):Shopify/graphql-batch开源软件地址(OpenSource Url):https://github.com/Shopify/graphql-batch开源编程语言(OpenSource Language):Ruby 99.8%开源软件介绍(OpenSource Introduction):GraphQL::BatchProvides an executor for the InstallationAdd this line to your application's Gemfile: gem 'graphql-batch' And then execute:
Or install it yourself as:
UsageBasic UsageSchema ConfigurationRequire the library require 'graphql/batch' Define a custom loader, which is initialized with arguments that are used for grouping and a perform method for performing the batch load. class RecordLoader < GraphQL::Batch::Loader
def initialize(model)
@model = model
end
def perform(ids)
@model.where(id: ids).each { |record| fulfill(record.id, record) }
ids.each { |id| fulfill(id, nil) unless fulfilled?(id) }
end
end Use class MySchema < GraphQL::Schema
query MyQueryType
mutation MyMutationType
use GraphQL::Batch
end Field UsageThe loader class can be used from the resolver for a graphql field by calling field :product, Types::Product, null: true do
argument :id, ID, required: true
end
def product(id:)
RecordLoader.for(Product).load(id)
end The loader also supports batch loading an array of records instead of just a single record, via field :products, [Types::Product, null: true], null: false do
argument :ids, [ID], required: true
end
def products(ids:)
RecordLoader.for(Product).load_many(ids)
end Although this library doesn't have a dependency on active record, the examples directory has record and association loaders for active record which handles edge cases like type casting ids and overriding GraphQL::Batch::Loader#cache_key to load associations on records with the same id. PromisesGraphQL::Batch::Loader#load returns a Promise using the promise.rb gem to provide a promise based API, so you can transform the query results using def product_title(id:)
RecordLoader.for(Product).load(id).then do |product|
product.title
end
end You may also need to do another query that depends on the first one to get the result, in which case the query block can return another query. def product_image(id:)
RecordLoader.for(Product).load(id).then do |product|
RecordLoader.for(Image).load(product.image_id)
end
end If the second query doesn't depend on the first one, then you can use Promise.all, which allows each query in the group to be batched with other queries. def all_collections
Promise.all([
CountLoader.for(Shop, :smart_collections).load(context.shop_id),
CountLoader.for(Shop, :custom_collections).load(context.shop_id),
]).then do |results|
results.reduce(&:+)
end
end
def product(id:)
# Try the cache first ...
CacheLoader.for(Product).load(id).then(nil, lambda do |exc|
# But if there's a connection error, go to the underlying database
raise exc unless exc.is_a?(Redis::BaseConnectionError)
logger.warn err.message
RecordLoader.for(Product).load(id)
end)
end Unit TestingYour loaders can be tested outside of a GraphQL query by doing the
batch loads in a block passed to def test_single_query
product = products(:snowboard)
title = GraphQL::Batch.batch do
RecordLoader.for(Product).load(product.id).then(&:title)
end
assert_equal product.title, title
end DevelopmentAfter checking out the repo, run ContributingSee our contributing guidelines for more information. LicenseThe gem is available as open source under the terms of the MIT License. |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论