Skip to content

Commit

Permalink
Merge pull request #33 from GreenTeaProgrammers/feature/backend/api
Browse files Browse the repository at this point in the history
feat:apiを実装
  • Loading branch information
KinjiKawaguchi authored Feb 12, 2024
2 parents ab96f01 + ee03718 commit 4c52f27
Show file tree
Hide file tree
Showing 13 changed files with 503 additions and 1 deletion.
7 changes: 7 additions & 0 deletions backend/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
DSN=
DB_USER_NAME=
DB_PASSWORD=
DB_ADDR=
DB_NAME=
PORT=
MODE_DEV=
3 changes: 2 additions & 1 deletion backend/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ require google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31
require (
github.com/golang/protobuf v1.5.3 // indirect
golang.org/x/net v0.18.0 // indirect
golang.org/x/sys v0.14.0 // indirect
golang.org/x/sys v0.17.0 // indirect
google.golang.org/grpc v1.61.0
google.golang.org/protobuf v1.31.0
)
Expand All @@ -30,6 +30,7 @@ require (
github.com/kelseyhightower/envconfig v1.4.0
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
github.com/zclconf/go-cty v1.8.0 // indirect
golang.org/x/crypto v0.19.0
golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3
golang.org/x/mod v0.14.0 // indirect
golang.org/x/text v0.14.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions backend/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgq
github.com/zclconf/go-cty v1.8.0 h1:s4AvqaeQzJIu3ndv4gVIhplVD0krU+bgrcLSVUnaWuA=
github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3 h1:/RIbNt/Zr7rVhIkQhooTxCxFcdWLGIKnZA4IXNFSrvo=
golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
Expand All @@ -69,6 +71,8 @@ golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
Expand Down
21 changes: 21 additions & 0 deletions backend/gprc_server/grpc_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import (

grpc_interfaces "github.com/GreenTeaProgrammers/WhereChildBus/backend/interfaces"
pb "github.com/GreenTeaProgrammers/WhereChildBus/backend/proto-gen/go/where_child_bus/v1"
"github.com/GreenTeaProgrammers/WhereChildBus/backend/usecases/bus"
"github.com/GreenTeaProgrammers/WhereChildBus/backend/usecases/child"
"github.com/GreenTeaProgrammers/WhereChildBus/backend/usecases/guardian"
"github.com/GreenTeaProgrammers/WhereChildBus/backend/usecases/nursery"
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging"
"golang.org/x/exp/slog"
"google.golang.org/grpc"
Expand All @@ -28,9 +32,26 @@ func New(opts ...optionFunc) *grpc.Server {
if opt.useReflection {
reflection.Register(srv)
}

busInteractor := bus.NewInteractor(opt.entClient, opt.logger)
busSrv := grpc_interfaces.NewBusServiceServer(busInteractor)
pb.RegisterBusServiceServer(srv, busSrv)

childInteractor := child.NewInteractor(opt.entClient, opt.logger)
childSrv := grpc_interfaces.NewChildServiceServer(childInteractor)
pb.RegisterChildServiceServer(srv, childSrv)

guardianInteractor := guardian.NewInteractor(opt.entClient, opt.logger)
guardianSrv := grpc_interfaces.NewGuardianServiceServer(guardianInteractor)
pb.RegisterGuardianServiceServer(srv, guardianSrv)

healthcheckSrv := grpc_interfaces.NewHealthcheckServiceServer()
pb.RegisterHealthcheckServiceServer(srv, healthcheckSrv)

nurseryInteractor := nursery.NewInteractor(opt.entClient, opt.logger)
nurserySrv := grpc_interfaces.NewNurseryServiceServer(nurseryInteractor)
pb.RegisterNurseryServiceServer(srv, nurserySrv)

return srv
}

Expand Down
21 changes: 21 additions & 0 deletions backend/interfaces/bus.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package interfaces

import (
"context"

pb "github.com/GreenTeaProgrammers/WhereChildBus/backend/proto-gen/go/where_child_bus/v1"
"github.com/GreenTeaProgrammers/WhereChildBus/backend/usecases/bus"
)

type busServiceServer struct {
interactor *bus.Interactor
}

func NewBusServiceServer(interactor *bus.Interactor) pb.BusServiceServer {
return &busServiceServer{interactor}
}

// GetBusListByNurseryId implements where_child_busv1.BusServiceServer.
func (s *busServiceServer) GetBusListByNurseryId(ctx context.Context, req *pb.GetBusListByNurseryIdRequest) (*pb.GetBusListByNurseryIdResponse, error) {
return s.interactor.GetBusListByNurseryID(ctx, req)
}
26 changes: 26 additions & 0 deletions backend/interfaces/child.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package interfaces

import (
"context"

pb "github.com/GreenTeaProgrammers/WhereChildBus/backend/proto-gen/go/where_child_bus/v1"
"github.com/GreenTeaProgrammers/WhereChildBus/backend/usecases/child"
)

type childServiceServer struct {
interactor *child.Interactor
}

func NewChildServiceServer(interactor *child.Interactor) pb.ChildServiceServer {
return &childServiceServer{interactor}
}

// GetChildListByGuardianID implements where_child_busv1.ChildServiceServer.
func (s *childServiceServer) GetChildListByGuardianID(ctx context.Context, req *pb.GetChildListByGuardianIDRequest) (*pb.GetChildListByGuardianIDResponse, error) {
return s.interactor.GetChildListByGuardianID(ctx, req)
}

// GetChildListByNurseryID implements where_child_busv1.ChildServiceServer.
func (s *childServiceServer) GetChildListByNurseryID(ctx context.Context, req *pb.GetChildListByNurseryIDRequest) (*pb.GetChildListByNurseryIDResponse, error) {
return s.interactor.GetChildListByNurseryID(ctx, req)
}
21 changes: 21 additions & 0 deletions backend/interfaces/guardian.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package interfaces

import (
"context"

pb "github.com/GreenTeaProgrammers/WhereChildBus/backend/proto-gen/go/where_child_bus/v1"
"github.com/GreenTeaProgrammers/WhereChildBus/backend/usecases/guardian"
)

type guardianServiceServer struct {
interactor *guardian.Interactor
}

func NewGuardianServiceServer(interactor *guardian.Interactor) pb.GuardianServiceServer {
return &guardianServiceServer{interactor}
}

// GuardianLogin implements where_child_busv1.GuardianServiceServer.
func (s *guardianServiceServer) GuardianLogin(ctx context.Context, req *pb.GuardianLoginRequest) (*pb.GuardianLoginResponse, error) {
return s.interactor.GuardianLogin(ctx, req)
}
20 changes: 20 additions & 0 deletions backend/interfaces/nursery.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package interfaces

import (
"context"

pb "github.com/GreenTeaProgrammers/WhereChildBus/backend/proto-gen/go/where_child_bus/v1"
"github.com/GreenTeaProgrammers/WhereChildBus/backend/usecases/nursery"
)

type nurseryServiceServer struct {
interactor *nursery.Interactor
}

func NewNurseryServiceServer(interactor *nursery.Interactor) pb.NurseryServiceServer {
return &nurseryServiceServer{interactor}
}

func (s *nurseryServiceServer) NurseryLogin(ctx context.Context, req *pb.NurseryLoginRequest) (*pb.NurseryLoginResponse, error) {
return s.interactor.NurseryLogin(ctx, req)
}
72 changes: 72 additions & 0 deletions backend/usecases/bus/bus.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package bus

import (
"fmt"

"github.com/google/uuid"
"golang.org/x/exp/slog"

"context"

pb "github.com/GreenTeaProgrammers/WhereChildBus/backend/proto-gen/go/where_child_bus/v1"
"github.com/GreenTeaProgrammers/WhereChildBus/backend/usecases/utils"

"github.com/GreenTeaProgrammers/WhereChildBus/backend/domain/repository/ent"
busRepo "github.com/GreenTeaProgrammers/WhereChildBus/backend/domain/repository/ent/bus"
nurseryRepo "github.com/GreenTeaProgrammers/WhereChildBus/backend/domain/repository/ent/nursery"
)

type Interactor struct {
entClient *ent.Client
logger *slog.Logger
}

func NewInteractor(entClient *ent.Client, logger *slog.Logger) *Interactor {
return &Interactor{entClient, logger}
}

func (i *Interactor) GetBusListByNurseryID(ctx context.Context, req *pb.GetBusListByNurseryIdRequest) (*pb.GetBusListByNurseryIdResponse, error) {
nurseryID, err := uuid.Parse(req.NurseryId)
if err != nil {
return nil, fmt.Errorf("failed to parse nursery ID '%s': %w", req.NurseryId, err)
}

buses, err := i.getBusList(ctx, func(tx *ent.Tx) (*ent.BusQuery, error) {
return tx.Bus.Query().Where(busRepo.HasNurseryWith(nurseryRepo.IDEQ(nurseryID))), nil
})

if err != nil {
return nil, err
}

return &pb.GetBusListByNurseryIdResponse{Buses: buses}, nil
}

func (i *Interactor) getBusList(ctx context.Context, queryFunc func(*ent.Tx) (*ent.BusQuery, error)) ([]*pb.Bus, error) {
tx, err := i.entClient.Tx(ctx)
if err != nil {
return nil, fmt.Errorf("failed to start transaction: %w", err)
}
defer tx.Rollback()

query, err := queryFunc(tx)
if err != nil {
return nil, fmt.Errorf("failed to create query: %w", err)
}

entBuses, err := query.All(ctx)
if err != nil {
return nil, fmt.Errorf("failed to execute query: %w", err)
}

pbBuses := make([]*pb.Bus, len(entBuses))
for i, b := range entBuses {
pbBuses[i] = utils.ToPbBus(b)
}

if err := tx.Commit(); err != nil {
return nil, fmt.Errorf("failed to commit transaction: %w", err)
}

return pbBuses, nil
}
91 changes: 91 additions & 0 deletions backend/usecases/child/child.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package child

import (
"fmt"

"github.com/google/uuid"
"golang.org/x/exp/slog"

"context"

pb "github.com/GreenTeaProgrammers/WhereChildBus/backend/proto-gen/go/where_child_bus/v1"
"github.com/GreenTeaProgrammers/WhereChildBus/backend/usecases/utils"

"github.com/GreenTeaProgrammers/WhereChildBus/backend/domain/repository/ent"
childRepo "github.com/GreenTeaProgrammers/WhereChildBus/backend/domain/repository/ent/child"
guardianRepo "github.com/GreenTeaProgrammers/WhereChildBus/backend/domain/repository/ent/guardian"
nurseryRepo "github.com/GreenTeaProgrammers/WhereChildBus/backend/domain/repository/ent/nursery"
)

type Interactor struct {
entClient *ent.Client
logger *slog.Logger
}

func NewInteractor(entClient *ent.Client, logger *slog.Logger) *Interactor {
return &Interactor{entClient, logger}
}

func (i *Interactor) GetChildListByGuardianID(ctx context.Context, req *pb.GetChildListByGuardianIDRequest) (*pb.GetChildListByGuardianIDResponse, error) {
guardianID, err := uuid.Parse(req.GuardianId)
if err != nil {
return nil, fmt.Errorf("failed to parse guardian ID '%s': %w", req.GuardianId, err)
}

children, err := i.getChildList(ctx, func(tx *ent.Tx) (*ent.ChildQuery, error) {
return tx.Child.Query().Where(childRepo.HasGuardianWith(guardianRepo.IDEQ(guardianID))), nil
})

if err != nil {
return nil, err
}

return &pb.GetChildListByGuardianIDResponse{Children: children}, nil
}

func (i *Interactor) GetChildListByNurseryID(ctx context.Context, req *pb.GetChildListByNurseryIDRequest) (*pb.GetChildListByNurseryIDResponse, error) {
nurseryID, err := uuid.Parse(req.NurseryId)
if err != nil {
return nil, fmt.Errorf("failed to parse nursery ID '%s': %w", req.NurseryId, err)
}

children, err := i.getChildList(ctx, func(tx *ent.Tx) (*ent.ChildQuery, error) {
return tx.Child.Query().Where(childRepo.HasNurseryWith(nurseryRepo.IDEQ(nurseryID))), nil
})

if err != nil {
return nil, err
}

return &pb.GetChildListByNurseryIDResponse{Children: children}, nil
}

// getChildList abstracts the common logic for fetching child lists.
func (i *Interactor) getChildList(ctx context.Context, queryFunc func(*ent.Tx) (*ent.ChildQuery, error)) ([]*pb.Child, error) {
tx, err := i.entClient.Tx(ctx)
if err != nil {
return nil, fmt.Errorf("failed to start transaction: %w", err)
}
defer tx.Rollback() // Rollback is safe to call even if the tx is already committed.

query, err := queryFunc(tx)
if err != nil {
return nil, err
}

entChildren, err := query.All(ctx)
if err != nil {
return nil, fmt.Errorf("query failed: %w", err)
}

pbChildren := make([]*pb.Child, len(entChildren))
for i, c := range entChildren {
pbChildren[i] = utils.ToPbChild(c)
}

if err := tx.Commit(); err != nil {
return nil, fmt.Errorf("failed to commit transaction: %w", err)
}

return pbChildren, nil
}
Loading

0 comments on commit 4c52f27

Please sign in to comment.