diff options
| author | 2025-10-13 14:03:17 +0200 | |
|---|---|---|
| committer | 2025-10-17 15:32:50 +0200 | |
| commit | 3a5119b5ff2c8f6ecb02d4054002b3845ca05e9c (patch) | |
| tree | 39a16e66ea60f6bd46a3d75e6da0c73b2705c118 | |
| parent | [performance] add benchmarks for native Go imaging code, small tweaks to redu... (diff) | |
| download | gotosocial-3a5119b5ff2c8f6ecb02d4054002b3845ca05e9c.tar.xz | |
[bugfix] repeated posts on timeline endpoints (#4494)
- updates the go-structr library to add support for getting the current HEAD and TAIL primary key values, which allows us to not insert statuses if they're older than the current oldest timeline item
- ensures the nextPg parameters get updated after loading from the cache before then performing a database query
closes: https://codeberg.org/superseriousbusiness/gotosocial/issues/4491
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4494
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
| -rw-r--r-- | go.mod | 2 | ||||
| -rw-r--r-- | go.sum | 4 | ||||
| -rw-r--r-- | internal/cache/timeline/status.go | 10 | ||||
| -rw-r--r-- | vendor/codeberg.org/gruf/go-structr/timeline.go | 33 | ||||
| -rw-r--r-- | vendor/modules.txt | 2 |
5 files changed, 47 insertions, 4 deletions
@@ -31,7 +31,7 @@ require ( codeberg.org/gruf/go-sched v1.2.4 codeberg.org/gruf/go-split v1.2.0 codeberg.org/gruf/go-storage v0.3.1 - codeberg.org/gruf/go-structr v0.9.12 + codeberg.org/gruf/go-structr v0.9.13 github.com/DmitriyVTitov/size v1.5.0 github.com/KimMachineGun/automemlimit v0.7.4 github.com/SherClockHolmes/webpush-go v1.4.0 @@ -54,8 +54,8 @@ codeberg.org/gruf/go-split v1.2.0 h1:PmzL23nVEVHm8VxjsJmv4m4wGQz2bGgQw52dgSSj65c codeberg.org/gruf/go-split v1.2.0/go.mod h1:0rejWJpqvOoFAd7nwm5tIXYKaAqjtFGOXmTqQV+VO38= codeberg.org/gruf/go-storage v0.3.1 h1:g66UIM/xXnEk9ejT+W0T9s/PODBZhXa/8ajzeY/MELI= codeberg.org/gruf/go-storage v0.3.1/go.mod h1:r43n/zi7YGOCl2iSl7AMI27D1zcWS65Bi2+5xDzypeo= -codeberg.org/gruf/go-structr v0.9.12 h1:yMopvexnuKgZme9WgvIhrJaAuAjfper/x38xsVuJOOo= -codeberg.org/gruf/go-structr v0.9.12/go.mod h1:sP2ZSjM5X5XKlxuhAbTKuVQm9DWbHsrQRuTl3MUwbHw= +codeberg.org/gruf/go-structr v0.9.13 h1:tTAR30OnSKrcvBomlGZdwE2nE+cfWhkX8UhX0GTAbMo= +codeberg.org/gruf/go-structr v0.9.13/go.mod h1:sP2ZSjM5X5XKlxuhAbTKuVQm9DWbHsrQRuTl3MUwbHw= codeberg.org/gruf/go-xunsafe v0.0.0-20250809104800-512a9df57d73 h1:pRaOwIOS1WSZoPCAvE0H1zpv+D4gF37OVppybffqdI8= codeberg.org/gruf/go-xunsafe v0.0.0-20250809104800-512a9df57d73/go.mod h1:9wkq+dmHjUhB/0ZxDUWAwsWuXwwGyx5N1dDCB9hpWs8= codeberg.org/superseriousbusiness/go-swagger v0.32.3-gts-go1.23-fix h1:k76/Th+bruqU/d+dB0Ru466ctTF2aVjKpisy/471ILE= diff --git a/internal/cache/timeline/status.go b/internal/cache/timeline/status.go index 7e6d3aa27..9e3957ac2 100644 --- a/internal/cache/timeline/status.go +++ b/internal/cache/timeline/status.go @@ -387,6 +387,9 @@ func (t *StatusTimeline) Load( return nil, "", "", gtserror.Newf("error loading statuses: %w", err) } + // Update nextPg cursor parameter for database query. + nextPageParams(nextPg, metas[len(metas)-1].ID, order) + // Prepare frontend API models for // the cached statuses. For now this // also does its own extra filtering. @@ -536,6 +539,13 @@ func (t *StatusTimeline) InsertOne(status *gtsmodel.Status, prepared *apimodel.S return false } + // If item is beyond end of the + // timeline, don't bother adding. + if tailID := t.cache.Tail(); // + tailID == nil || status.ID < *tailID { + return false + } + if status.BoostOfID != "" { // Check through top $repeatBoostDepth number of items. for i, value := range t.cache.RangeUnsafe(structr.Desc) { diff --git a/vendor/codeberg.org/gruf/go-structr/timeline.go b/vendor/codeberg.org/gruf/go-structr/timeline.go index 749ec862a..e738a8228 100644 --- a/vendor/codeberg.org/gruf/go-structr/timeline.go +++ b/vendor/codeberg.org/gruf/go-structr/timeline.go @@ -7,6 +7,7 @@ import ( "slices" "strings" "sync" + "sync/atomic" "unsafe" "codeberg.org/gruf/go-mempool" @@ -83,6 +84,11 @@ type Timeline[StructType any, PK cmp.Ordered] struct { // types by user defined sets of fields. indices []Index + // atomically updated head + // / tail primary key values. + headPK unsafe.Pointer + tailPK unsafe.Pointer + // protective mutex, guards: // - Timeline{}.* // - Index{}.data @@ -150,6 +156,16 @@ func (t *Timeline[T, PK]) Index(name string) *Index { panic("unknown index: " + name) } +// Head returns the current head primary key. +func (t *Timeline[T, PK]) Head() *PK { + return (*PK)(atomic.LoadPointer(&t.headPK)) +} + +// Tail returns the current tail primary key. +func (t *Timeline[T, PK]) Tail() *PK { + return (*PK)(atomic.LoadPointer(&t.tailPK)) +} + // Select allows you to retrieve a slice of values, in order, from the timeline. // This slice is defined by the minimum and maximum primary key parameters, up to // a given length in size. The direction in which you select will determine which @@ -570,6 +586,10 @@ func (t *Timeline[T, PK]) Trim(max int, dir Direction) { bottom := t.list.tail if bottom == nil { + // Zero head + tail primary keys. + atomic.StorePointer(&t.headPK, nil) + atomic.StorePointer(&t.tailPK, nil) + // reached // end. break @@ -589,6 +609,10 @@ func (t *Timeline[T, PK]) Trim(max int, dir Direction) { top := t.list.head if top == nil { + // Zero head + tail primary keys. + atomic.StorePointer(&t.headPK, nil) + atomic.StorePointer(&t.tailPK, nil) + // reached // end. break @@ -1034,6 +1058,15 @@ func (t *Timeline[T, PK]) store_one(last *list_elem, value value_with_pk[T, PK]) goto indexing indexing: + // Set new head / tail + // primary key values. + switch last { + case t.list.head: + atomic.StorePointer(&t.headPK, value.kptr) + case t.list.tail: + atomic.StorePointer(&t.tailPK, value.kptr) + } + // Append already-extracted // primary key to 0th index. _ = idx0.add(key, i_item) diff --git a/vendor/modules.txt b/vendor/modules.txt index 10c10e1c2..3f8477520 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -293,7 +293,7 @@ codeberg.org/gruf/go-storage/disk codeberg.org/gruf/go-storage/internal codeberg.org/gruf/go-storage/memory codeberg.org/gruf/go-storage/s3 -# codeberg.org/gruf/go-structr v0.9.12 +# codeberg.org/gruf/go-structr v0.9.13 ## explicit; go 1.24.5 codeberg.org/gruf/go-structr # codeberg.org/gruf/go-xunsafe v0.0.0-20250809104800-512a9df57d73 |
