feat: distribute new local posts to followers via websocket

This commit is contained in:
sam 2023-10-15 21:39:50 +02:00
parent 5c6da51234
commit 97b05d787f
6 changed files with 107 additions and 75 deletions

View file

@ -1,9 +1,14 @@
package processor
import (
"context"
"time"
"git.sleepycat.moe/sam/mercury/internal/database"
"git.sleepycat.moe/sam/mercury/internal/database/sql"
"git.sleepycat.moe/sam/mercury/internal/streaming"
"git.sleepycat.moe/sam/mercury/web/api"
"github.com/rs/zerolog/log"
)
type Processor struct {
@ -14,7 +19,7 @@ type Processor struct {
func New(db *sql.Base) *Processor {
p := &Processor{
SocketHolder: &streaming.SocketHolder{},
SocketHolder: streaming.NewSocketHolder(),
db: db,
}
@ -23,5 +28,54 @@ func New(db *sql.Base) *Processor {
}
func (p *Processor) HandlePost(post database.Post) {
// this function is spun off in a separate goroutine, so we shouldn't use the same context as the parent request
// TODO: make timeout configurable?
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
conn, err := p.db.Acquire(ctx)
if err != nil {
log.Err(err).Msg("acquiring database")
return
}
defer conn.Release()
// get the blog and their followers
blog, err := sql.NewBlogStore(conn).ByID(ctx, post.BlogID)
if err != nil {
log.Err(err).Msg("getting blog")
return
}
acct, err := sql.NewAccountStore(conn).ByID(ctx, blog.AccountID)
if err != nil {
log.Err(err).Msg("getting account")
return
}
followers, err := sql.NewBlogStore(conn).Followers(ctx, blog.ID)
if err != nil {
log.Err(err).Msg("getting followers")
return
}
p.handlePostLocal(ctx, post, blog, acct, followers)
}
// handlePostLocal handles a post on the local side--mostly sending notifications to websockets.
// All posts go through this function.
func (p *Processor) handlePostLocal(
ctx context.Context, post database.Post,
blog database.Blog, acct database.Account,
followers []sql.BlogFollower,
) {
// send to self
apiPost := api.DBPostToPost(post, blog, acct)
p.SocketHolder.Send(acct.ID, streaming.EventTypePost, apiPost)
for _, follower := range followers {
if !follower.IsLocal {
continue
}
p.SocketHolder.Send(follower.AccountID, streaming.EventTypePost, apiPost)
}
}