summaryrefslogtreecommitdiff
path: root/vendor/codeberg.org/gruf/go-structr
diff options
context:
space:
mode:
authorLibravatar kim <grufwub@gmail.com>2025-10-13 14:03:17 +0200
committerLibravatar tobi <tobi.smethurst@protonmail.com>2025-10-17 15:32:50 +0200
commit3a5119b5ff2c8f6ecb02d4054002b3845ca05e9c (patch)
tree39a16e66ea60f6bd46a3d75e6da0c73b2705c118 /vendor/codeberg.org/gruf/go-structr
parent[performance] add benchmarks for native Go imaging code, small tweaks to redu... (diff)
downloadgotosocial-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/go-structr')
-rw-r--r--vendor/codeberg.org/gruf/go-structr/timeline.go33
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)