add support for page-based cursortokens (like goext)
Some checks failed
Build Docker and Deploy / Build Docker Container (push) Successful in 52s
Build Docker and Deploy / Run Unit-Tests (push) Failing after 2m49s
Build Docker and Deploy / Deploy to Server (push) Has been skipped

This commit is contained in:
2025-12-03 19:46:09 +01:00
parent d26f18f356
commit 4b8ebf15d2
4 changed files with 339 additions and 33 deletions

View File

@@ -4,21 +4,27 @@ import (
"encoding/base32"
"encoding/json"
"errors"
"fmt"
"strconv"
"strings"
"time"
"git.blackforestbytes.com/BlackForestBytes/goext/langext"
)
type Mode string //@enum:type
const (
CTMStart = "START"
CTMNormal = "NORMAL"
CTMEnd = "END"
CTMStart = "START"
CTMNormal = "NORMAL"
CTMPaginated = "PAGINATED"
CTMEnd = "END"
)
type CursorToken struct {
Mode Mode
Timestamp int64
Timestamp *int64
Page *int
Id string
Direction string
FilterHash string
@@ -34,7 +40,8 @@ type cursorTokenSerialize struct {
func Start() CursorToken {
return CursorToken{
Mode: CTMStart,
Timestamp: 0,
Timestamp: langext.Ptr[int64](0),
Page: nil,
Id: "",
Direction: "",
FilterHash: "",
@@ -44,7 +51,8 @@ func Start() CursorToken {
func End() CursorToken {
return CursorToken{
Mode: CTMEnd,
Timestamp: 0,
Timestamp: nil,
Page: nil,
Id: "",
Direction: "",
FilterHash: "",
@@ -54,13 +62,22 @@ func End() CursorToken {
func Normal(ts time.Time, id string, dir string, filter string) CursorToken {
return CursorToken{
Mode: CTMNormal,
Timestamp: ts.UnixMilli(),
Timestamp: langext.Ptr(ts.UnixMilli()),
Page: nil,
Id: id,
Direction: dir,
FilterHash: filter,
}
}
func Paginated(p int) CursorToken {
return CursorToken{
Mode: CTMPaginated,
Timestamp: nil,
Page: langext.Ptr(p),
}
}
func (c *CursorToken) Token() string {
if c.Mode == CTMStart {
return "@start"
@@ -69,6 +86,10 @@ func (c *CursorToken) Token() string {
return "@end"
}
if c.Page != nil {
return fmt.Sprintf("$%d", *c.Page)
}
// We kinda manually implement omitempty for the CursorToken here
// because omitempty does not work for time.Time and otherwise we would always
// get weird time values when decoding a token that initially didn't have an Timestamp set
@@ -80,8 +101,8 @@ func (c *CursorToken) Token() string {
sertok.Id = &c.Id
}
if c.Timestamp != 0 {
sertok.Timestamp = &c.Timestamp
if c.Timestamp != nil && *c.Timestamp != 0 {
sertok.Timestamp = langext.Ptr(*c.Timestamp)
}
if c.Direction != "" {
@@ -111,6 +132,14 @@ func Decode(tok string) (CursorToken, error) {
return End(), nil
}
if strings.HasPrefix(tok, "$") {
p, err := strconv.ParseInt(tok[1:], 10, 0)
if err != nil {
return CursorToken{}, errors.New("could not decode paginated token")
}
return Paginated(int(p)), nil
}
if !strings.HasPrefix(tok, "tok_") {
return CursorToken{}, errors.New("could not decode token, missing prefix")
}
@@ -129,7 +158,7 @@ func Decode(tok string) (CursorToken, error) {
token := CursorToken{Mode: CTMNormal}
if tokenDeserialize.Timestamp != nil {
token.Timestamp = *tokenDeserialize.Timestamp
token.Timestamp = langext.Ptr(*tokenDeserialize.Timestamp)
}
if tokenDeserialize.Id != nil {
token.Id = *tokenDeserialize.Id