I want to use graph-gophers/dataloader
to implement a dataloader for bulk-fetching users.
I have implemented it like below but I need to return an explicit data type, not an interface{}
Firstly, I create UserReader
with function GetUsers
by given dataloader.Keys
:
type UserReader struct {
userCtrl user.Controller // This is my user service for Create, Get, Delete user
}
func newUserReader(userCtrl user.Controller) UserReader {
return UserReader{
userCtrl: userCtrl,
}
}
// GetUsers return a list of result by given keys
func (reader UserReader) GetUsers(ctx context.Context, keys dataloader.Keys) []*dataloader.Result {
output := make([]*dataloader.Result, len(keys))
for i, key := range keys {
userID := key.String()
// Get list of user by string userID
result, err := reader.userCtrl.GetUsers(ctx, userID)
output[i] = &dataloader.Result{Data: result, Error: err}
}
return output
}
And then, I create a Loader
with function GetUser
to get a user by userID
, it won't request data from userCtrl
more than 1 time in a single request.
type Loader struct {
userLoader *dataloader.Loader
}
func newLoader(userCtrl user.Controller) Loader {
userReader := newUserReader(userCtrl)
return Loader{
// Create new user loader with batch function
userLoader: dataloader.NewBatchedLoader(userReader.GetUsers),
}
}
// UserLoader returns the user loader
func (loader Loader) UserLoader() *dataloader.Loader {
return loader.userLoader
}
// GetUser return a user by given parameter
func (loader impl) GetUser(ctx context.Context, userID string) (model.User, error) {
// FromCtx gets a Loader from context if it exists, else nil.
ctxLoader := FromCtx(ctx)
// Thunk is function return value with interface{} type and error
thunk := ctxLoader.UserLoader().Load(ctx, dataloader.StringKey(userID))
result, err := thunk()
if err != nil {
return nil, err
}
return result.(model.User), nil // Convert datatype here!!!
}
And finally, It can be use
dataloader.FromCtx(ctx).GetUser(ctx, userID)
But I need userReader.getUsers
to return an object containing model.user
not interface{}
because I don't want to convert the data type in the Loader.getUser
function.
Is there a way to have dataloader.Result
return a certain data type instead of the interface{}
?
The v7
version of graph-gophers/dataloader
supports generics. Specifically, the BatchFunc
signature has changed so you can specify the resulting type.