307 lines
8.7 KiB
Go
307 lines
8.7 KiB
Go
package frontapi
|
|
|
|
import (
|
|
"context"
|
|
genCharacter "crossnokaye-interview-assignment/services/character/gen/character"
|
|
genCharacterClient "crossnokaye-interview-assignment/services/character/gen/grpc/character/client"
|
|
front "crossnokaye-interview-assignment/services/front/gen/front"
|
|
genInventoryClient "crossnokaye-interview-assignment/services/inventory/gen/grpc/inventory/client"
|
|
genInventory "crossnokaye-interview-assignment/services/inventory/gen/inventory"
|
|
genItemClient "crossnokaye-interview-assignment/services/item/gen/grpc/item/client"
|
|
genItem "crossnokaye-interview-assignment/services/item/gen/item"
|
|
"errors"
|
|
"fmt"
|
|
"github.com/golang/protobuf/ptypes/empty"
|
|
goa "goa.design/goa/v3/pkg"
|
|
"google.golang.org/grpc"
|
|
"log"
|
|
)
|
|
|
|
type itemClient struct {
|
|
getItem goa.Endpoint
|
|
listItems goa.Endpoint
|
|
createItem goa.Endpoint
|
|
updateItem goa.Endpoint
|
|
deleteItem goa.Endpoint
|
|
}
|
|
|
|
type characterClient struct {
|
|
getCharacter goa.Endpoint
|
|
listCharacters goa.Endpoint
|
|
createCharacter goa.Endpoint
|
|
updateCharacter goa.Endpoint
|
|
deleteCharacter goa.Endpoint
|
|
}
|
|
|
|
type inventoryClient struct {
|
|
addItem goa.Endpoint
|
|
removeItem goa.Endpoint
|
|
removeAll goa.Endpoint
|
|
listInventoryItems goa.Endpoint
|
|
listCharactersWithItem goa.Endpoint
|
|
}
|
|
|
|
// front service example implementation.
|
|
// The example methods log the requests and return zero values.
|
|
type frontsrvc struct {
|
|
logger *log.Logger
|
|
|
|
itemClient *itemClient
|
|
characterClient *characterClient
|
|
inventoryClient *inventoryClient
|
|
}
|
|
|
|
// NewFront returns the front service implementation.
|
|
func NewFront(logger *log.Logger, itemClientConnection *grpc.ClientConn, characterClientConnection *grpc.ClientConn,
|
|
inventoryClientConnection *grpc.ClientConn) front.Service {
|
|
|
|
ic := genItemClient.NewClient(itemClientConnection)
|
|
cc := genCharacterClient.NewClient(characterClientConnection)
|
|
icc := genInventoryClient.NewClient(inventoryClientConnection)
|
|
return &frontsrvc{logger: logger,
|
|
itemClient: &itemClient{
|
|
ic.GetItem(),
|
|
ic.ListItems(),
|
|
ic.CreateItem(),
|
|
ic.UpdateItem(),
|
|
ic.DeleteItem()},
|
|
characterClient: &characterClient{
|
|
cc.GetCharacter(),
|
|
cc.ListCharacters(),
|
|
cc.CreateCharacter(),
|
|
cc.UpdateCharacter(),
|
|
cc.DeleteCharacter()},
|
|
inventoryClient: &inventoryClient{
|
|
icc.AddItem(),
|
|
icc.RemoveItem(),
|
|
icc.RemoveAll(),
|
|
icc.ListInventory(),
|
|
icc.ListCharactersWithItem(),
|
|
}}
|
|
}
|
|
|
|
// GetItem implements getItem.
|
|
func (s *frontsrvc) GetItem(ctx context.Context, name string) (res *front.Item, err error) {
|
|
s.logger.Print("front.getItem")
|
|
getItemResponse, err := s.itemClient.getItem(ctx, &genItem.GetItemPayload{Name: &name})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
item := getItemResponse.(*genItem.Item)
|
|
res = (*front.Item)(item)
|
|
return
|
|
}
|
|
|
|
func (s *frontsrvc) ListItems(ctx context.Context) (res []*front.Item, err error) {
|
|
s.logger.Print("front.listItems")
|
|
listItemsResponse, err := s.itemClient.listItems(ctx, &genItem.ListItemsPayload{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
items := listItemsResponse.([]*genItem.Item)
|
|
for _, itemToReturn := range items {
|
|
res = append(res, (*front.Item)(itemToReturn))
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// CreateItem implements createItem.
|
|
func (s *frontsrvc) CreateItem(ctx context.Context, p *front.Item) (res *front.Item, err error) {
|
|
s.logger.Print("front.createItem")
|
|
createItemResponse, err := s.itemClient.createItem(ctx, (*genItem.Item)(p))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
item := createItemResponse.(*genItem.Item)
|
|
res = (*front.Item)(item)
|
|
return
|
|
}
|
|
|
|
// UpdateItem implements updateItem.
|
|
func (s *frontsrvc) UpdateItem(ctx context.Context, p *front.Item) (res *front.Item, err error) {
|
|
s.logger.Print("front.updateItem")
|
|
updateItemResponse, err := s.itemClient.updateItem(ctx, (*genItem.Item)(p))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
item := updateItemResponse.(*genItem.Item)
|
|
res = (*front.Item)(item)
|
|
return
|
|
}
|
|
|
|
// DeleteItem implements deleteItem.
|
|
func (s *frontsrvc) DeleteItem(ctx context.Context, p string) (err error) {
|
|
s.logger.Print("front.deleteItem")
|
|
|
|
characterResponse, err := s.inventoryClient.listCharactersWithItem(ctx, &genInventory.ListCharactersWithItemPayload{ItemName: &p})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
characters := characterResponse.([]string)
|
|
|
|
if len(characters) > 0 {
|
|
return front.MakeBadRequest(fmt.Errorf("item '%s' is referenced by character(s) %v", p, characters))
|
|
}
|
|
|
|
_, err = s.itemClient.deleteItem(ctx, &genItem.DeleteItemPayload{Name: &p})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// GetCharacter implements getCharacter.
|
|
func (s *frontsrvc) GetCharacter(ctx context.Context, name string) (res *front.Character, err error) {
|
|
s.logger.Print("front.getCharacter")
|
|
getCharacterResponse, err := s.characterClient.getCharacter(ctx, &genCharacter.GetCharacterPayload{Name: &name})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
character := getCharacterResponse.(*genCharacter.Character)
|
|
res = (*front.Character)(character)
|
|
return
|
|
}
|
|
|
|
func (s *frontsrvc) ListCharacters(ctx context.Context) (res []*front.Character, err error) {
|
|
s.logger.Print("front.listCharacters")
|
|
listCharactersResponse, err := s.characterClient.listCharacters(ctx, empty.Empty{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
characters := listCharactersResponse.([]*genCharacter.Character)
|
|
for _, itemToReturn := range characters {
|
|
res = append(res, (*front.Character)(itemToReturn))
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// CreateCharacter implements createCharacter.
|
|
func (s *frontsrvc) CreateCharacter(ctx context.Context, p *front.Character) (res *front.Character, err error) {
|
|
s.logger.Print("front.createCharacter")
|
|
createCharacterResponse, err := s.characterClient.createCharacter(ctx, (*genCharacter.Character)(p))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
character := createCharacterResponse.(*genCharacter.Character)
|
|
res = (*front.Character)(character)
|
|
return
|
|
}
|
|
|
|
// UpdateCharacter implements updateCharacter.
|
|
func (s *frontsrvc) UpdateCharacter(ctx context.Context, p *front.Character) (res *front.Character, err error) {
|
|
s.logger.Print("front.updateCharacter")
|
|
updateCharacterResponse, err := s.characterClient.updateCharacter(ctx, (*genCharacter.Character)(p))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
character := updateCharacterResponse.(*genCharacter.Character)
|
|
res = (*front.Character)(character)
|
|
|
|
return
|
|
}
|
|
|
|
// DeleteCharacter implements deleteCharacter.
|
|
func (s *frontsrvc) DeleteCharacter(ctx context.Context, name string) (err error) {
|
|
s.logger.Print("front.deleteCharacter")
|
|
|
|
_, err = s.characterClient.deleteCharacter(ctx, &genCharacter.DeleteCharacterPayload{Name: &name})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = s.inventoryClient.removeAll(ctx, &genInventory.RemoveAllPayload{CharacterName: &name})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// AddItemToInventory implements addItemToInventory.
|
|
func (s *frontsrvc) AddItemToInventory(ctx context.Context, p *front.InventoryRecord) (err error) {
|
|
s.logger.Print("front.addItemToInventory")
|
|
|
|
err = s.checkItemAndCharacter(ctx, p)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = s.inventoryClient.addItem(ctx, (*genInventory.InventoryRecord)(p))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// RemoveItemFromInventory implements removeItemFromInventory.
|
|
func (s *frontsrvc) RemoveItemFromInventory(ctx context.Context, p *front.InventoryRecord) (err error) {
|
|
s.logger.Print("front.removeItemFromInventory")
|
|
|
|
err = s.checkItemAndCharacter(ctx, p)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = s.inventoryClient.removeItem(ctx, (*genInventory.InventoryRecord)(p))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (s *frontsrvc) ListInventoryItems(ctx context.Context, payload *front.ListInventoryItemsPayload) (res []*front.Item, err error) {
|
|
listInventoryResponse, err := s.inventoryClient.listInventoryItems(ctx,
|
|
&genInventory.ListInventoryPayload{CharacterName: payload.CharacterName})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
itemNames := listInventoryResponse.([]string)
|
|
if len(itemNames) == 0 {
|
|
return
|
|
}
|
|
itemResponse, err := s.itemClient.listItems(ctx, &genItem.ListItemsPayload{NameFilter: itemNames})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
items := itemResponse.([]*genItem.Item)
|
|
for _, value := range items {
|
|
res = append(res, (*front.Item)(value))
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (s *frontsrvc) checkItemAndCharacter(ctx context.Context, payload *front.InventoryRecord) (err error) {
|
|
getItemResponse, err := s.itemClient.getItem(ctx, &genItem.GetItemPayload{Name: &payload.ItemName})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if getItemResponse.(*genItem.Item) == nil {
|
|
return errors.New("item not found")
|
|
}
|
|
|
|
getCharacterResponse, err := s.characterClient.getCharacter(ctx,
|
|
&genCharacter.GetCharacterPayload{Name: &payload.CharacterName})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if getCharacterResponse.(*genCharacter.Character) == nil {
|
|
return errors.New("character not found")
|
|
}
|
|
return
|
|
}
|