diff options
Diffstat (limited to 'internal/db')
-rw-r--r-- | internal/db/bundb/media.go | 86 | ||||
-rw-r--r-- | internal/db/bundb/status.go | 22 | ||||
-rw-r--r-- | internal/db/media.go | 11 |
3 files changed, 91 insertions, 28 deletions
diff --git a/internal/db/bundb/media.go b/internal/db/bundb/media.go index 6975df85f..8f6985bad 100644 --- a/internal/db/bundb/media.go +++ b/internal/db/bundb/media.go @@ -34,39 +34,69 @@ type mediaDB struct { state *state.State } -func (m *mediaDB) newMediaQ(i *gtsmodel.MediaAttachment) *bun.SelectQuery { - return m.conn. - NewSelect(). - Model(i) -} - func (m *mediaDB) GetAttachmentByID(ctx context.Context, id string) (*gtsmodel.MediaAttachment, db.Error) { return m.getAttachment( ctx, "ID", func(attachment *gtsmodel.MediaAttachment) error { - return m.newMediaQ(attachment).Where("? = ?", bun.Ident("media_attachment.id"), id).Scan(ctx) + return m.conn.NewSelect(). + Model(attachment). + Where("? = ?", bun.Ident("media_attachment.id"), id). + Scan(ctx) }, id, ) } -func (m *mediaDB) getAttachments(ctx context.Context, ids []string) ([]*gtsmodel.MediaAttachment, db.Error) { - attachments := make([]*gtsmodel.MediaAttachment, 0, len(ids)) +func (m *mediaDB) getAttachment(ctx context.Context, lookup string, dbQuery func(*gtsmodel.MediaAttachment) error, keyParts ...any) (*gtsmodel.MediaAttachment, db.Error) { + return m.state.Caches.GTS.Media().Load(lookup, func() (*gtsmodel.MediaAttachment, error) { + var attachment gtsmodel.MediaAttachment - for _, id := range ids { - // Attempt fetch from DB - attachment, err := m.GetAttachmentByID(ctx, id) - if err != nil { - log.Errorf(ctx, "error getting attachment %q: %v", id, err) - continue + // Not cached! Perform database query + if err := dbQuery(&attachment); err != nil { + return nil, m.conn.ProcessError(err) } - // Append attachment - attachments = append(attachments, attachment) + return &attachment, nil + }, keyParts...) +} + +func (m *mediaDB) PutAttachment(ctx context.Context, media *gtsmodel.MediaAttachment) error { + return m.state.Caches.GTS.Media().Store(media, func() error { + _, err := m.conn.NewInsert().Model(media).Exec(ctx) + return m.conn.ProcessError(err) + }) +} + +func (m *mediaDB) UpdateAttachment(ctx context.Context, media *gtsmodel.MediaAttachment, columns ...string) error { + media.UpdatedAt = time.Now() + if len(columns) > 0 { + // If we're updating by column, ensure "updated_at" is included. + columns = append(columns, "updated_at") } - return attachments, nil + return m.state.Caches.GTS.Media().Store(media, func() error { + _, err := m.conn.NewUpdate(). + Model(media). + Where("? = ?", bun.Ident("media_attachment.id"), media.ID). + Column(columns...). + Exec(ctx) + return m.conn.ProcessError(err) + }) +} + +func (m *mediaDB) DeleteAttachment(ctx context.Context, id string) error { + // Attempt to delete from database. + if _, err := m.conn.NewDelete(). + TableExpr("? AS ?", bun.Ident("media_attachments"), bun.Ident("media_attachment")). + Where("? = ?", bun.Ident("media_attachment.id"), id). + Exec(ctx); err != nil { + return m.conn.ProcessError(err) + } + + // Invalidate this media item from the cache. + m.state.Caches.GTS.Media().Invalidate("ID", id) + return nil } func (m *mediaDB) GetRemoteOlderThan(ctx context.Context, olderThan time.Time, limit int) ([]*gtsmodel.MediaAttachment, db.Error) { @@ -183,14 +213,20 @@ func (m *mediaDB) CountLocalUnattachedOlderThan(ctx context.Context, olderThan t return count, nil } -func (m *mediaDB) getAttachment(ctx context.Context, lookup string, dbQuery func(*gtsmodel.MediaAttachment) error, keyParts ...any) (*gtsmodel.MediaAttachment, db.Error) { - // Fetch attachment from database - // todo: cache this lookup - attachment := new(gtsmodel.MediaAttachment) +func (m *mediaDB) getAttachments(ctx context.Context, ids []string) ([]*gtsmodel.MediaAttachment, db.Error) { + attachments := make([]*gtsmodel.MediaAttachment, 0, len(ids)) - if err := dbQuery(attachment); err != nil { - return nil, m.conn.ProcessError(err) + for _, id := range ids { + // Attempt fetch from DB + attachment, err := m.GetAttachmentByID(ctx, id) + if err != nil { + log.Errorf(ctx, "error getting attachment %q: %v", id, err) + continue + } + + // Append attachment + attachments = append(attachments, attachment) } - return attachment, nil + return attachments, nil } diff --git a/internal/db/bundb/status.go b/internal/db/bundb/status.go index 72e44068d..3bbf67657 100644 --- a/internal/db/bundb/status.go +++ b/internal/db/bundb/status.go @@ -188,7 +188,7 @@ func (s *statusDB) getStatus(ctx context.Context, lookup string, dbQuery func(*g } func (s *statusDB) PutStatus(ctx context.Context, status *gtsmodel.Status) db.Error { - return s.state.Caches.GTS.Status().Store(status, func() error { + err := s.state.Caches.GTS.Status().Store(status, func() error { // It is safe to run this database transaction within cache.Store // as the cache does not attempt a mutex lock until AFTER hook. // @@ -248,6 +248,17 @@ func (s *statusDB) PutStatus(ctx context.Context, status *gtsmodel.Status) db.Er return err }) }) + if err != nil { + // already processed + return err + } + + for _, id := range status.AttachmentIDs { + // Clear updated media attachment IDs from cache + s.state.Caches.GTS.Media().Invalidate("ID", id) + } + + return nil } func (s *statusDB) UpdateStatus(ctx context.Context, status *gtsmodel.Status, columns ...string) db.Error { @@ -317,11 +328,18 @@ func (s *statusDB) UpdateStatus(ctx context.Context, status *gtsmodel.Status, co Exec(ctx) return err }); err != nil { + // already processed return err } - // Drop any old value from cache by this ID + for _, id := range status.AttachmentIDs { + // Clear updated media attachment IDs from cache + s.state.Caches.GTS.Media().Invalidate("ID", id) + } + + // Drop any old status value from cache by this ID s.state.Caches.GTS.Status().Invalidate("ID", status.ID) + return nil } diff --git a/internal/db/media.go b/internal/db/media.go index 3756bd58f..131d0ab08 100644 --- a/internal/db/media.go +++ b/internal/db/media.go @@ -27,9 +27,18 @@ import ( // Media contains functions related to creating/getting/removing media attachments. type Media interface { - // GetAttachmentByID gets a single attachment by its ID + // GetAttachmentByID gets a single attachment by its ID. GetAttachmentByID(ctx context.Context, id string) (*gtsmodel.MediaAttachment, Error) + // PutAttachment inserts the given attachment into the database. + PutAttachment(ctx context.Context, media *gtsmodel.MediaAttachment) error + + // UpdateAttachment will update the given attachment in the database. + UpdateAttachment(ctx context.Context, media *gtsmodel.MediaAttachment, columns ...string) error + + // DeleteAttachment deletes the attachment with given ID from the database. + DeleteAttachment(ctx context.Context, id string) error + // GetRemoteOlderThan gets limit n remote media attachments (including avatars and headers) older than the given // olderThan time. These will be returned in order of attachment.created_at descending (newest to oldest in other words). // |