v0.0.31 Корректно сгенерирован резолвер получения Author для клипов
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
73946da723
commit
c7e109fe99
2
.env
2
.env
@ -13,4 +13,4 @@ SMTP_FROM=info@tailly.ru
|
||||
AppURL="https://tailly.ru"
|
||||
MESSAGE_SERVICE_ADDRESS="tailly_messages:50052"
|
||||
SUBSCRIBE_SERVICE_ADDRESS="tailly_subscribers:50053"
|
||||
CLIP_SERVICE_ADDRESS="tailly_clips:50054"
|
||||
CLIP_SERVICE_ADDRESS="localhost:50054"
|
||||
@ -8,7 +8,6 @@ type Clip struct {
|
||||
VideoURL string `json:"videoUrl"`
|
||||
ThumbnailURL string `json:"thumbnailUrl"`
|
||||
AuthorID int `json:"-"`
|
||||
Author *User `json:"author"`
|
||||
LikesCount int `json:"likesCount"`
|
||||
CommentsCount int `json:"commentsCount"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
|
||||
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"tailly_back_v2/internal/domain"
|
||||
"tailly_back_v2/proto"
|
||||
"time"
|
||||
@ -31,47 +30,15 @@ func (r *clipResolver) IsLiked(ctx context.Context, obj *domain.Clip) (bool, err
|
||||
}
|
||||
|
||||
func (r *clipResolver) Author(ctx context.Context, obj *domain.Clip) (*domain.User, error) {
|
||||
log.Printf("Resolving author for clip %d, authorID: %d", obj.ID, obj.AuthorID)
|
||||
|
||||
if obj.AuthorID == 0 {
|
||||
log.Printf("WARNING: Clip %d has no authorID, returning stub", obj.ID)
|
||||
return &domain.User{
|
||||
ID: 0,
|
||||
Username: "Unknown User",
|
||||
Avatar: "/img/logo.png",
|
||||
Email: "unknown@example.com",
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
}, nil
|
||||
return nil, fmt.Errorf("clip has no author ID")
|
||||
}
|
||||
|
||||
// Получаем пользователя из сервиса
|
||||
author, err := r.Services.User.GetByID(ctx, obj.AuthorID)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: Failed to get author %d for clip %d: %v", obj.AuthorID, obj.ID, err)
|
||||
return &domain.User{
|
||||
ID: obj.AuthorID,
|
||||
Username: "Error Loading User",
|
||||
Avatar: "/img/logo.png",
|
||||
Email: "error@example.com",
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
}, nil
|
||||
}
|
||||
log.Printf("Resolved author for clip %d", author)
|
||||
if author == nil {
|
||||
log.Printf("WARNING: Author %d not found for clip %d", obj.AuthorID, obj.ID)
|
||||
return &domain.User{
|
||||
ID: obj.AuthorID,
|
||||
Username: "Deleted User",
|
||||
Avatar: "/img/logo.png",
|
||||
Email: "deleted@example.com",
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
}, nil
|
||||
return nil, fmt.Errorf("failed to get author: %w", err)
|
||||
}
|
||||
|
||||
log.Printf("Successfully resolved author %d for clip %d", obj.AuthorID, obj.ID)
|
||||
return author, nil
|
||||
}
|
||||
|
||||
@ -252,24 +219,10 @@ func (r *queryResolver) Clips(ctx context.Context, limit *int, offset *int) ([]*
|
||||
Offset: int32(offsetVal),
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("ERROR: Failed to get clips from gRPC service: %v", err)
|
||||
return nil, fmt.Errorf("failed to get clips: %w", err)
|
||||
}
|
||||
|
||||
clips := r.protoClipsToDomain(resp.Clips)
|
||||
|
||||
// Детальное логирование
|
||||
log.Printf("Retrieved %d clips from gRPC service", len(clips))
|
||||
for i, clip := range clips {
|
||||
log.Printf("Clip %d: ID=%d, Title=%s, AuthorID=%d", i, clip.ID, clip.Title, clip.AuthorID)
|
||||
|
||||
// Проверяем, что AuthorID заполнен
|
||||
if clip.AuthorID == 0 {
|
||||
log.Printf("ERROR: Clip %d has AuthorID=0!", clip.ID)
|
||||
}
|
||||
}
|
||||
|
||||
return clips, nil
|
||||
return r.protoClipsToDomain(resp.Clips), nil
|
||||
}
|
||||
|
||||
// UserClips is the resolver for the userClips field.
|
||||
|
||||
@ -303,6 +303,8 @@ type ChatResolver interface {
|
||||
UpdatedAt(ctx context.Context, obj *domain.Chat) (string, error)
|
||||
}
|
||||
type ClipResolver interface {
|
||||
Author(ctx context.Context, obj *domain.Clip) (*domain.User, error)
|
||||
|
||||
IsLiked(ctx context.Context, obj *domain.Clip) (bool, error)
|
||||
CreatedAt(ctx context.Context, obj *domain.Clip) (string, error)
|
||||
UpdatedAt(ctx context.Context, obj *domain.Clip) (string, error)
|
||||
@ -3274,7 +3276,7 @@ func (ec *executionContext) _Clip_author(ctx context.Context, field graphql.Coll
|
||||
}()
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Author, nil
|
||||
return ec.resolvers.Clip().Author(rctx, obj)
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
@ -3295,8 +3297,8 @@ func (ec *executionContext) fieldContext_Clip_author(_ context.Context, field gr
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "Clip",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
IsMethod: true,
|
||||
IsResolver: true,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
switch field.Name {
|
||||
case "id":
|
||||
@ -13905,10 +13907,41 @@ func (ec *executionContext) _Clip(ctx context.Context, sel ast.SelectionSet, obj
|
||||
atomic.AddUint32(&out.Invalids, 1)
|
||||
}
|
||||
case "author":
|
||||
out.Values[i] = ec._Clip_author(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
atomic.AddUint32(&out.Invalids, 1)
|
||||
field := field
|
||||
|
||||
innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
}
|
||||
}()
|
||||
res = ec._Clip_author(ctx, field, obj)
|
||||
if res == graphql.Null {
|
||||
atomic.AddUint32(&fs.Invalids, 1)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
if field.Deferrable != nil {
|
||||
dfs, ok := deferred[field.Deferrable.Label]
|
||||
di := 0
|
||||
if ok {
|
||||
dfs.AddField(field)
|
||||
di = len(dfs.Values) - 1
|
||||
} else {
|
||||
dfs = graphql.NewFieldSet([]graphql.CollectedField{field})
|
||||
deferred[field.Deferrable.Label] = dfs
|
||||
}
|
||||
dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler {
|
||||
return innerFunc(ctx, dfs)
|
||||
})
|
||||
|
||||
// don't run the out.Concurrently() call below
|
||||
out.Values[i] = graphql.Null
|
||||
continue
|
||||
}
|
||||
|
||||
out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
|
||||
case "commentsCount":
|
||||
out.Values[i] = ec._Clip_commentsCount(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user