Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/identity-api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func main() {

s := newDefaultServer(graph.NewExecutableSchema(cfg))

srv := loader.Middleware(dbs, s, settings)
srv := loader.Middleware(dbs, s, settings, &logger)

http.Handle("/", playground.Handler("GraphQL playground", "/query"))
http.Handle("/query", srv)
Expand Down
2 changes: 1 addition & 1 deletion graph/dcn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func TestDCNQuery(t *testing.T) {

require.NoError(err)
cfg := Config{Resolvers: resolver}
c := client.New(loader.Middleware(pdb, NewDefaultServer(NewExecutableSchema(cfg)), settings))
c := client.New(loader.Middleware(pdb, NewDefaultServer(NewExecutableSchema(cfg)), settings, nil))

type response struct {
DCN struct {
Expand Down
5 changes: 3 additions & 2 deletions graph/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,17 +122,18 @@ type Resolver struct {
// NewResolver creates a new Resolver with allocated repositories.
func NewResolver(baseRepo *base.Repository) *Resolver {
tablelandApiService := services.NewTablelandApiService(baseRepo.Log, &baseRepo.Settings)
deviceDefRepo := devicedefinition.New(baseRepo, tablelandApiService)

return &Resolver{
aftermarket: aftermarket.New(baseRepo),
dcn: dcn.New(baseRepo),
manufacturer: manufacturer.New(baseRepo),
reward: reward.Repository{Repository: baseRepo},
synthetic: synthetic.New(baseRepo),
vehicle: vehicle.New(baseRepo),
vehicle: vehicle.New(baseRepo, deviceDefRepo),
vehicleprivilege: vehicleprivilege.Repository{Repository: baseRepo},
vehiclesacd: vehiclesacd.Repository{Repository: baseRepo},
deviceDefinition: devicedefinition.New(baseRepo, tablelandApiService),
deviceDefinition: deviceDefRepo,
developerLicense: developerlicense.New(baseRepo),
stake: stake.New(baseRepo),
connection: connection.New(baseRepo),
Expand Down
2 changes: 1 addition & 1 deletion graph/resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func TestResolver(t *testing.T) {
logger := zerolog.Nop()
repo := base.NewRepository(pdb, settings, &logger)
resolver := NewResolver(repo)
c := client.New(loader.Middleware(pdb, NewDefaultServer(NewExecutableSchema(Config{Resolvers: resolver})), settings))
c := client.New(loader.Middleware(pdb, NewDefaultServer(NewExecutableSchema(Config{Resolvers: resolver})), settings, nil))

t.Run("ownedAftermarketDevices, return only one response", func(t *testing.T) {
var resp interface{}
Expand Down
40 changes: 8 additions & 32 deletions graph/rewards_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,10 +213,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetEarningsByVehicle_FwdPaginate() {
}`

c := client.New(
loader.Middleware(
r.pdb,
NewDefaultServer(NewExecutableSchema(Config{Resolvers: r.resolver})), r.settings,
),
loader.Middleware(r.pdb, NewDefaultServer(NewExecutableSchema(Config{Resolvers: r.resolver})), r.settings, nil),
)

var resp interface{}
Expand Down Expand Up @@ -389,10 +386,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetEarningsByVehicle_FwdPaginate_Firs
}`

c := client.New(
loader.Middleware(
r.pdb,
NewDefaultServer(NewExecutableSchema(Config{Resolvers: r.resolver})), r.settings,
),
loader.Middleware(r.pdb, NewDefaultServer(NewExecutableSchema(Config{Resolvers: r.resolver})), r.settings, nil),
)

var resp interface{}
Expand Down Expand Up @@ -594,10 +588,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetEarningsByVehicle_BackPaginate_Las
}`

c := client.New(
loader.Middleware(
r.pdb,
NewDefaultServer(NewExecutableSchema(Config{Resolvers: r.resolver})), r.settings,
),
loader.Middleware(r.pdb, NewDefaultServer(NewExecutableSchema(Config{Resolvers: r.resolver})), r.settings, nil),
)

var resp interface{}
Expand Down Expand Up @@ -799,10 +790,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetEarningsByVehicle_BackPaginate_Las
}`

c := client.New(
loader.Middleware(
r.pdb,
NewDefaultServer(NewExecutableSchema(Config{Resolvers: r.resolver})), r.settings,
),
loader.Middleware(r.pdb, NewDefaultServer(NewExecutableSchema(Config{Resolvers: r.resolver})), r.settings, nil),
)

var resp interface{}
Expand Down Expand Up @@ -962,10 +950,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetAftermarketDeviceEarnings_FwdPagin
}`

c := client.New(
loader.Middleware(
r.pdb,
NewDefaultServer(NewExecutableSchema(Config{Resolvers: r.resolver})), r.settings,
),
loader.Middleware(r.pdb, NewDefaultServer(NewExecutableSchema(Config{Resolvers: r.resolver})), r.settings, nil),
)

var resp interface{}
Expand Down Expand Up @@ -1113,10 +1098,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetUserRewards_FwdPaginate() {
}`, beneficiary.Hex())

c := client.New(
loader.Middleware(
r.pdb,
NewDefaultServer(NewExecutableSchema(Config{Resolvers: r.resolver})), r.settings,
),
loader.Middleware(r.pdb, NewDefaultServer(NewExecutableSchema(Config{Resolvers: r.resolver})), r.settings, nil),
)

var resp interface{}
Expand Down Expand Up @@ -1286,10 +1268,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetUserRewards_BackPaginate_LastBefor
}`, beneficiary.Hex())

c := client.New(
loader.Middleware(
r.pdb,
NewDefaultServer(NewExecutableSchema(Config{Resolvers: r.resolver})), r.settings,
),
loader.Middleware(r.pdb, NewDefaultServer(NewExecutableSchema(Config{Resolvers: r.resolver})), r.settings, nil),
)

var resp interface{}
Expand Down Expand Up @@ -1416,10 +1395,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetUserRewards_NullEarnings() {
}`, beneficiary.Hex())

c := client.New(
loader.Middleware(
r.pdb,
NewDefaultServer(NewExecutableSchema(Config{Resolvers: r.resolver})), r.settings,
),
loader.Middleware(r.pdb, NewDefaultServer(NewExecutableSchema(Config{Resolvers: r.resolver})), r.settings, nil),
)

var resp any
Expand Down
7 changes: 5 additions & 2 deletions graph/schema.resolvers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/DIMO-Network/identity-api/internal/repositories/aftermarket"
"github.com/DIMO-Network/identity-api/internal/repositories/base"
"github.com/DIMO-Network/identity-api/internal/repositories/dcn"
"github.com/DIMO-Network/identity-api/internal/repositories/devicedefinition"
"github.com/DIMO-Network/identity-api/internal/repositories/manufacturer"
"github.com/DIMO-Network/identity-api/internal/repositories/synthetic"
"github.com/DIMO-Network/identity-api/internal/repositories/vehicle"
Expand All @@ -24,8 +25,10 @@ func TestQueryResolver_Node(t *testing.T) {

baseRepo := &base.Repository{}

vehicleRepo := vehicle.New(baseRepo)
testVehicle, err := vehicleRepo.ToAPI(&models.Vehicle{ID: 1}, "", "")
// Create a mock device definition repository for the vehicle repository
mockDeviceDefRepo := &devicedefinition.Repository{}
vehicleRepo := vehicle.New(baseRepo, mockDeviceDefRepo)
testVehicle, err := vehicleRepo.ToAPI(&models.Vehicle{ID: 1}, "", "", nil)
require.NoError(t, err)

aftermarketRepo := aftermarket.New(baseRepo)
Expand Down
7 changes: 6 additions & 1 deletion graph/vehicle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ type VehicleTestSuite struct {
consumer *services.ContractsEventsConsumer
}

//// Test Runner - commenting this out since seems this test was WIP
//func TestVehicleTestSuite(t *testing.T) {
// suite.Run(t, new(VehicleTestSuite))
//}

func (s *VehicleTestSuite) SetupSuite() {
ctx := context.TODO()
var db db.Store
Expand All @@ -46,7 +51,7 @@ func (s *VehicleTestSuite) SetupSuite() {
resolver := NewResolver(repo)

s.consumer = services.NewContractsEventsConsumer(db, &logger, &settings)
s.handler = loader.Middleware(db, NewDefaultServer(NewExecutableSchema(Config{Resolvers: resolver})), settings)
s.handler = loader.Middleware(db, NewDefaultServer(NewExecutableSchema(Config{Resolvers: resolver})), settings, nil)
}

func (s *VehicleTestSuite) TearDownSuite() {
Expand Down
16 changes: 12 additions & 4 deletions internal/loader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ import (
"github.com/DIMO-Network/identity-api/internal/repositories/base"
"github.com/DIMO-Network/identity-api/internal/repositories/connection"
"github.com/DIMO-Network/identity-api/internal/repositories/dcn"
"github.com/DIMO-Network/identity-api/internal/repositories/devicedefinition"
"github.com/DIMO-Network/identity-api/internal/repositories/manufacturer"
"github.com/DIMO-Network/identity-api/internal/repositories/stake"
"github.com/DIMO-Network/identity-api/internal/repositories/storagenode"
"github.com/DIMO-Network/identity-api/internal/repositories/synthetic"
"github.com/DIMO-Network/identity-api/internal/repositories/vehicle"
"github.com/DIMO-Network/identity-api/internal/services"
"github.com/DIMO-Network/shared/pkg/db"
"github.com/graph-gophers/dataloader/v7"
"github.com/rs/zerolog"
)

type loadersString string
Expand All @@ -39,10 +42,15 @@ type Loaders struct {
}

// NewDataLoader returns the instantiated Loaders struct for use in a request
func NewDataLoader(dbs db.Store, settings config.Settings) *Loaders {
func NewDataLoader(dbs db.Store, settings config.Settings, lg *zerolog.Logger) *Loaders {
// instantiate the user dataloader
baseRepo := &base.Repository{PDB: dbs, Settings: settings}
vehicle := NewVehicleLoader(vehicle.New(baseRepo))

// Create device definition repository first
tablelandAPI := services.NewTablelandApiService(lg, &settings)
deviceDefRepo := devicedefinition.New(baseRepo, tablelandAPI)

vehicle := NewVehicleLoader(vehicle.New(baseRepo, deviceDefRepo), deviceDefRepo)
aftermarketDevice := NewAftermarketDeviceLoader(aftermarket.New(baseRepo))
syntheticDevice := NewSyntheticDeviceLoader(synthetic.New(baseRepo))
dcn := NewDCNLoader(dcn.New(baseRepo))
Expand Down Expand Up @@ -98,9 +106,9 @@ func NewDataLoader(dbs db.Store, settings config.Settings) *Loaders {

// Middleware injects a DataLoader into the request context so it can be
// used later in the schema resolvers
func Middleware(db db.Store, next http.Handler, settings config.Settings) http.Handler {
func Middleware(db db.Store, next http.Handler, settings config.Settings, lg *zerolog.Logger) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
loader := NewDataLoader(db, settings)
loader := NewDataLoader(db, settings, lg)
nextCtx := context.WithValue(r.Context(), dataLoadersKey, loader)
r = r.WithContext(nextCtx)
next.ServeHTTP(w, r)
Expand Down
50 changes: 39 additions & 11 deletions internal/loader/vehicle_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,24 @@ import (
"errors"
"fmt"

"github.com/DIMO-Network/identity-api/graph/model"
"github.com/DIMO-Network/identity-api/internal/repositories/devicedefinition"

gmodel "github.com/DIMO-Network/identity-api/graph/model"
"github.com/DIMO-Network/identity-api/internal/repositories/vehicle"
"github.com/DIMO-Network/identity-api/models"
"github.com/graph-gophers/dataloader/v7"
)

type VehicleLoader struct {
repo *vehicle.Repository
repo *vehicle.Repository
definitionsRepo *devicedefinition.Repository
}

func NewVehicleLoader(repo *vehicle.Repository) *VehicleLoader {
return &VehicleLoader{repo: repo}
func NewVehicleLoader(repo *vehicle.Repository, definitionsRepo *devicedefinition.Repository) *VehicleLoader {
return &VehicleLoader{repo: repo, definitionsRepo: definitionsRepo}
}

func GetVehicleByID(ctx context.Context, vehicleID int) (*model.Vehicle, error) {
func GetVehicleByID(ctx context.Context, vehicleID int) (*gmodel.Vehicle, error) {
// read loader from context
loaders := ctx.Value(dataLoadersKey).(*Loaders)
// invoke and get thunk
Expand All @@ -29,13 +32,13 @@ func GetVehicleByID(ctx context.Context, vehicleID int) (*model.Vehicle, error)
}

// BatchGetVehicleByID implements the dataloader for finding vehicles by their ids.
func (v *VehicleLoader) BatchGetVehicleByID(ctx context.Context, vehicleIDs []int) []*dataloader.Result[*model.Vehicle] {
results := make([]*dataloader.Result[*model.Vehicle], len(vehicleIDs))
func (v *VehicleLoader) BatchGetVehicleByID(ctx context.Context, vehicleIDs []int) []*dataloader.Result[*gmodel.Vehicle] {
results := make([]*dataloader.Result[*gmodel.Vehicle], len(vehicleIDs))

vehicles, err := models.Vehicles(models.VehicleWhere.ID.IN(vehicleIDs)).All(ctx, v.repo.PDB.DBS().Reader)
if err != nil {
for i := range results {
results[i] = &dataloader.Result[*model.Vehicle]{Error: err}
results[i] = &dataloader.Result[*gmodel.Vehicle]{Error: err}
}
return results
}
Expand All @@ -46,6 +49,26 @@ func (v *VehicleLoader) BatchGetVehicleByID(ctx context.Context, vehicleIDs []in
vehicleByID[v.ID] = v
}

// populate a map of device definitions by id for fast lookup later
definitions := make(map[string]*gmodel.DeviceDefinition)
for _, veh := range vehicles {
definitions[veh.DeviceDefinitionID.String] = &gmodel.DeviceDefinition{}
}
ids := make([]string, 0, len(definitions))
for id := range definitions {
ids = append(ids, id)
}
dds, err := v.definitionsRepo.GetDeviceDefinitionsByIDs(ctx, ids)
if err != nil {
for i := range results {
results[i] = &dataloader.Result[*gmodel.Vehicle]{Error: err}
}
return results
}
for _, dd := range dds {
definitions[dd.DeviceDefinitionID] = dd
}

for i, k := range vehicleIDs {
if veh, ok := vehicleByID[k]; ok {
var retErr error
Expand All @@ -66,16 +89,21 @@ func (v *VehicleLoader) BatchGetVehicleByID(ctx context.Context, vehicleIDs []in
if err != nil {
retErr = errors.Join(retErr, fmt.Errorf("error getting vehicle data uri: %w", err))
}
obj, err := v.repo.ToAPI(veh, imageURI, dataURI)
definition, ok := definitions[veh.DeviceDefinitionID.String]
if !ok {
retErr = errors.Join(retErr, fmt.Errorf("error getting device definition: not found %s", veh.DeviceDefinitionID.String))
}

obj, err := v.repo.ToAPI(veh, imageURI, dataURI, definition)
if err != nil {
retErr = errors.Join(retErr, fmt.Errorf("error converting vehicle to API: %w", err))
}
results[i] = &dataloader.Result[*model.Vehicle]{
results[i] = &dataloader.Result[*gmodel.Vehicle]{
Data: obj,
Error: retErr,
}
} else {
results[i] = &dataloader.Result[*model.Vehicle]{Error: fmt.Errorf("no vehicle with id %d", k)}
results[i] = &dataloader.Result[*gmodel.Vehicle]{Error: fmt.Errorf("no vehicle with id %d", k)}
}
}

Expand Down
Loading
Loading