adding sequence marker to get topics to support staggard loading

This commit is contained in:
Roland Osborne 2022-07-03 00:18:57 -07:00
parent e4830093e3
commit 1c05180251
2 changed files with 128 additions and 9 deletions

View File

@ -2485,7 +2485,7 @@ paths:
get:
tags:
- content
description: Get channel topic slots. If revision set, detail fields omitted in response
description: Get channel topic slots. If revision set, detail fields omitted in response. Staggered loading supported through sequnce marker. Initially count can be used to limit the topics returned. The sequence marker returned in the header must be used in subsequent queries for the same topic window.
operationId: get-channel-topics
security:
- bearerAuth: []
@ -2501,16 +2501,43 @@ paths:
description: return updated topics since revision
required: false
schema:
type: string
type: integer
format: int64
- name: count
in: query
description: limit number of topics from latest when revision not set
required: false
schema:
type: integer
format: int64
- name: begin
in: query
description: return topics after and including sequence marker
required: false
schema:
type: integer
format: int64
- name: end
in: query
description: return topics before and not including sequence marker
required: false
schema:
type: integer
format: int64
responses:
'200':
description: successful operation
headers:
X-Topic-Revision:
Topic-Revision:
schema:
type: integer
format: int64
description: current topic revision
Topic-Marker:
schema:
type: integer
format: int64
description: sequnce marker of first topic when count set
content:
application/json:
schema:

View File

@ -6,9 +6,23 @@ import (
"databag/internal/store"
)
func reverse(input []store.TopicSlot) []store.TopicSlot {
var output []store.TopicSlot
for i := len(input) - 1; i >= 0; i-- {
output = append(output, input[i])
}
return output
}
func GetChannelTopics(w http.ResponseWriter, r *http.Request) {
var revisionSet bool
var revision int64
var beginSet bool
var begin int64
var endSet bool
var end int64
var countSet bool
var count int
channelSlot, _, err, code := getChannelSlot(r, false)
if err != nil {
@ -25,24 +39,102 @@ func GetChannelTopics(w http.ResponseWriter, r *http.Request) {
}
}
cnt := r.FormValue("count")
if cnt != "" {
countSet = true
if count, err = strconv.Atoi(cnt); err != nil {
ErrResponse(w, http.StatusBadRequest, err)
return
}
}
bn := r.FormValue("begin")
if bn != "" {
beginSet = true
if begin, err = strconv.ParseInt(bn, 10, 64); err != nil {
ErrResponse(w, http.StatusBadRequest, err)
return
}
}
en := r.FormValue("end")
if en != "" {
endSet = true
if end, err = strconv.ParseInt(en, 10, 64); err != nil {
ErrResponse(w, http.StatusBadRequest, err)
return
}
}
response := []*Topic{}
if revisionSet {
var slots []store.TopicSlot
if err := store.DB.Preload("Topic").Where("channel_id = ? AND revision > ?", channelSlot.Channel.ID, revision).Find(&slots).Error; err != nil {
ErrResponse(w, http.StatusInternalServerError, err)
return
if beginSet && !endSet {
if err := store.DB.Preload("Topic").Where("channel_id = ? AND revision > ? AND id >= ?", channelSlot.Channel.ID, revision, begin).Find(&slots).Error; err != nil {
ErrResponse(w, http.StatusInternalServerError, err)
return
}
} else if !beginSet && endSet {
if err := store.DB.Preload("Topic").Where("channel_id = ? AND revision > ? AND id < ?", channelSlot.Channel.ID, revision, end).Find(&slots).Error; err != nil {
ErrResponse(w, http.StatusInternalServerError, err)
return
}
} else if beginSet && endSet {
if err := store.DB.Preload("Topic").Where("channel_id = ? AND revision > ? AND id >= ? AND id < ?", channelSlot.Channel.ID, revision, begin, end).Find(&slots).Error; err != nil {
ErrResponse(w, http.StatusInternalServerError, err)
return
}
} else {
if err := store.DB.Preload("Topic").Where("channel_id = ? AND revision > ?", channelSlot.Channel.ID, revision).Find(&slots).Error; err != nil {
ErrResponse(w, http.StatusInternalServerError, err)
return
}
}
for _, slot := range slots {
response = append(response, getTopicRevisionModel(&slot))
}
} else {
var slots []store.TopicSlot
if err := store.DB.Preload("Topic.Assets").Where("channel_id = ?", channelSlot.Channel.ID).Find(&slots).Error; err != nil {
ErrResponse(w, http.StatusInternalServerError, err)
return
if countSet {
if !endSet {
if err := store.DB.Preload("Topic.Assets").Where("channel_id = ?", channelSlot.Channel.ID).Order("id desc").Limit(count).Find(&slots).Error; err != nil {
ErrResponse(w, http.StatusInternalServerError, err)
return
}
} else {
if err := store.DB.Preload("Topic.Assets").Where("channel_id = ? AND id < ?", channelSlot.Channel.ID, end).Order("id desc").Limit(count).Find(&slots).Error; err != nil {
ErrResponse(w, http.StatusInternalServerError, err)
return
}
}
slots = reverse(slots)
} else if beginSet && !endSet {
if err := store.DB.Preload("Topic.Assets").Where("channel_id = ? AND id >= ?", channelSlot.Channel.ID, begin).Find(&slots).Error; err != nil {
ErrResponse(w, http.StatusInternalServerError, err)
return
}
} else if !beginSet && endSet {
if err := store.DB.Preload("Topic.Assets").Where("channel_id = ? AND id < ?", channelSlot.Channel.ID, end).Find(&slots).Error; err != nil {
ErrResponse(w, http.StatusInternalServerError, err)
return
}
} else if beginSet && endSet {
if err := store.DB.Preload("Topic.Assets").Where("channel_id = ? AND id >= ? AND id < ?", channelSlot.Channel.ID, begin, end).Find(&slots).Error; err != nil {
ErrResponse(w, http.StatusInternalServerError, err)
return
}
} else {
if err := store.DB.Preload("Topic.Assets").Where("channel_id = ?", channelSlot.Channel.ID).Find(&slots).Error; err != nil {
ErrResponse(w, http.StatusInternalServerError, err)
return
}
}
for _, slot := range slots {
if slot.Topic != nil {
if countSet {
w.Header().Set("Topic-Index", strconv.FormatUint(uint64(slot.ID), 10))
countSet = false
}
response = append(response, getTopicModel(&slot))
}
}