add support for page-based cursortokens (like goext)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package primary
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"blackforestbytes.com/simplecloudnotifier/db"
|
||||
ct "blackforestbytes.com/simplecloudnotifier/db/cursortoken"
|
||||
"blackforestbytes.com/simplecloudnotifier/models"
|
||||
"errors"
|
||||
"git.blackforestbytes.com/BlackForestBytes/goext/sq"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (db *Database) GetMessageByUserMessageID(ctx db.TxContext, usrMsgId string) (*models.Message, error) {
|
||||
@@ -87,26 +88,32 @@ func (db *Database) ListMessages(ctx db.TxContext, filter models.MessageFilter,
|
||||
return nil, ct.CursorToken{}, 0, err
|
||||
}
|
||||
|
||||
pageCond := "1=1"
|
||||
if inTok.Mode == ct.CTMNormal {
|
||||
pageCond = "timestamp_real < :tokts OR (timestamp_real = :tokts AND message_id < :tokid )"
|
||||
}
|
||||
|
||||
filterCond, filterJoin, prepParams, err := filter.SQL()
|
||||
|
||||
orderClause := ""
|
||||
pageCond := "1=1"
|
||||
|
||||
limitCond := ""
|
||||
if pageSize != nil {
|
||||
orderClause = "ORDER BY COALESCE(timestamp_client, timestamp_real) DESC, message_id DESC LIMIT :lim"
|
||||
limitCond = "LIMIT :lim"
|
||||
prepParams["lim"] = *pageSize + 1
|
||||
} else {
|
||||
orderClause = "ORDER BY COALESCE(timestamp_client, timestamp_real) DESC, message_id DESC"
|
||||
}
|
||||
|
||||
sqlQueryList := "SELECT " + "messages.*" + " FROM messages " + filterJoin + " WHERE ( " + pageCond + " ) AND ( " + filterCond + " ) " + orderClause
|
||||
sqlQueryCount := "SELECT " + " COUNT(*) AS count FROM messages " + filterJoin + " WHERE ( " + filterCond + " ) "
|
||||
if inTok.Mode == ct.CTMNormal {
|
||||
pageCond = "timestamp_real < :tokts OR (timestamp_real = :tokts AND message_id < :tokid )"
|
||||
prepParams["tokts"] = inTok.Timestamp
|
||||
prepParams["tokid"] = inTok.Id
|
||||
} else if inTok.Mode == ct.CTMPaginated {
|
||||
if pageSize != nil {
|
||||
limitCond = "LIMIT :lim OFFSET :off"
|
||||
prepParams["lim"] = *pageSize + 1
|
||||
prepParams["off"] = (*pageSize) * (*inTok.Page)
|
||||
}
|
||||
}
|
||||
|
||||
prepParams["tokts"] = inTok.Timestamp
|
||||
prepParams["tokid"] = inTok.Id
|
||||
orderClause := "ORDER BY COALESCE(timestamp_client, timestamp_real) DESC, message_id DESC"
|
||||
|
||||
sqlQueryList := "SELECT " + "messages.*" + " FROM messages " + filterJoin + " WHERE ( " + pageCond + " ) AND ( " + filterCond + " ) " + orderClause + " " + limitCond
|
||||
sqlQueryCount := "SELECT " + " COUNT(*) AS count FROM messages " + filterJoin + " WHERE ( " + filterCond + " ) "
|
||||
|
||||
if inTok.Mode == ct.CTMEnd {
|
||||
|
||||
@@ -132,7 +139,12 @@ func (db *Database) ListMessages(ctx db.TxContext, filter models.MessageFilter,
|
||||
return nil, ct.CursorToken{}, 0, err
|
||||
}
|
||||
|
||||
outToken := ct.Normal(dataList[*pageSize-1].Timestamp(), dataList[*pageSize-1].MessageID.String(), "DESC", filter.Hash())
|
||||
var outToken ct.CursorToken
|
||||
if inTok.Mode == ct.CTMPaginated {
|
||||
outToken = ct.Paginated(*inTok.Page + 1)
|
||||
} else {
|
||||
outToken = ct.Normal(dataList[*pageSize-1].Timestamp(), dataList[*pageSize-1].MessageID.String(), "DESC", filter.Hash())
|
||||
}
|
||||
|
||||
return dataList[0:*pageSize], outToken, dataCount.Count, nil
|
||||
}
|
||||
|
||||
@@ -52,14 +52,29 @@ func (db *Database) ListRequestLogs(ctx context.Context, filter models.RequestLo
|
||||
return make([]models.RequestLog, 0), ct.End(), nil
|
||||
}
|
||||
|
||||
pageCond := "1=1"
|
||||
if inTok.Mode == ct.CTMNormal {
|
||||
pageCond = "timestamp_created < :tokts OR (timestamp_created = :tokts AND request_id < :tokid )"
|
||||
}
|
||||
|
||||
filterCond, filterJoin, prepParams, err := filter.SQL()
|
||||
|
||||
orderClause := ""
|
||||
pageCond := "1=1"
|
||||
|
||||
limitCond := ""
|
||||
if pageSize != nil {
|
||||
limitCond = "LIMIT :lim"
|
||||
prepParams["lim"] = *pageSize + 1
|
||||
}
|
||||
|
||||
if inTok.Mode == ct.CTMNormal {
|
||||
pageCond = "timestamp_created < :tokts OR (timestamp_created = :tokts AND request_id < :tokid )"
|
||||
prepParams["tokts"] = inTok.Timestamp
|
||||
prepParams["tokid"] = inTok.Id
|
||||
} else if inTok.Mode == ct.CTMPaginated {
|
||||
if pageSize != nil {
|
||||
limitCond = "LIMIT :lim OFFSET :off"
|
||||
prepParams["lim"] = *pageSize + 1
|
||||
prepParams["off"] = (*pageSize) * (*inTok.Page)
|
||||
}
|
||||
}
|
||||
|
||||
orderClause := "ORDER BY timestamp_created DESC, request_id DESC"
|
||||
if pageSize != nil {
|
||||
orderClause = "ORDER BY timestamp_created DESC, request_id DESC LIMIT :lim"
|
||||
prepParams["lim"] = *pageSize + 1
|
||||
@@ -67,7 +82,7 @@ func (db *Database) ListRequestLogs(ctx context.Context, filter models.RequestLo
|
||||
orderClause = "ORDER BY timestamp_created DESC, request_id DESC"
|
||||
}
|
||||
|
||||
sqlQuery := "SELECT " + "requests.*" + " FROM requests " + filterJoin + " WHERE ( " + pageCond + " ) AND ( " + filterCond + " ) " + orderClause
|
||||
sqlQuery := "SELECT " + "requests.*" + " FROM requests " + filterJoin + " WHERE ( " + pageCond + " ) AND ( " + filterCond + " ) " + orderClause + " " + limitCond
|
||||
|
||||
prepParams["tokts"] = inTok.Timestamp
|
||||
prepParams["tokid"] = inTok.Id
|
||||
|
||||
Reference in New Issue
Block a user