refactor: workers

This commit is contained in:
DevMiner 2024-08-29 00:46:32 +02:00
parent 02ad720439
commit 8fa44e5f72
20 changed files with 764 additions and 465 deletions

View file

@ -89,6 +89,10 @@ func (i *ManagerImpl) Atomic(ctx context.Context, fn func(ctx context.Context, t
return tx.Finish()
}
func (i *ManagerImpl) Ping() error {
return i.db.Ping()
}
func (i *ManagerImpl) Users() repository.UserRepository {
return i.users
}

View file

@ -51,6 +51,7 @@ type InstanceMetadataRepository interface {
type Manager interface {
Atomic(ctx context.Context, fn func(ctx context.Context, tx Manager) error) error
Ping() error
Users() UserRepository
Notes() NoteRepository

View file

@ -2,6 +2,7 @@ package service
import (
"context"
"github.com/gofiber/fiber/v2"
"github.com/versia-pub/versia-go/internal/repository"
"github.com/versia-pub/versia-go/pkg/versia"
@ -57,7 +58,7 @@ type InstanceMetadataService interface {
}
type TaskService interface {
ScheduleTask(ctx context.Context, type_ string, data any) error
ScheduleNoteTask(ctx context.Context, type_ string, data any) error
}
type RequestSigner interface {

View file

@ -2,17 +2,18 @@ package svc_impls
import (
"context"
"slices"
"github.com/versia-pub/versia-go/internal/repository"
"github.com/versia-pub/versia-go/internal/service"
task_dtos "github.com/versia-pub/versia-go/internal/task/dtos"
"github.com/versia-pub/versia-go/pkg/versia"
"slices"
"git.devminer.xyz/devminer/unitel"
"github.com/go-logr/logr"
"github.com/google/uuid"
"github.com/versia-pub/versia-go/internal/api_schema"
"github.com/versia-pub/versia-go/internal/entity"
"github.com/versia-pub/versia-go/internal/tasks"
)
var _ service.NoteService = (*NoteServiceImpl)(nil)
@ -69,7 +70,7 @@ func (i NoteServiceImpl) CreateNote(ctx context.Context, req api_schema.CreateNo
return err
}
if err := i.taskService.ScheduleTask(ctx, tasks.FederateNote, tasks.FederateNoteData{NoteID: n.ID}); err != nil {
if err := i.taskService.ScheduleNoteTask(ctx, task_dtos.FederateNote, task_dtos.FederateNoteData{NoteID: n.ID}); err != nil {
return err
}

View file

@ -2,7 +2,9 @@ package svc_impls
import (
"context"
"github.com/versia-pub/versia-go/internal/service"
"github.com/versia-pub/versia-go/internal/task"
"git.devminer.xyz/devminer/unitel"
"github.com/go-logr/logr"
@ -12,22 +14,22 @@ import (
var _ service.TaskService = (*TaskServiceImpl)(nil)
type TaskServiceImpl struct {
client *taskqueue.Client
manager task.Manager
telemetry *unitel.Telemetry
log logr.Logger
}
func NewTaskServiceImpl(client *taskqueue.Client, telemetry *unitel.Telemetry, log logr.Logger) *TaskServiceImpl {
func NewTaskServiceImpl(manager task.Manager, telemetry *unitel.Telemetry, log logr.Logger) *TaskServiceImpl {
return &TaskServiceImpl{
client: client,
manager: manager,
telemetry: telemetry,
log: log,
}
}
func (i TaskServiceImpl) ScheduleTask(ctx context.Context, type_ string, data any) error {
func (i TaskServiceImpl) ScheduleNoteTask(ctx context.Context, type_ string, data any) error {
s := i.telemetry.StartSpan(ctx, "function", "svc_impls/TaskServiceImpl.ScheduleTask")
defer s.End()
ctx = s.Context()
@ -38,7 +40,7 @@ func (i TaskServiceImpl) ScheduleTask(ctx context.Context, type_ string, data an
return err
}
if err := i.client.Submit(ctx, t); err != nil {
if err := i.manager.Notes().Submit(ctx, t); err != nil {
i.log.Error(err, "Failed to schedule task", "type", type_, "taskID", t.ID)
return err
}

View file

@ -0,0 +1,11 @@
package task_dtos
import "github.com/google/uuid"
const (
FederateNote = "federate_note"
)
type FederateNoteData struct {
NoteID uuid.UUID `json:"noteID"`
}

20
internal/task/handler.go Normal file
View file

@ -0,0 +1,20 @@
package task
import (
"context"
"github.com/versia-pub/versia-go/pkg/taskqueue"
)
type Manager interface {
Notes() NoteHandler
}
type Handler interface {
Register(*taskqueue.Set)
Submit(context.Context, taskqueue.Task) error
}
type NoteHandler interface {
Submit(context.Context, taskqueue.Task) error
}

View file

@ -0,0 +1,11 @@
package task_impls
import "git.devminer.xyz/devminer/unitel"
type baseHandler struct {
telemetry *unitel.Telemetry
}
func newBaseHandler() *baseHandler {
return &baseHandler{}
}

View file

@ -0,0 +1,29 @@
package task_impls
import (
"git.devminer.xyz/devminer/unitel"
"github.com/go-logr/logr"
"github.com/versia-pub/versia-go/internal/task"
)
var _ task.Manager = (*Manager)(nil)
type Manager struct {
notes *NoteHandler
telemetry *unitel.Telemetry
log logr.Logger
}
func NewManager(notes *NoteHandler, telemetry *unitel.Telemetry, log logr.Logger) *Manager {
return &Manager{
notes: notes,
telemetry: telemetry,
log: log,
}
}
func (m *Manager) Notes() task.NoteHandler {
return m.notes
}

View file

@ -0,0 +1,97 @@
package task_impls
import (
"context"
"github.com/versia-pub/versia-go/internal/entity"
"github.com/versia-pub/versia-go/internal/repository"
"github.com/versia-pub/versia-go/internal/service"
"github.com/versia-pub/versia-go/internal/task"
task_dtos "github.com/versia-pub/versia-go/internal/task/dtos"
"github.com/versia-pub/versia-go/internal/utils"
"git.devminer.xyz/devminer/unitel"
"github.com/go-logr/logr"
"github.com/versia-pub/versia-go/pkg/taskqueue"
)
var _ task.Handler = (*NoteHandler)(nil)
type NoteHandler struct {
federationService service.FederationService
repositories repository.Manager
telemetry *unitel.Telemetry
log logr.Logger
set *taskqueue.Set
}
func NewNoteHandler(federationService service.FederationService, repositories repository.Manager, telemetry *unitel.Telemetry, log logr.Logger) *NoteHandler {
return &NoteHandler{
federationService: federationService,
repositories: repositories,
telemetry: telemetry,
log: log,
}
}
func (t *NoteHandler) Start(ctx context.Context) error {
consumer := t.set.Consumer("note-handler")
return consumer.Start(ctx)
}
func (t *NoteHandler) Register(s *taskqueue.Set) {
t.set = s
s.RegisterHandler(task_dtos.FederateNote, utils.ParseTask(t.FederateNote))
}
func (t *NoteHandler) Submit(ctx context.Context, task taskqueue.Task) error {
s := t.telemetry.StartSpan(ctx, "function", "task_impls/NoteHandler.Submit")
defer s.End()
ctx = s.Context()
return t.set.Submit(ctx, task)
}
func (t *NoteHandler) FederateNote(ctx context.Context, data task_dtos.FederateNoteData) error {
s := t.telemetry.StartSpan(ctx, "function", "task_impls/NoteHandler.FederateNote")
defer s.End()
ctx = s.Context()
var n *entity.Note
if err := t.repositories.Atomic(ctx, func(ctx context.Context, tx repository.Manager) error {
var err error
n, err = tx.Notes().GetByID(ctx, data.NoteID)
if err != nil {
return err
}
if n == nil {
t.log.V(-1).Info("Could not find note", "id", data.NoteID)
return nil
}
for _, uu := range n.Mentions {
if !uu.IsRemote {
t.log.V(2).Info("User is not remote", "user", uu.ID)
continue
}
res, err := t.federationService.SendToInbox(ctx, n.Author, &uu, n.ToVersia())
if err != nil {
t.log.Error(err, "Failed to send note to remote user", "res", res, "user", uu.ID)
} else {
t.log.V(2).Info("Sent note to remote user", "res", res, "user", uu.ID)
}
}
return nil
}); err != nil {
return err
}
return nil
}

View file

@ -1,11 +0,0 @@
package tasks
import "context"
type FederateFollowData struct {
FollowID string `json:"followID"`
}
func (t *Handler) FederateFollow(ctx context.Context, data FederateNoteData) error {
return nil
}

View file

@ -1,52 +0,0 @@
package tasks
import (
"context"
"github.com/versia-pub/versia-go/internal/repository"
"github.com/google/uuid"
"github.com/versia-pub/versia-go/internal/entity"
)
type FederateNoteData struct {
NoteID uuid.UUID `json:"noteID"`
}
func (t *Handler) FederateNote(ctx context.Context, data FederateNoteData) error {
s := t.telemetry.StartSpan(ctx, "function", "tasks/Handler.FederateNote")
defer s.End()
ctx = s.Context()
var n *entity.Note
if err := t.repositories.Atomic(ctx, func(ctx context.Context, tx repository.Manager) error {
var err error
n, err = tx.Notes().GetByID(ctx, data.NoteID)
if err != nil {
return err
}
if n == nil {
t.log.V(-1).Info("Could not find note", "id", data.NoteID)
return nil
}
for _, uu := range n.Mentions {
if !uu.IsRemote {
t.log.V(2).Info("User is not remote", "user", uu.ID)
continue
}
res, err := t.federationService.SendToInbox(ctx, n.Author, &uu, n.ToVersia())
if err != nil {
t.log.Error(err, "Failed to send note to remote user", "res", res, "user", uu.ID)
} else {
t.log.V(2).Info("Sent note to remote user", "res", res, "user", uu.ID)
}
}
return nil
}); err != nil {
return err
}
return nil
}

View file

@ -1,53 +0,0 @@
package tasks
import (
"context"
"encoding/json"
"github.com/versia-pub/versia-go/internal/repository"
"github.com/versia-pub/versia-go/internal/service"
"git.devminer.xyz/devminer/unitel"
"github.com/go-logr/logr"
"github.com/versia-pub/versia-go/pkg/taskqueue"
)
const (
FederateNote = "federate_note"
FederateFollow = "federate_follow"
)
type Handler struct {
federationService service.FederationService
repositories repository.Manager
telemetry *unitel.Telemetry
log logr.Logger
}
func NewHandler(federationService service.FederationService, repositories repository.Manager, telemetry *unitel.Telemetry, log logr.Logger) *Handler {
return &Handler{
federationService: federationService,
repositories: repositories,
telemetry: telemetry,
log: log,
}
}
func (t *Handler) Register(tq *taskqueue.Client) {
tq.RegisterHandler(FederateNote, parse(t.FederateNote))
tq.RegisterHandler(FederateFollow, parse(t.FederateFollow))
}
func parse[T any](handler func(context.Context, T) error) func(context.Context, taskqueue.Task) error {
return func(ctx context.Context, task taskqueue.Task) error {
var data T
if err := json.Unmarshal(task.Payload, &data); err != nil {
return err
}
return handler(ctx, data)
}
}

19
internal/utils/tasks.go Normal file
View file

@ -0,0 +1,19 @@
package utils
import (
"context"
"encoding/json"
"github.com/versia-pub/versia-go/pkg/taskqueue"
)
func ParseTask[T any](handler func(context.Context, T) error) func(context.Context, taskqueue.Task) error {
return func(ctx context.Context, task taskqueue.Task) error {
var data T
if err := json.Unmarshal(task.Payload, &data); err != nil {
return err
}
return handler(ctx, data)
}
}