Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

database: add namespace to item #862

Merged
merged 6 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions master/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -807,7 +807,7 @@ func (m *Master) getRecommend(request *restful.Request, response *restful.Respon
// Send result
details := make([]data.Item, len(results))
for i := range results {
details[i], err = m.DataClient.GetItem(ctx, results[i])
details[i], err = m.DataClient.GetItem(ctx, "", results[i])
if err != nil {
server.InternalServerError(response, err)
return
Expand All @@ -832,7 +832,7 @@ func (m *Master) getTypedFeedbackByUser(request *restful.Request, response *rest
}
feedbackType := request.PathParameter("feedback-type")
userId := request.PathParameter("user-id")
feedback, err := m.DataClient.GetUserFeedback(ctx, userId, m.Config.Now(), feedbackType)
feedback, err := m.DataClient.GetUserFeedback(ctx, "", userId, m.Config.Now(), feedbackType)
if err != nil {
server.InternalServerError(response, err)
return
Expand All @@ -843,7 +843,7 @@ func (m *Master) getTypedFeedbackByUser(request *restful.Request, response *rest
details[i].UserId = feedback[i].UserId
details[i].Timestamp = feedback[i].Timestamp
details[i].Comment = feedback[i].Comment
details[i].Item, err = m.DataClient.GetItem(ctx, feedback[i].ItemId)
details[i].Item, err = m.DataClient.GetItem(ctx, "", feedback[i].ItemId)
if errors.Is(err, errors.NotFound) {
details[i].Item = data.Item{ItemId: feedback[i].ItemId, Comment: "** This item doesn't exist in Gorse **"}
} else if err != nil {
Expand Down Expand Up @@ -895,7 +895,7 @@ func (m *Master) searchDocuments(collection, subset, category string, request *r
details := make([]ScoredItem, len(scores))
for i := range scores {
details[i].Score = scores[i].Score
details[i].Item, err = m.DataClient.GetItem(ctx, scores[i].Id)
details[i].Item, err = m.DataClient.GetItem(ctx, "", scores[i].Id)
if err != nil {
server.InternalServerError(response, err)
return
Expand Down
2 changes: 1 addition & 1 deletion master/tasks.go
Original file line number Diff line number Diff line change
Expand Up @@ -1368,7 +1368,7 @@ func (t *CacheGarbageCollectionTask) run(ctx context.Context, j *task.JobsAlloca
return nil
}
// check item in database
_, err := t.DataClient.GetItem(ctx, itemId)
_, err := t.DataClient.GetItem(ctx, "", itemId)
if !errors.Is(err, errors.NotFound) {
if err != nil {
log.Logger().Error("failed to load item", zap.String("item_id", itemId), zap.Error(err))
Expand Down
36 changes: 18 additions & 18 deletions server/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,7 @@ func (s *RestServer) searchDocuments(collection, subset, category string, isItem

readItems := mapset.NewSet[string]()
if userId != "" {
feedback, err := s.DataClient.GetUserFeedback(ctx, userId, s.Config.Now())
feedback, err := s.DataClient.GetUserFeedback(ctx, "", userId, s.Config.Now())
if err != nil {
InternalServerError(response, err)
return
Expand Down Expand Up @@ -656,7 +656,7 @@ func (s *RestServer) getTypedFeedbackByItem(request *restful.Request, response *
}
feedbackType := request.PathParameter("feedback-type")
itemId := request.PathParameter("item-id")
feedback, err := s.DataClient.GetItemFeedback(ctx, itemId, feedbackType)
feedback, err := s.DataClient.GetItemFeedback(ctx, "", itemId, feedbackType)
if err != nil {
InternalServerError(response, err)
return
Expand All @@ -671,7 +671,7 @@ func (s *RestServer) getFeedbackByItem(request *restful.Request, response *restf
ctx = request.Request.Context()
}
itemId := request.PathParameter("item-id")
feedback, err := s.DataClient.GetItemFeedback(ctx, itemId)
feedback, err := s.DataClient.GetItemFeedback(ctx, "", itemId)
if err != nil {
InternalServerError(response, err)
return
Expand Down Expand Up @@ -774,7 +774,7 @@ type recommendContext struct {

func (s *RestServer) createRecommendContext(ctx context.Context, userId string, categories []string, n int) (*recommendContext, error) {
// pull historical feedback
userFeedback, err := s.DataClient.GetUserFeedback(ctx, userId, s.Config.Now())
userFeedback, err := s.DataClient.GetUserFeedback(ctx, "", userId, s.Config.Now())
if err != nil {
return nil, errors.Trace(err)
}
Expand Down Expand Up @@ -847,14 +847,14 @@ func (s *RestServer) RecommendUserBased(ctx *recommendContext) error {
}
for _, user := range similarUsers {
// load historical feedback
feedbacks, err := s.DataClient.GetUserFeedback(ctx.context, user.Id, s.Config.Now(), s.Config.Recommend.DataSource.PositiveFeedbackTypes...)
feedbacks, err := s.DataClient.GetUserFeedback(ctx.context, "", user.Id, s.Config.Now(), s.Config.Recommend.DataSource.PositiveFeedbackTypes...)
if err != nil {
return errors.Trace(err)
}
// add unseen items
for _, feedback := range feedbacks {
if !ctx.excludeSet.Contains(feedback.ItemId) {
item, err := s.DataClient.GetItem(ctx.context, feedback.ItemId)
item, err := s.DataClient.GetItem(ctx.context, "", feedback.ItemId)
if err != nil {
return errors.Trace(err)
}
Expand Down Expand Up @@ -1297,7 +1297,7 @@ func (s *RestServer) getTypedFeedbackByUser(request *restful.Request, response *
}
feedbackType := request.PathParameter("feedback-type")
userId := request.PathParameter("user-id")
feedback, err := s.DataClient.GetUserFeedback(ctx, userId, s.Config.Now(), feedbackType)
feedback, err := s.DataClient.GetUserFeedback(ctx, "", userId, s.Config.Now(), feedbackType)
if err != nil {
InternalServerError(response, err)
return
Expand All @@ -1312,7 +1312,7 @@ func (s *RestServer) getFeedbackByUser(request *restful.Request, response *restf
ctx = request.Request.Context()
}
userId := request.PathParameter("user-id")
feedback, err := s.DataClient.GetUserFeedback(ctx, userId, s.Config.Now())
feedback, err := s.DataClient.GetUserFeedback(ctx, "", userId, s.Config.Now())
if err != nil {
InternalServerError(response, err)
return
Expand Down Expand Up @@ -1345,7 +1345,7 @@ func (s *RestServer) batchInsertItems(ctx context.Context, response *restful.Res
)
// load existed items
start := time.Now()
existedItems, err := s.DataClient.BatchGetItems(ctx, lo.Map(temp, func(t Item, i int) string {
existedItems, err := s.DataClient.BatchGetItems(ctx, "", lo.Map(temp, func(t Item, i int) string {
return t.ItemId
}))
if err != nil {
Expand Down Expand Up @@ -1512,7 +1512,7 @@ func (s *RestServer) modifyItem(request *restful.Request, response *restful.Resp
}
}
// modify item
if err := s.DataClient.ModifyItem(ctx, itemId, patch); err != nil {
if err := s.DataClient.ModifyItem(ctx, "", itemId, patch); err != nil {
InternalServerError(response, err)
return
}
Expand Down Expand Up @@ -1556,7 +1556,7 @@ func (s *RestServer) getItem(request *restful.Request, response *restful.Respons
// Get item id
itemId := request.PathParameter("item-id")
// Get item
item, err := s.DataClient.GetItem(ctx, itemId)
item, err := s.DataClient.GetItem(ctx, "", itemId)
if err != nil {
if errors.Is(err, errors.NotFound) {
PageNotFound(response, err)
Expand All @@ -1575,7 +1575,7 @@ func (s *RestServer) deleteItem(request *restful.Request, response *restful.Resp
}
itemId := request.PathParameter("item-id")
// delete item from database
if err := s.DataClient.DeleteItem(ctx, itemId); err != nil {
if err := s.DataClient.DeleteItem(ctx, "", itemId); err != nil {
InternalServerError(response, err)
return
}
Expand All @@ -1596,7 +1596,7 @@ func (s *RestServer) insertItemCategory(request *restful.Request, response *rest
itemId := request.PathParameter("item-id")
category := request.PathParameter("category")
// fetch item
item, err := s.DataClient.GetItem(ctx, itemId)
item, err := s.DataClient.GetItem(ctx, "", itemId)
if err != nil {
InternalServerError(response, err)
return
Expand Down Expand Up @@ -1626,7 +1626,7 @@ func (s *RestServer) deleteItemCategory(request *restful.Request, response *rest
itemId := request.PathParameter("item-id")
category := request.PathParameter("category")
// fetch item
item, err := s.DataClient.GetItem(ctx, itemId)
item, err := s.DataClient.GetItem(ctx, "", itemId)
if err != nil {
InternalServerError(response, err)
return
Expand Down Expand Up @@ -1777,7 +1777,7 @@ func (s *RestServer) getUserItemFeedback(request *restful.Request, response *res
// Parse parameters
userId := request.PathParameter("user-id")
itemId := request.PathParameter("item-id")
if feedback, err := s.DataClient.GetUserItemFeedback(ctx, userId, itemId); err != nil {
if feedback, err := s.DataClient.GetUserItemFeedback(ctx, "", userId, itemId); err != nil {
InternalServerError(response, err)
} else {
Ok(response, feedback)
Expand All @@ -1792,7 +1792,7 @@ func (s *RestServer) deleteUserItemFeedback(request *restful.Request, response *
// Parse parameters
userId := request.PathParameter("user-id")
itemId := request.PathParameter("item-id")
if deleteCount, err := s.DataClient.DeleteUserItemFeedback(ctx, userId, itemId); err != nil {
if deleteCount, err := s.DataClient.DeleteUserItemFeedback(ctx, "", userId, itemId); err != nil {
InternalServerError(response, err)
} else {
Ok(response, Success{RowAffected: deleteCount})
Expand All @@ -1808,7 +1808,7 @@ func (s *RestServer) getTypedUserItemFeedback(request *restful.Request, response
feedbackType := request.PathParameter("feedback-type")
userId := request.PathParameter("user-id")
itemId := request.PathParameter("item-id")
if feedback, err := s.DataClient.GetUserItemFeedback(ctx, userId, itemId, feedbackType); err != nil {
if feedback, err := s.DataClient.GetUserItemFeedback(ctx, "", userId, itemId, feedbackType); err != nil {
InternalServerError(response, err)
} else if feedbackType == "" {
Text(response, "{}")
Expand All @@ -1826,7 +1826,7 @@ func (s *RestServer) deleteTypedUserItemFeedback(request *restful.Request, respo
feedbackType := request.PathParameter("feedback-type")
userId := request.PathParameter("user-id")
itemId := request.PathParameter("item-id")
if deleteCount, err := s.DataClient.DeleteUserItemFeedback(ctx, userId, itemId, feedbackType); err != nil {
if deleteCount, err := s.DataClient.DeleteUserItemFeedback(ctx, "", userId, itemId, feedbackType); err != nil {
InternalServerError(response, err)
} else {
Ok(response, Success{deleteCount})
Expand Down
8 changes: 4 additions & 4 deletions server/rest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -751,15 +751,15 @@ func (suite *ServerTestSuite) TestFeedback() {
Header("X-API-Key", apiKey).
Expect(t).
Status(http.StatusOK).
Body(`[{"FeedbackType":"click", "UserId": "2", "ItemId": "4", "Timestamp":"0001-01-01T00:00:00Z","Comment":""}]`).
Body(suite.marshal([]data.Feedback{feedback[2]})).
End()
apitest.New().
Handler(suite.handler).
Get("/api/item/4/feedback/click").
Header("X-API-Key", apiKey).
Expect(t).
Status(http.StatusOK).
Body(`[{"FeedbackType":"click", "UserId": "2", "ItemId": "4", "Timestamp":"0001-01-01T00:00:00Z","Comment":""}]`).
Body(suite.marshal([]data.Feedback{feedback[2]})).
End()
// test overwrite
apitest.New().
Expand All @@ -774,7 +774,7 @@ func (suite *ServerTestSuite) TestFeedback() {
Status(http.StatusOK).
Body(`{"RowAffected": 1}`).
End()
ret, err := suite.DataClient.GetUserFeedback(ctx, "0", suite.Config.Now(), "click")
ret, err := suite.DataClient.GetUserFeedback(ctx, "", "0", suite.Config.Now(), "click")
assert.NoError(t, err)
assert.Equal(t, 1, len(ret))
assert.Equal(t, "override", ret[0].Comment)
Expand All @@ -791,7 +791,7 @@ func (suite *ServerTestSuite) TestFeedback() {
Status(http.StatusOK).
Body(`{"RowAffected": 1}`).
End()
ret, err = suite.DataClient.GetUserFeedback(ctx, "0", suite.Config.Now(), "click")
ret, err = suite.DataClient.GetUserFeedback(ctx, "", "0", suite.Config.Now(), "click")
assert.NoError(t, err)
assert.Equal(t, 1, len(ret))
assert.Equal(t, "override", ret[0].Comment)
Expand Down
37 changes: 29 additions & 8 deletions storage/data/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ func ValidateLabels(o any) error {

// Item stores meta data about item.
type Item struct {
Namespace string `gorm:"primaryKey" mapstructure:"namespace"`
ItemId string `gorm:"primaryKey" mapstructure:"item_id"`
IsHidden bool `mapstructure:"is_hidden"`
Categories []string `gorm:"serializer:json" mapstructure:"categories"`
Expand All @@ -116,6 +117,18 @@ type ItemPatch struct {
Comment *string
}

type ItemUID struct {
Namespace string
ItemId string
}

func (item *Item) ItemUID() ItemUID {
return ItemUID{
Namespace: item.Namespace,
ItemId: item.ItemId,
}
}

// User stores meta data about user.
type User struct {
UserId string `gorm:"primaryKey" mapstructure:"user_id"`
Expand All @@ -133,11 +146,19 @@ type UserPatch struct {

// FeedbackKey identifies feedback.
type FeedbackKey struct {
Namespace string `gorm:"column:namespace" mapstructure:"namespace"`
FeedbackType string `gorm:"column:feedback_type" mapstructure:"feedback_type"`
UserId string `gorm:"column:user_id" mapstructure:"user_id"`
ItemId string `gorm:"column:item_id" mapstructure:"item_id"`
}

func (key *FeedbackKey) ItemUID() ItemUID {
return ItemUID{
Namespace: key.Namespace,
ItemId: key.ItemId,
}
}

// Feedback stores feedback.
type Feedback struct {
FeedbackKey `gorm:"embedded" mapstructure:",squash"`
Expand Down Expand Up @@ -225,20 +246,20 @@ type Database interface {
Close() error
Purge() error
BatchInsertItems(ctx context.Context, items []Item) error
BatchGetItems(ctx context.Context, itemIds []string) ([]Item, error)
DeleteItem(ctx context.Context, itemId string) error
GetItem(ctx context.Context, itemId string) (Item, error)
ModifyItem(ctx context.Context, itemId string, patch ItemPatch) error
BatchGetItems(ctx context.Context, namespace string, itemIds []string) ([]Item, error)
DeleteItem(ctx context.Context, namespace, itemId string) error
GetItem(ctx context.Context, namespace, itemId string) (Item, error)
ModifyItem(ctx context.Context, namespace, itemId string, patch ItemPatch) error
GetItems(ctx context.Context, cursor string, n int, beginTime *time.Time) (string, []Item, error)
GetItemFeedback(ctx context.Context, itemId string, feedbackTypes ...string) ([]Feedback, error)
GetItemFeedback(ctx context.Context, namespace, itemId string, feedbackTypes ...string) ([]Feedback, error)
BatchInsertUsers(ctx context.Context, users []User) error
DeleteUser(ctx context.Context, userId string) error
GetUser(ctx context.Context, userId string) (User, error)
ModifyUser(ctx context.Context, userId string, patch UserPatch) error
GetUsers(ctx context.Context, cursor string, n int) (string, []User, error)
GetUserFeedback(ctx context.Context, userId string, endTime *time.Time, feedbackTypes ...string) ([]Feedback, error)
GetUserItemFeedback(ctx context.Context, userId, itemId string, feedbackTypes ...string) ([]Feedback, error)
DeleteUserItemFeedback(ctx context.Context, userId, itemId string, feedbackTypes ...string) (int, error)
GetUserFeedback(ctx context.Context, namespace, userId string, endTime *time.Time, feedbackTypes ...string) ([]Feedback, error)
GetUserItemFeedback(ctx context.Context, namespace, userId, itemId string, feedbackTypes ...string) ([]Feedback, error)
DeleteUserItemFeedback(ctx context.Context, namespace, userId, itemId string, feedbackTypes ...string) (int, error)
BatchInsertFeedback(ctx context.Context, feedback []Feedback, insertUser, insertItem, overwrite bool) error
GetFeedback(ctx context.Context, cursor string, n int, beginTime, endTime *time.Time, feedbackTypes ...string) (string, []Feedback, error)
GetUserStream(ctx context.Context, batchSize int) (chan []User, chan error)
Expand Down
Loading
Loading