From 42017035fc485eda9528d1dda32b5a5e4df3413a Mon Sep 17 00:00:00 2001 From: Untone Date: Tue, 21 May 2024 03:25:15 +0300 Subject: [PATCH] reimplement-following-data-proxy --- server/memorystore/providers/redis/store.go | 93 ++++++++++++++++----- 1 file changed, 73 insertions(+), 20 deletions(-) diff --git a/server/memorystore/providers/redis/store.go b/server/memorystore/providers/redis/store.go index 5dc8e88..5ced74b 100644 --- a/server/memorystore/providers/redis/store.go +++ b/server/memorystore/providers/redis/store.go @@ -227,42 +227,95 @@ type AuthorProfile struct { // GetUserAppDataFromRedis retrieves user profile and follows from Redis, combines them into a JSON format, // and assigns the JSON string to the provided user's ID. +f func (c *provider) GetUserAppDataFromRedis(userId string) (string, error) { - authorProfileString, err := c.store.Get(c.ctx, fmt.Sprintf(`user:%s`, userId)).Result() + // Получаем ID автора из Redis + authorIdString, err := c.store.Get(c.ctx, fmt.Sprintf("user:id:%s", userId)).Result() if err != nil { return "", err } - // Parse authorProfileString into a map + // Преобразуем ID автора из строки в int + var authorId int + err = json.Unmarshal([]byte(authorIdString), &authorId) + if err != nil { + return "", err + } + + // Получаем профиль автора из Redis + authorProfileString, err := c.store.Get(c.ctx, fmt.Sprintf("author:id:%d", authorId)).Result() + if err != nil { + return "", err + } + + // Парсим профиль пользователя в map var authorProfileMap map[string]interface{} err = json.Unmarshal([]byte(authorProfileString), &authorProfileMap) if err != nil { return "", err } - // Combine user data into a JSON string - combinedData := "{" - // Use authorProfileMap["id"] here if necessary - authorId := int(authorProfileMap["id"].(float64)) // convert float64 to int - combinedData += fmt.Sprintf(`"profile": %s`, authorProfileString) - - authorFollowsAuthorsString := c.store.Get(c.ctx, fmt.Sprintf(`author:%d:follows-authors`, authorId)).Val() - if authorFollowsAuthorsString != "" { - combinedData += fmt.Sprintf(`,"authors": %s`, authorFollowsAuthorsString) + // Начинаем сбор данных в общий JSON + combinedData := map[string]interface{}{ + "profile": authorProfileMap, } - authorFollowsTopicsString := c.store.Get(c.ctx, fmt.Sprintf(`author:%d:follows-topics`, authorId)).Val() - if authorFollowsTopicsString != "" { - combinedData += fmt.Sprintf(`,"topics": %s`, authorFollowsTopicsString) + // Получаем подписки автора на других авторов + if authorsObjectsString, err := c.getFollowedObjectsString(fmt.Sprintf("author:follows-authors:%d", authorId), "author:id:%d"); err == nil { + combinedData["authors"] = authorsObjectsString } - authorFollowers := c.store.Get(c.ctx, fmt.Sprintf(`author:%d:followers`, authorId)).Val() - if authorFollowers != "" { - combinedData += fmt.Sprintf(`,"followers": %s`, authorFollowers) + // Получаем подписки автора на темы + if topicsObjectString, err := c.getFollowedObjectsString(fmt.Sprintf("author:follows-topics:%d", authorId), "topic:id:%d"); err == nil { + combinedData["topics"] = topicsObjectString } - combinedData += "}" - // log.Printf("%v", combinedData) + // Получаем подписчиков автора + if authorFollowersObjectsString, err := c.getFollowedObjectsString(fmt.Sprintf("author:followers:%d", authorId), "author:id:%d"); err == nil { + combinedData["followers"] = authorFollowersObjectsString + } - return combinedData, nil + // Преобразуем собранные данные в JSON строку + combinedDataString, err := json.Marshal(combinedData) + if err != nil { + return "", err + } + + return string(combinedDataString), nil +} + +// Универсальная функция для получения объектов по списку ID из Redis +func (c *provider) getFollowedObjectsString(followKey string, objectKeyPattern string) ([]map[string]interface{}, error) { + followsString, err := c.store.Get(c.ctx, followKey).Result() + if err != nil { + if err == redis.Nil { + return []map[string]interface{}{}, nil + } + return nil, err + } + + var ids []int + err = json.Unmarshal([]byte(followsString), &ids) + if err != nil { + return nil, err + } + + objects := make([]map[string]interface{}, 0, len(ids)) + for _, id := range ids { + objectString, err := c.store.Get(c.ctx, fmt.Sprintf(objectKeyPattern, id)).Result() + if err == redis.Nil { + continue + } else if err != nil { + return nil, err + } + + var object map[string]interface{} + err = json.Unmarshal([]byte(objectString), &object) + if err != nil { + return nil, err + } + objects = append(objects, object) + } + + return objects, nil }