Skip to content

Commit

Permalink
refactor reply path with partial data structure and rich content hydr…
Browse files Browse the repository at this point in the history
…ation
  • Loading branch information
Southclaws committed Nov 26, 2023
1 parent 56ca4b3 commit 01e0d57
Show file tree
Hide file tree
Showing 11 changed files with 74 additions and 98 deletions.
9 changes: 0 additions & 9 deletions app/resources/reply/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"github.com/Southclaws/fault/fctx"
"github.com/Southclaws/fault/fmsg"
"github.com/Southclaws/fault/ftag"
"github.com/Southclaws/opt"
"github.com/rs/xid"

"github.com/Southclaws/storyden/app/resources/account"
Expand All @@ -28,11 +27,8 @@ func New(db *ent.Client) Repository {

func (d *database) Create(
ctx context.Context,
body string,
authorID account.AccountID,
parentID post.ID,
replyToID opt.Optional[post.ID],
meta map[string]any,
opts ...Option,
) (*Reply, error) {
thread, err := d.db.Post.Get(ctx, xid.ID(parentID))
Expand All @@ -50,7 +46,6 @@ func (d *database) Create(

q := d.db.Post.
Create().
SetBody(string(body)).
SetFirst(false).
SetRootID(xid.ID(parentID)).
SetAuthorID(xid.ID(authorID))
Expand All @@ -59,10 +54,6 @@ func (d *database) Create(
fn(q.Mutation())
}

replyToID.Call(func(value post.ID) {
q.SetReplyToID(xid.ID(value))
})

p, err := q.Save(ctx)
if err != nil {
if ent.IsConstraintError(err) {
Expand Down
16 changes: 12 additions & 4 deletions app/resources/reply/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"

"github.com/Southclaws/dt"
"github.com/Southclaws/opt"
"github.com/rs/xid"

"github.com/Southclaws/storyden/app/resources/account"
Expand All @@ -18,11 +17,8 @@ type Option func(*ent.PostMutation)
type Repository interface {
Create(
ctx context.Context,
body string,
authorID account.AccountID,
parentID post.ID,
replyToID opt.Optional[post.ID],
meta map[string]any,
opts ...Option,
) (*Reply, error)

Expand All @@ -45,6 +41,18 @@ func WithBody(v string) Option {
}
}

func WithShort(v string) Option {
return func(pm *ent.PostMutation) {
pm.SetShort(v)
}
}

func WithReplyTo(v post.ID) Option {
return func(pm *ent.PostMutation) {
pm.SetReplyToID(xid.ID(v))
}
}

func WithMeta(meta map[string]any) Option {
return func(m *ent.PostMutation) {
m.SetMetadata(meta)
Expand Down
4 changes: 1 addition & 3 deletions app/resources/seed/post.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,11 +302,9 @@ func threads(tr thread.Repository, pr reply.Repository, rr react.Repository, ar

for _, p := range t.Posts[1:] {
p, err = pr.Create(ctx,
p.Body,
p.Author.ID,
th.ID,
nil,
nil,
reply.WithBody(p.Body),
reply.WithID(p.ID))
if err != nil {
if ent.IsConstraintError(err) {
Expand Down
4 changes: 3 additions & 1 deletion app/services/hydrator/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (

type Service interface {
HydrateThread(ctx context.Context, body, url string) []thread.Option
HydrateReply(ctx context.Context, body, url string) []reply.Option
HydrateCluster(ctx context.Context, body, url string) []cluster.Option
HydrateItem(ctx context.Context, body, url string) []item.Option
}
Expand Down Expand Up @@ -61,10 +62,11 @@ func (s *service) HydrateThread(ctx context.Context, body, url string) []thread.
}

func (s *service) HydrateReply(ctx context.Context, body, url string) []reply.Option {
_, links, assets := s.hydrate(ctx, body, url)
short, links, assets := s.hydrate(ctx, body, url)

return []reply.Option{
reply.WithAssets(assets...),
reply.WithShort(short),
reply.WithLinks(links...),
}
}
Expand Down
12 changes: 6 additions & 6 deletions app/services/reply/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"github.com/Southclaws/fault"
"github.com/Southclaws/fault/fctx"
"github.com/Southclaws/fault/fmsg"
"github.com/Southclaws/opt"

"github.com/Southclaws/storyden/app/resources/account"
"github.com/Southclaws/storyden/app/resources/post"
Expand All @@ -15,14 +14,15 @@ import (

func (s *service) Create(
ctx context.Context,
body string,
authorID account.AccountID,
parentID post.ID,
replyToID opt.Optional[post.ID],
meta map[string]any,
opts ...reply.Option,
partial Partial,
) (*reply.Reply, error) {
p, err := s.post_repo.Create(ctx, body, authorID, parentID, replyToID, meta, opts...)
opts := partial.Opts()

opts = append(opts, s.hydrate(ctx, partial)...)

p, err := s.post_repo.Create(ctx, authorID, parentID, opts...)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx), fmsg.With("failed to create reply post in thread"))
}
Expand Down
30 changes: 24 additions & 6 deletions app/services/reply/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,16 @@ import (
"github.com/Southclaws/storyden/app/resources/post"
"github.com/Southclaws/storyden/app/resources/rbac"
"github.com/Southclaws/storyden/app/resources/reply"
"github.com/Southclaws/storyden/app/services/hydrator"
)

type Service interface {
// Create a new thread in the specified category.
Create(
ctx context.Context,
body string,
authorID account.AccountID,
parentID post.ID,
replyToID opt.Optional[post.ID],
meta map[string]any,
opts ...reply.Option,
partial Partial,
) (*reply.Reply, error)

Update(ctx context.Context, threadID post.ID, partial Partial) (*reply.Reply, error)
Expand All @@ -32,8 +30,16 @@ type Service interface {
}

type Partial struct {
Body opt.Optional[string]
Meta opt.Optional[map[string]any]
Body opt.Optional[string]
ReplyTo opt.Optional[post.ID]
Meta opt.Optional[map[string]any]
}

func (p Partial) Opts() (opts []reply.Option) {
p.Body.Call(func(v string) { opts = append(opts, reply.WithBody(v)) })
p.ReplyTo.Call(func(v post.ID) { opts = append(opts, reply.WithReplyTo(v)) })
p.Meta.Call(func(v map[string]any) { opts = append(opts, reply.WithMeta(v)) })
return
}

func Build() fx.Option {
Expand All @@ -46,6 +52,7 @@ type service struct {

account_repo account.Repository
post_repo reply.Repository
hydrator hydrator.Service
}

func New(
Expand All @@ -54,11 +61,22 @@ func New(

account_repo account.Repository,
post_repo reply.Repository,
hydrator hydrator.Service,
) Service {
return &service{
l: l.With(zap.String("service", "reply")),
rbac: rbac,
account_repo: account_repo,
post_repo: post_repo,
hydrator: hydrator,
}
}

func (s *service) hydrate(ctx context.Context, partial Partial) (opts []reply.Option) {
body, bodyOK := partial.Body.Get()
if !bodyOK {
return
}

return s.hydrator.HydrateReply(ctx, body, "")
}
5 changes: 2 additions & 3 deletions app/services/reply/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,9 @@ func (s *service) Update(ctx context.Context, threadID post.ID, partial Partial)
return nil, fault.Wrap(err, fctx.With(ctx), fmsg.With("failed to authorize"))
}

opts := []reply.Option{}
opts := partial.Opts()

partial.Body.Call(func(v string) { opts = append(opts, reply.WithBody(v)) })
partial.Meta.Call(func(v map[string]any) { opts = append(opts, reply.WithMeta(v)) })
opts = append(opts, s.hydrate(ctx, partial)...)

p, err = s.post_repo.Update(ctx, threadID, opts...)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions app/services/thread/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func (s *service) Create(ctx context.Context,
thread.WithMeta(meta),
)

// BUG: partial does not have body set
opts = append(opts, s.hydrate(ctx, partial)...)

thr, err := s.thread_repo.Create(ctx,
Expand Down
52 changes: 16 additions & 36 deletions app/transports/openapi/bindings/posts.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package bindings

import (
"context"
"encoding/json"

"github.com/Southclaws/dt"
"github.com/Southclaws/fault"
Expand Down Expand Up @@ -48,36 +47,23 @@ func (p *Posts) PostCreate(ctx context.Context, request openapi.PostCreateReques
return nil, fault.Wrap(err, fctx.With(ctx))
}

var mentionReply opt.Optional[post.ID]

if request.Body.ReplyTo != nil {
tm := openapi.ParseID(*request.Body.ReplyTo)
mentionReply = opt.New(post.ID(tm))
}

var meta map[string]any
if request.Body.Meta != nil {
meta = *request.Body.Meta
partial := reply_service.Partial{
Body: opt.New(request.Body.Body),
ReplyTo: opt.Map(opt.NewPtr(request.Body.ReplyTo), deserialisePostID),
Meta: opt.NewPtr((*map[string]any)(request.Body.Meta)),
}

post, err := p.reply_svc.Create(ctx,
request.Body.Body,
accountID,
postID,
mentionReply,
meta,
partial,
)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}

sp, err := serialisePost(post)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}

return openapi.PostCreate200JSONResponse{
PostCreateOKJSONResponse: openapi.PostCreateOKJSONResponse(sp),
PostCreateOKJSONResponse: openapi.PostCreateOKJSONResponse(serialisePost(post)),
}, nil
}

Expand All @@ -87,25 +73,18 @@ func (p *Posts) PostUpdate(ctx context.Context, request openapi.PostUpdateReques
return nil, fault.Wrap(err, fctx.With(ctx))
}

jsonBody, err := json.Marshal(request.Body.Body)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
partial := reply_service.Partial{
Body: opt.NewPtr(request.Body.Body),
Meta: opt.NewPtr((*map[string]any)(request.Body.Meta)),
}

post, err := p.reply_svc.Update(ctx, postID, reply_service.Partial{
Body: opt.New(string(jsonBody)),
})
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}

sp, err := serialisePost(post)
post, err := p.reply_svc.Update(ctx, postID, partial)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}

return openapi.PostUpdate200JSONResponse{
PostUpdateOKJSONResponse: openapi.PostUpdateOKJSONResponse(sp),
PostUpdateOKJSONResponse: openapi.PostUpdateOKJSONResponse(serialisePost(post)),
}, nil
}

Expand Down Expand Up @@ -140,10 +119,7 @@ func (p *Posts) PostSearch(ctx context.Context, request openapi.PostSearchReques
return nil, fault.Wrap(err, fctx.With(ctx))
}

results, err := dt.MapErr(posts, serialisePost)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}
results := dt.Map(posts, serialisePost)

return openapi.PostSearch200JSONResponse{
PostSearchOKJSONResponse: openapi.PostSearchOKJSONResponse{
Expand All @@ -153,6 +129,10 @@ func (p *Posts) PostSearch(ctx context.Context, request openapi.PostSearchReques
}, nil
}

func deserialisePostID(s string) post.ID {
return post.ID(openapi.ParseID(s))
}

func deserialiseContentKinds(in openapi.ContentKinds) ([]post_search.Kind, error) {
out, err := dt.MapErr(in, deserialiseContentKind)
if err != nil {
Expand Down
21 changes: 3 additions & 18 deletions app/transports/openapi/bindings/threads.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,8 @@ func (i *Threads) ThreadCreate(ctx context.Context, request openapi.ThreadCreate
return nil, fault.Wrap(err, fctx.With(ctx))
}

sp, err := serialiseThread(thread)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}

return openapi.ThreadCreate200JSONResponse{
ThreadCreateOKJSONResponse: openapi.ThreadCreateOKJSONResponse(*sp),
ThreadCreateOKJSONResponse: openapi.ThreadCreateOKJSONResponse(serialiseThread(thread)),
}, nil
}

Expand All @@ -101,13 +96,8 @@ func (i *Threads) ThreadUpdate(ctx context.Context, request openapi.ThreadUpdate
return nil, fault.Wrap(err, fctx.With(ctx))
}

sp, err := serialiseThread(thread)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}

return openapi.ThreadUpdate200JSONResponse{
ThreadUpdateOKJSONResponse: openapi.ThreadUpdateOKJSONResponse(*sp),
ThreadUpdateOKJSONResponse: openapi.ThreadUpdateOKJSONResponse(serialiseThread(thread)),
}, nil
}

Expand Down Expand Up @@ -172,13 +162,8 @@ func (i *Threads) ThreadGet(ctx context.Context, request openapi.ThreadGetReques
return nil, fault.Wrap(err, fctx.With(ctx))
}

sp, err := serialiseThread(thread)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}

return openapi.ThreadGet200JSONResponse{
ThreadGetJSONResponse: openapi.ThreadGetJSONResponse(*sp),
ThreadGetJSONResponse: openapi.ThreadGetJSONResponse(serialiseThread(thread)),
}, nil
}

Expand Down
Loading

0 comments on commit 01e0d57

Please sign in to comment.