summaryrefslogtreecommitdiff
path: root/internal/timeline/get.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/timeline/get.go')
-rw-r--r--internal/timeline/get.go82
1 files changed, 53 insertions, 29 deletions
diff --git a/internal/timeline/get.go b/internal/timeline/get.go
index cb6399ec9..b286ab369 100644
--- a/internal/timeline/get.go
+++ b/internal/timeline/get.go
@@ -23,6 +23,7 @@ import (
"context"
"errors"
"fmt"
+ "time"
"codeberg.org/gruf/go-kv"
"github.com/superseriousbusiness/gotosocial/internal/log"
@@ -30,16 +31,27 @@ import (
const retries = 5
+func (t *timeline) LastGot() time.Time {
+ t.Lock()
+ defer t.Unlock()
+ return t.lastGot
+}
+
func (t *timeline) Get(ctx context.Context, amount int, maxID string, sinceID string, minID string, prepareNext bool) ([]Preparable, error) {
l := log.WithFields(kv.Fields{
-
{"accountID", t.accountID},
{"amount", amount},
{"maxID", maxID},
{"sinceID", sinceID},
{"minID", minID},
}...)
- l.Debug("entering get")
+ l.Debug("entering get and updating t.lastGot")
+
+ // regardless of what happens below, update the
+ // last time Get was called for this timeline
+ t.Lock()
+ t.lastGot = time.Now()
+ t.Unlock()
var items []Preparable
var err error
@@ -47,7 +59,7 @@ func (t *timeline) Get(ctx context.Context, amount int, maxID string, sinceID st
// no params are defined to just fetch from the top
// this is equivalent to a user asking for the top x items from their timeline
if maxID == "" && sinceID == "" && minID == "" {
- items, err = t.GetXFromTop(ctx, amount)
+ items, err = t.getXFromTop(ctx, amount)
// aysnchronously prepare the next predicted query so it's ready when the user asks for it
if len(items) != 0 {
nextMaxID := items[len(items)-1].GetID()
@@ -67,7 +79,7 @@ func (t *timeline) Get(ctx context.Context, amount int, maxID string, sinceID st
// this is equivalent to a user asking for the next x items from their timeline, starting from maxID
if maxID != "" && sinceID == "" {
attempts := 0
- items, err = t.GetXBehindID(ctx, amount, maxID, &attempts)
+ items, err = t.getXBehindID(ctx, amount, maxID, &attempts)
// aysnchronously prepare the next predicted query so it's ready when the user asks for it
if len(items) != 0 {
nextMaxID := items[len(items)-1].GetID()
@@ -86,25 +98,26 @@ func (t *timeline) Get(ctx context.Context, amount int, maxID string, sinceID st
// maxID is defined and sinceID || minID are as well, so take a slice between them
// this is equivalent to a user asking for items older than x but newer than y
if maxID != "" && sinceID != "" {
- items, err = t.GetXBetweenID(ctx, amount, maxID, minID)
+ items, err = t.getXBetweenID(ctx, amount, maxID, minID)
}
if maxID != "" && minID != "" {
- items, err = t.GetXBetweenID(ctx, amount, maxID, minID)
+ items, err = t.getXBetweenID(ctx, amount, maxID, minID)
}
// maxID isn't defined, but sinceID || minID are, so take x before
// this is equivalent to a user asking for items newer than x (eg., refreshing the top of their timeline)
if maxID == "" && sinceID != "" {
- items, err = t.GetXBeforeID(ctx, amount, sinceID, true)
+ items, err = t.getXBeforeID(ctx, amount, sinceID, true)
}
if maxID == "" && minID != "" {
- items, err = t.GetXBeforeID(ctx, amount, minID, true)
+ items, err = t.getXBeforeID(ctx, amount, minID, true)
}
return items, err
}
-func (t *timeline) GetXFromTop(ctx context.Context, amount int) ([]Preparable, error) {
+// getXFromTop returns x amount of items from the top of the timeline, from newest to oldest.
+func (t *timeline) getXFromTop(ctx context.Context, amount int) ([]Preparable, error) {
// make a slice of preparedItems with the length we need to return
preparedItems := make([]Preparable, 0, amount)
@@ -124,7 +137,7 @@ func (t *timeline) GetXFromTop(ctx context.Context, amount int) ([]Preparable, e
for e := t.preparedItems.data.Front(); e != nil; e = e.Next() {
entry, ok := e.Value.(*preparedItemsEntry)
if !ok {
- return nil, errors.New("GetXFromTop: could not parse e as a preparedItemsEntry")
+ return nil, errors.New("getXFromTop: could not parse e as a preparedItemsEntry")
}
preparedItems = append(preparedItems, entry.prepared)
served++
@@ -136,9 +149,12 @@ func (t *timeline) GetXFromTop(ctx context.Context, amount int) ([]Preparable, e
return preparedItems, nil
}
-func (t *timeline) GetXBehindID(ctx context.Context, amount int, behindID string, attempts *int) ([]Preparable, error) {
+// getXBehindID returns x amount of items from the given id onwards, from newest to oldest.
+// This will NOT include the item with the given ID.
+//
+// This corresponds to an api call to /timelines/home?max_id=WHATEVER
+func (t *timeline) getXBehindID(ctx context.Context, amount int, behindID string, attempts *int) ([]Preparable, error) {
l := log.WithFields(kv.Fields{
-
{"amount", amount},
{"behindID", behindID},
{"attempts", attempts},
@@ -164,7 +180,7 @@ findMarkLoop:
position++
entry, ok := e.Value.(*preparedItemsEntry)
if !ok {
- return nil, errors.New("GetXBehindID: could not parse e as a preparedPostsEntry")
+ return nil, errors.New("getXBehindID: could not parse e as a preparedPostsEntry")
}
if entry.itemID <= behindID {
@@ -177,10 +193,10 @@ findMarkLoop:
// we didn't find it, so we need to make sure it's indexed and prepared and then try again
// this can happen when a user asks for really old items
if behindIDMark == nil {
- if err := t.PrepareBehind(ctx, behindID, amount); err != nil {
- return nil, fmt.Errorf("GetXBehindID: error preparing behind and including ID %s", behindID)
+ if err := t.prepareBehind(ctx, behindID, amount); err != nil {
+ return nil, fmt.Errorf("getXBehindID: error preparing behind and including ID %s", behindID)
}
- oldestID, err := t.OldestPreparedItemID(ctx)
+ oldestID, err := t.oldestPreparedItemID(ctx)
if err != nil {
return nil, err
}
@@ -196,13 +212,13 @@ findMarkLoop:
l.Tracef("exceeded retries looking for behindID %s", behindID)
return items, nil
}
- l.Trace("trying GetXBehindID again")
- return t.GetXBehindID(ctx, amount, behindID, attempts)
+ l.Trace("trying getXBehindID again")
+ return t.getXBehindID(ctx, amount, behindID, attempts)
}
// make sure we have enough items prepared behind it to return what we're being asked for
if t.preparedItems.data.Len() < amount+position {
- if err := t.PrepareBehind(ctx, behindID, amount); err != nil {
+ if err := t.prepareBehind(ctx, behindID, amount); err != nil {
return nil, err
}
}
@@ -213,7 +229,7 @@ serveloop:
for e := behindIDMark.Next(); e != nil; e = e.Next() {
entry, ok := e.Value.(*preparedItemsEntry)
if !ok {
- return nil, errors.New("GetXBehindID: could not parse e as a preparedPostsEntry")
+ return nil, errors.New("getXBehindID: could not parse e as a preparedPostsEntry")
}
// serve up to the amount requested
@@ -227,7 +243,11 @@ serveloop:
return items, nil
}
-func (t *timeline) GetXBeforeID(ctx context.Context, amount int, beforeID string, startFromTop bool) ([]Preparable, error) {
+// getXBeforeID returns x amount of items up to the given id, from newest to oldest.
+// This will NOT include the item with the given ID.
+//
+// This corresponds to an api call to /timelines/home?since_id=WHATEVER
+func (t *timeline) getXBeforeID(ctx context.Context, amount int, beforeID string, startFromTop bool) ([]Preparable, error) {
// make a slice of items with the length we need to return
items := make([]Preparable, 0, amount)
@@ -241,7 +261,7 @@ findMarkLoop:
for e := t.preparedItems.data.Front(); e != nil; e = e.Next() {
entry, ok := e.Value.(*preparedItemsEntry)
if !ok {
- return nil, errors.New("GetXBeforeID: could not parse e as a preparedPostsEntry")
+ return nil, errors.New("getXBeforeID: could not parse e as a preparedPostsEntry")
}
if entry.itemID >= beforeID {
@@ -263,7 +283,7 @@ findMarkLoop:
for e := t.preparedItems.data.Front(); e != nil; e = e.Next() {
entry, ok := e.Value.(*preparedItemsEntry)
if !ok {
- return nil, errors.New("GetXBeforeID: could not parse e as a preparedPostsEntry")
+ return nil, errors.New("getXBeforeID: could not parse e as a preparedPostsEntry")
}
if entry.itemID == beforeID {
@@ -283,7 +303,7 @@ findMarkLoop:
for e := beforeIDMark.Prev(); e != nil; e = e.Prev() {
entry, ok := e.Value.(*preparedItemsEntry)
if !ok {
- return nil, errors.New("GetXBeforeID: could not parse e as a preparedPostsEntry")
+ return nil, errors.New("getXBeforeID: could not parse e as a preparedPostsEntry")
}
// serve up to the amount requested
@@ -298,7 +318,11 @@ findMarkLoop:
return items, nil
}
-func (t *timeline) GetXBetweenID(ctx context.Context, amount int, behindID string, beforeID string) ([]Preparable, error) {
+// getXBetweenID returns x amount of items from the given maxID, up to the given id, from newest to oldest.
+// This will NOT include the item with the given IDs.
+//
+// This corresponds to an api call to /timelines/home?since_id=WHATEVER&max_id=WHATEVER_ELSE
+func (t *timeline) getXBetweenID(ctx context.Context, amount int, behindID string, beforeID string) ([]Preparable, error) {
// make a slice of items with the length we need to return
items := make([]Preparable, 0, amount)
@@ -314,7 +338,7 @@ findMarkLoop:
position++
entry, ok := e.Value.(*preparedItemsEntry)
if !ok {
- return nil, errors.New("GetXBetweenID: could not parse e as a preparedPostsEntry")
+ return nil, errors.New("getXBetweenID: could not parse e as a preparedPostsEntry")
}
if entry.itemID == behindID {
@@ -325,12 +349,12 @@ findMarkLoop:
// we didn't find it
if behindIDMark == nil {
- return nil, fmt.Errorf("GetXBetweenID: couldn't find item with ID %s", behindID)
+ return nil, fmt.Errorf("getXBetweenID: couldn't find item with ID %s", behindID)
}
// make sure we have enough items prepared behind it to return what we're being asked for
if t.preparedItems.data.Len() < amount+position {
- if err := t.PrepareBehind(ctx, behindID, amount); err != nil {
+ if err := t.prepareBehind(ctx, behindID, amount); err != nil {
return nil, err
}
}
@@ -341,7 +365,7 @@ serveloop:
for e := behindIDMark.Next(); e != nil; e = e.Next() {
entry, ok := e.Value.(*preparedItemsEntry)
if !ok {
- return nil, errors.New("GetXBetweenID: could not parse e as a preparedPostsEntry")
+ return nil, errors.New("getXBetweenID: could not parse e as a preparedPostsEntry")
}
if entry.itemID == beforeID {