diff options
| author | 2025-10-13 14:03:17 +0200 | |
|---|---|---|
| committer | 2025-10-17 15:32:50 +0200 | |
| commit | 3a5119b5ff2c8f6ecb02d4054002b3845ca05e9c (patch) | |
| tree | 39a16e66ea60f6bd46a3d75e6da0c73b2705c118 /vendor/codeberg.org/gruf | |
| 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>
Diffstat (limited to 'vendor/codeberg.org/gruf')
| -rw-r--r-- | vendor/codeberg.org/gruf/go-structr/timeline.go | 33 |
1 files changed, 33 insertions, 0 deletions
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) |
