From 0ceee0089f76476e3f84a74aa50459ba8083079d Mon Sep 17 00:00:00 2001 From: Roland Osborne Date: Sun, 3 Jul 2022 21:11:30 -0700 Subject: [PATCH] support staggard loading of tags --- doc/api.oa3 | 31 ++++- .../internal/api_getChannelTopicTags.go | 107 ++++++++++++++++-- net/server/internal/api_getChannelTopics.go | 6 +- 3 files changed, 132 insertions(+), 12 deletions(-) diff --git a/doc/api.oa3 b/doc/api.oa3 index 8099491d..77af5391 100644 --- a/doc/api.oa3 +++ b/doc/api.oa3 @@ -2982,16 +2982,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 latest from latest when revision not set + required: false + schema: + type: integer + format: int64 + - name: begin + in: query + description: return tags after and including sequence marker + required: false + schema: + type: integer + format: int64 + - name: end + in: query + description: return tags before and not including sequence marker + required: false + schema: + type: integer + format: int64 responses: '200': description: successful operation headers: - X-Tag-Revision: + Tag-Revision: schema: type: integer format: int64 description: current tag revision + Tag-Marker: + schema: + type: integer + format: int64 + description: sequnce marker of first tag when count set content: application/json: schema: diff --git a/net/server/internal/api_getChannelTopicTags.go b/net/server/internal/api_getChannelTopicTags.go index d8e00126..4d07a361 100644 --- a/net/server/internal/api_getChannelTopicTags.go +++ b/net/server/internal/api_getChannelTopicTags.go @@ -9,9 +9,23 @@ import ( "databag/internal/store" ) +func reverseTags(input []store.TagSlot) []store.TagSlot { + var output []store.TagSlot + for i := len(input) - 1; i >= 0; i-- { + output = append(output, input[i]) + } + return output +} + func GetChannelTopicTags(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 // load channel slot channelSlot, _, err, code := getChannelSlot(r, false) @@ -23,6 +37,7 @@ func GetChannelTopicTags(w http.ResponseWriter, r *http.Request) { // scan parameters params := mux.Vars(r) topicId := params["topicId"] + rev := r.FormValue("revision") if rev != "" { revisionSet = true @@ -32,6 +47,33 @@ func GetChannelTopicTags(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 + } + } + // load topic var topicSlot store.TopicSlot if err = store.DB.Preload("Topic").Where("channel_id = ? AND topic_slot_id = ?", channelSlot.Channel.ID, topicId).First(&topicSlot).Error; err != nil { @@ -47,24 +89,75 @@ func GetChannelTopicTags(w http.ResponseWriter, r *http.Request) { return } - var response []*Tag + response := []*Tag{} if revisionSet { var slots []store.TagSlot - if err := store.DB.Preload("Tag").Where("topic_id = ? AND revision > ?", topicSlot.Topic.ID, revision).Find(&slots).Error; err != nil { - ErrResponse(w, http.StatusInternalServerError, err) - return + if beginSet && !endSet { + if err := store.DB.Preload("Tag").Where("topic_id = ? AND revision > ? AND id >= ?", topicSlot.Topic.ID, revision, begin).Find(&slots).Error; err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } + } else if !beginSet && endSet { + if err := store.DB.Preload("Tag").Where("topic_id = ? AND revision > ? AND id < ?", topicSlot.Topic.ID, revision, end).Find(&slots).Error; err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } + } else if beginSet && endSet { + if err := store.DB.Preload("Tag").Where("topic_id = ? AND revision > ? AND id >= ? AND id < ?", topicSlot.Topic.ID, revision, begin, end).Find(&slots).Error; err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } + } else { + if err := store.DB.Preload("Tag").Where("topic_id = ? AND revision > ?", topicSlot.Topic.ID, revision).Find(&slots).Error; err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } } for _, slot := range slots { response = append(response, getTagModel(&slot)) } } else { var slots []store.TagSlot - if err := store.DB.Preload("Tag").Where("topic_id = ?", topicSlot.Topic.ID).Find(&slots).Error; err != nil { - ErrResponse(w, http.StatusInternalServerError, err) - return + if countSet { + if !endSet { + if err := store.DB.Preload("Tag").Where("topic_id = ?", topicSlot.Topic.ID).Order("id desc").Limit(count).Find(&slots).Error; err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } + } else { + if err := store.DB.Preload("Tag").Where("topic_id = ? AND id < ?", topicSlot.Topic.ID, end).Order("id desc").Limit(count).Find(&slots).Error; err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } + } + slots = reverseTags(slots) + } else if beginSet && !endSet { + if err := store.DB.Preload("Tag").Where("topic_id = ? AND id >= ?", topicSlot.Topic.ID, begin).Find(&slots).Error; err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } + } else if !beginSet && endSet { + if err := store.DB.Preload("Tag").Where("topic_id = ? AND id < ?", topicSlot.Topic.ID, end).Find(&slots).Error; err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } + } else if beginSet && endSet { + if err := store.DB.Preload("Tag").Where("topic_id = ? AND id >= ? AND id < ?", topicSlot.Topic.ID, begin, end).Find(&slots).Error; err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } + } else { + if err := store.DB.Preload("Tag").Where("topic_id = ?", topicSlot.Topic.ID).Find(&slots).Error; err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } } for _, slot := range slots { if slot.Tag != nil { + if countSet { + w.Header().Set("Tag-Marker", strconv.FormatUint(uint64(slot.ID), 10)) + countSet = false + } response = append(response, getTagModel(&slot)) } } diff --git a/net/server/internal/api_getChannelTopics.go b/net/server/internal/api_getChannelTopics.go index 871abed1..297ae070 100644 --- a/net/server/internal/api_getChannelTopics.go +++ b/net/server/internal/api_getChannelTopics.go @@ -6,7 +6,7 @@ import ( "databag/internal/store" ) -func reverse(input []store.TopicSlot) []store.TopicSlot { +func reverseTopics(input []store.TopicSlot) []store.TopicSlot { var output []store.TopicSlot for i := len(input) - 1; i >= 0; i-- { output = append(output, input[i]) @@ -107,7 +107,7 @@ func GetChannelTopics(w http.ResponseWriter, r *http.Request) { return } } - slots = reverse(slots) + slots = reverseTopics(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) @@ -132,7 +132,7 @@ func GetChannelTopics(w http.ResponseWriter, r *http.Request) { for _, slot := range slots { if slot.Topic != nil { if countSet { - w.Header().Set("Topic-Index", strconv.FormatUint(uint64(slot.ID), 10)) + w.Header().Set("Topic-Marker", strconv.FormatUint(uint64(slot.ID), 10)) countSet = false } response = append(response, getTopicModel(&slot))