2022-08-07 11:55:49 -06:00
|
|
|
package gql_ev
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2022-08-14 10:04:15 -06:00
|
|
|
"crypto/sha256"
|
2022-08-09 16:23:33 -06:00
|
|
|
"fmt"
|
2022-08-14 10:04:15 -06:00
|
|
|
"strings"
|
2022-08-09 16:23:33 -06:00
|
|
|
"time"
|
2022-08-07 11:55:49 -06:00
|
|
|
|
2022-08-14 10:04:15 -06:00
|
|
|
"github.com/keys-pub/keys"
|
2022-08-13 13:34:13 -06:00
|
|
|
"github.com/sour-is/ev/internal/logz"
|
2022-08-14 10:04:15 -06:00
|
|
|
"github.com/sour-is/ev/pkg/domain"
|
2022-08-09 16:23:33 -06:00
|
|
|
"github.com/sour-is/ev/pkg/es"
|
|
|
|
"github.com/sour-is/ev/pkg/msgbus"
|
2022-08-13 13:34:13 -06:00
|
|
|
"go.opentelemetry.io/otel/metric/instrument/syncint64"
|
|
|
|
"go.uber.org/multierr"
|
2022-08-07 11:55:49 -06:00
|
|
|
)
|
|
|
|
|
|
|
|
type Resolver struct {
|
2022-08-09 16:23:33 -06:00
|
|
|
es *es.EventStore
|
2022-08-13 13:34:13 -06:00
|
|
|
|
|
|
|
Mresolver_posts syncint64.Counter
|
|
|
|
Mresolver_post_added syncint64.Counter
|
|
|
|
Mresolver_post_added_event syncint64.Counter
|
2022-08-07 11:55:49 -06:00
|
|
|
}
|
|
|
|
|
2022-08-13 13:34:13 -06:00
|
|
|
func New(es *es.EventStore) (*Resolver, error) {
|
|
|
|
m := logz.Meter(context.Background())
|
|
|
|
|
|
|
|
var errs error
|
|
|
|
|
|
|
|
Mresolver_posts, err := m.SyncInt64().Counter("resolver_posts")
|
|
|
|
errs = multierr.Append(errs, err)
|
|
|
|
|
|
|
|
Mresolver_post_added, err := m.SyncInt64().Counter("resolver_post_added")
|
|
|
|
errs = multierr.Append(errs, err)
|
|
|
|
|
|
|
|
Mresolver_post_added_event, err := m.SyncInt64().Counter("resolver_post_added")
|
|
|
|
errs = multierr.Append(errs, err)
|
|
|
|
|
|
|
|
return &Resolver{
|
|
|
|
es,
|
|
|
|
Mresolver_posts,
|
|
|
|
Mresolver_post_added,
|
|
|
|
Mresolver_post_added_event,
|
|
|
|
}, errs
|
2022-08-07 11:55:49 -06:00
|
|
|
}
|
|
|
|
|
2022-08-09 16:23:33 -06:00
|
|
|
// Posts is the resolver for the events field.
|
|
|
|
func (r *Resolver) Posts(ctx context.Context, streamID string, paging *PageInput) (*Connection, error) {
|
2022-08-13 18:59:15 -06:00
|
|
|
ctx, span := logz.Span(ctx)
|
|
|
|
defer span.End()
|
|
|
|
|
2022-08-13 13:34:13 -06:00
|
|
|
r.Mresolver_posts.Add(ctx, 1)
|
|
|
|
|
2022-08-07 11:55:49 -06:00
|
|
|
lis, err := r.es.Read(ctx, streamID, paging.GetIdx(0), paging.GetCount(30))
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
edges := make([]Edge, 0, len(lis))
|
|
|
|
for i := range lis {
|
2022-08-13 18:59:15 -06:00
|
|
|
span.AddEvent(fmt.Sprint("post ", i, " of ", len(lis)))
|
2022-08-07 11:55:49 -06:00
|
|
|
e := lis[i]
|
|
|
|
m := e.EventMeta()
|
|
|
|
|
2022-08-09 16:23:33 -06:00
|
|
|
post, ok := e.(*msgbus.PostEvent)
|
2022-08-07 11:55:49 -06:00
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2022-08-09 16:23:33 -06:00
|
|
|
edges = append(edges, PostEvent{
|
2022-08-07 11:55:49 -06:00
|
|
|
ID: lis[i].EventMeta().EventID.String(),
|
|
|
|
Payload: string(post.Payload),
|
|
|
|
Tags: post.Tags,
|
|
|
|
Meta: &m,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
var first, last uint64
|
|
|
|
if first, err = r.es.FirstIndex(ctx, streamID); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if last, err = r.es.LastIndex(ctx, streamID); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &Connection{
|
|
|
|
Paging: &PageInfo{
|
|
|
|
Next: lis.Last().EventMeta().Position < last,
|
|
|
|
Prev: lis.First().EventMeta().Position > first,
|
|
|
|
Begin: lis.First().EventMeta().Position,
|
|
|
|
End: lis.Last().EventMeta().Position,
|
|
|
|
},
|
|
|
|
Edges: edges,
|
|
|
|
}, nil
|
|
|
|
}
|
2022-08-09 16:23:33 -06:00
|
|
|
|
2022-08-10 10:09:58 -06:00
|
|
|
func (r *Resolver) PostAdded(ctx context.Context, streamID string, after int64) (<-chan *PostEvent, error) {
|
2022-08-13 18:59:15 -06:00
|
|
|
ctx, span := logz.Span(ctx)
|
|
|
|
defer span.End()
|
|
|
|
|
2022-08-13 13:34:13 -06:00
|
|
|
r.Mresolver_post_added.Add(ctx, 1)
|
|
|
|
|
2022-08-09 16:23:33 -06:00
|
|
|
es := r.es.EventStream()
|
|
|
|
if es == nil {
|
|
|
|
return nil, fmt.Errorf("EventStore does not implement streaming")
|
|
|
|
}
|
|
|
|
|
2022-08-10 10:09:58 -06:00
|
|
|
sub, err := es.Subscribe(ctx, streamID, after)
|
2022-08-09 16:23:33 -06:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
ch := make(chan *PostEvent)
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
defer func() {
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
|
|
|
|
defer cancel()
|
2022-08-10 10:09:58 -06:00
|
|
|
sub.Close(ctx)
|
2022-08-09 16:23:33 -06:00
|
|
|
}()
|
|
|
|
|
|
|
|
for sub.Recv(ctx) {
|
|
|
|
events, err := sub.Events(ctx)
|
|
|
|
if err != nil {
|
|
|
|
break
|
|
|
|
}
|
2022-08-13 13:34:13 -06:00
|
|
|
r.Mresolver_post_added_event.Add(ctx, int64(len(events)))
|
|
|
|
|
2022-08-09 16:23:33 -06:00
|
|
|
for _, e := range events {
|
|
|
|
m := e.EventMeta()
|
|
|
|
if p, ok := e.(*msgbus.PostEvent); ok {
|
|
|
|
select {
|
|
|
|
case ch <- &PostEvent{
|
|
|
|
ID: m.EventID.String(),
|
|
|
|
Payload: string(p.Payload),
|
|
|
|
Tags: p.Tags,
|
|
|
|
Meta: &m,
|
|
|
|
}:
|
|
|
|
continue
|
|
|
|
case <-ctx.Done():
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
return ch, nil
|
|
|
|
}
|
2022-08-14 10:04:15 -06:00
|
|
|
|
|
|
|
func (r *Resolver) CreateSaltyUser(ctx context.Context, nick string, pub string) (*SaltyUser, error) {
|
|
|
|
streamID := fmt.Sprintf("saltyuser-%x", sha256.Sum256([]byte(strings.ToLower(nick))))
|
|
|
|
|
|
|
|
key, err := keys.NewEdX25519PublicKeyFromID(keys.ID(pub))
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
a, err := es.Create(ctx, r.es, streamID, func(ctx context.Context, agg *domain.SaltyUser) error {
|
|
|
|
return agg.OnUserRegister(nick, key)
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &SaltyUser{
|
|
|
|
Nick: nick,
|
|
|
|
Pubkey: pub,
|
|
|
|
Inbox: a.Inbox.String(),
|
|
|
|
}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *Resolver) SaltyUser(ctx context.Context, nick string) (*SaltyUser, error) {
|
|
|
|
streamID := fmt.Sprintf("saltyuser-%x", sha256.Sum256([]byte(strings.ToLower(nick))))
|
|
|
|
|
|
|
|
a, err := es.Update(ctx, r.es, streamID, func(ctx context.Context, agg *domain.SaltyUser) error { return nil })
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &SaltyUser{
|
|
|
|
Nick: nick,
|
|
|
|
Pubkey: a.Pubkey.String(),
|
|
|
|
Inbox: a.Inbox.String(),
|
|
|
|
}, err
|
|
|
|
}
|