feat: implement core backend architecture and project management services for the History API
Build and Release / release (push) Successful in 1m33s

This commit is contained in:
2026-06-05 14:18:55 +07:00
parent 420a9ad43a
commit fdcd44cc00
70 changed files with 944 additions and 734 deletions
+26 -27
View File
@@ -2,8 +2,7 @@ package repositories
import (
"context"
"encoding/json"
"fmt"
json "history-api/pkg/jsonx"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
@@ -66,14 +65,14 @@ func (r *battleReplayRepository) getByIDsWithFallback(ctx context.Context, ids [
}
keys := make([]string, len(ids))
for i, id := range ids {
keys[i] = fmt.Sprintf("battle_replay:id:%s", id)
keys[i] = cache.Key("battle_replay:id", id)
}
raws := r.c.MGet(ctx, keys...)
var items []*models.BattleReplayEntity
missingToCache := make(map[string]any)
items := make([]*models.BattleReplayEntity, 0, len(ids))
missingToCache := make(map[string]any, len(ids))
var missingPgIds []pgtype.UUID
missingPgIds := make([]pgtype.UUID, 0, len(ids))
for i, b := range raws {
if len(b) == 0 {
pgId := pgtype.UUID{}
@@ -84,7 +83,7 @@ func (r *battleReplayRepository) getByIDsWithFallback(ctx context.Context, ids [
}
}
dbMap := make(map[string]*models.BattleReplayEntity)
dbMap := make(map[string]*models.BattleReplayEntity, len(missingPgIds))
if len(missingPgIds) > 0 {
dbRows, err := r.q.GetBattleReplaysByIDs(ctx, missingPgIds)
if err == nil {
@@ -121,7 +120,7 @@ func (r *battleReplayRepository) GetByIDs(ctx context.Context, ids []string) ([]
}
func (r *battleReplayRepository) GetByID(ctx context.Context, id pgtype.UUID) (*models.BattleReplayEntity, error) {
cacheId := fmt.Sprintf("battle_replay:id:%s", convert.UUIDToString(id))
cacheId := cache.Key("battle_replay:id", convert.UUIDToString(id))
var item models.BattleReplayEntity
err := r.c.Get(ctx, cacheId, &item)
if err == nil {
@@ -141,7 +140,7 @@ func (r *battleReplayRepository) GetByID(ctx context.Context, id pgtype.UUID) (*
}
func (r *battleReplayRepository) GetByGeometryID(ctx context.Context, geometryID pgtype.UUID) ([]*models.BattleReplayEntity, error) {
cacheKey := fmt.Sprintf("battle_replay:geometry:%s", convert.UUIDToString(geometryID))
cacheKey := cache.Key("battle_replay:geometry", convert.UUIDToString(geometryID))
var cachedIDs []string
err := r.c.Get(ctx, cacheKey, &cachedIDs)
if err == nil {
@@ -156,15 +155,15 @@ func (r *battleReplayRepository) GetByGeometryID(ctx context.Context, geometryID
return nil, err
}
var items []*models.BattleReplayEntity
var ids []string
itemToCache := make(map[string]any)
items := make([]*models.BattleReplayEntity, 0, len(rows))
ids := make([]string, 0, len(rows))
itemToCache := make(map[string]any, len(rows))
for _, row := range rows {
item := r.rowToEntity(row)
ids = append(ids, item.ID)
items = append(items, item)
itemToCache[fmt.Sprintf("battle_replay:id:%s", item.ID)] = item
itemToCache[cache.Key("battle_replay:id", item.ID)] = item
}
if len(itemToCache) > 0 {
@@ -180,7 +179,7 @@ func (r *battleReplayRepository) GetByGeometryIDs(ctx context.Context, geometryI
return []*models.BattleReplayEntity{}, nil
}
var pgIds []pgtype.UUID
pgIds := make([]pgtype.UUID, 0, len(geometryIDs))
for _, id := range geometryIDs {
pgId := pgtype.UUID{}
if err := pgId.Scan(id); err == nil {
@@ -193,13 +192,13 @@ func (r *battleReplayRepository) GetByGeometryIDs(ctx context.Context, geometryI
return nil, err
}
var items []*models.BattleReplayEntity
itemToCache := make(map[string]any)
items := make([]*models.BattleReplayEntity, 0, len(rows))
itemToCache := make(map[string]any, len(rows))
for _, row := range rows {
item := r.rowToEntity(row)
items = append(items, item)
itemToCache[fmt.Sprintf("battle_replay:id:%s", item.ID)] = item
itemToCache[cache.Key("battle_replay:id", item.ID)] = item
}
if len(itemToCache) > 0 {
@@ -210,7 +209,7 @@ func (r *battleReplayRepository) GetByGeometryIDs(ctx context.Context, geometryI
}
func (r *battleReplayRepository) GetByProjectID(ctx context.Context, projectID pgtype.UUID) ([]*models.BattleReplayEntity, error) {
cacheKey := fmt.Sprintf("battle_replay:project:%s", convert.UUIDToString(projectID))
cacheKey := cache.Key("battle_replay:project", convert.UUIDToString(projectID))
var cachedIDs []string
err := r.c.Get(ctx, cacheKey, &cachedIDs)
if err == nil {
@@ -225,15 +224,15 @@ func (r *battleReplayRepository) GetByProjectID(ctx context.Context, projectID p
return nil, err
}
var items []*models.BattleReplayEntity
var ids []string
itemToCache := make(map[string]any)
items := make([]*models.BattleReplayEntity, 0, len(rows))
ids := make([]string, 0, len(rows))
itemToCache := make(map[string]any, len(rows))
for _, row := range rows {
item := r.rowToEntity(row)
ids = append(ids, item.ID)
items = append(items, item)
itemToCache[fmt.Sprintf("battle_replay:id:%s", item.ID)] = item
itemToCache[cache.Key("battle_replay:id", item.ID)] = item
}
if len(itemToCache) > 0 {
@@ -252,8 +251,8 @@ func (r *battleReplayRepository) Create(ctx context.Context, params sqlc.CreateB
entity := r.rowToEntity(row)
_ = r.c.Del(ctx, fmt.Sprintf("battle_replay:project:%s", entity.ProjectID))
_ = r.c.Del(ctx, fmt.Sprintf("battle_replay:geometry:%s", entity.GeometryID))
_ = r.c.Del(ctx, cache.Key("battle_replay:project", entity.ProjectID))
_ = r.c.Del(ctx, cache.Key("battle_replay:geometry", entity.GeometryID))
return entity, nil
}
@@ -265,7 +264,7 @@ func (r *battleReplayRepository) Update(ctx context.Context, params sqlc.UpdateB
}
entity := r.rowToEntity(row)
_ = r.c.Del(ctx, fmt.Sprintf("battle_replay:id:%s", entity.ID))
_ = r.c.Del(ctx, cache.Key("battle_replay:id", entity.ID))
return entity, nil
}
@@ -274,7 +273,7 @@ func (r *battleReplayRepository) Delete(ctx context.Context, id pgtype.UUID) err
if err != nil {
return err
}
_ = r.c.Del(ctx, fmt.Sprintf("battle_replay:id:%s", convert.UUIDToString(id)))
_ = r.c.Del(ctx, cache.Key("battle_replay:id", convert.UUIDToString(id)))
return nil
}
@@ -286,7 +285,7 @@ func (r *battleReplayRepository) DeleteByIDs(ctx context.Context, ids []pgtype.U
if len(ids) > 0 {
keys := make([]string, len(ids))
for i, id := range ids {
keys[i] = fmt.Sprintf("battle_replay:id:%s", convert.UUIDToString(id))
keys[i] = cache.Key("battle_replay:id", convert.UUIDToString(id))
}
_ = r.c.Del(ctx, keys...)
}
+31 -37
View File
@@ -2,14 +2,13 @@ package repositories
import (
"context"
"crypto/md5"
"encoding/json"
"fmt"
"history-api/internal/gen/sqlc"
"history-api/internal/models"
"history-api/pkg/cache"
"history-api/pkg/constants"
"history-api/pkg/convert"
json "history-api/pkg/jsonx"
"strconv"
"github.com/jackc/pgx/v5/pgtype"
"github.com/jackc/pgx/v5/pgxpool"
@@ -39,9 +38,7 @@ func NewChatRepository(db *pgxpool.Pool, c cache.Cache) ChatRepository {
}
func (r *chatRepository) generateQueryKey(prefix string, params any) string {
b, _ := json.Marshal(params)
hash := fmt.Sprintf("%x", md5.Sum(b))
return fmt.Sprintf("%s:query:%s", prefix, hash)
return cache.QueryKey(prefix, params)
}
func (r *chatRepository) getConversationsByIDsWithFallback(ctx context.Context, ids []string) ([]*models.ConversationEntity, error) {
@@ -50,14 +47,14 @@ func (r *chatRepository) getConversationsByIDsWithFallback(ctx context.Context,
}
keys := make([]string, len(ids))
for i, id := range ids {
keys[i] = fmt.Sprintf("conversation:id:%s", id)
keys[i] = cache.Key("conversation:id", id)
}
raws := r.c.MGet(ctx, keys...)
var results []*models.ConversationEntity
missingToCache := make(map[string]any)
results := make([]*models.ConversationEntity, 0, len(ids))
missingToCache := make(map[string]any, len(ids))
var missingPgIds []pgtype.UUID
missingPgIds := make([]pgtype.UUID, 0, len(ids))
for i, b := range raws {
if len(b) == 0 {
pgId := pgtype.UUID{}
@@ -68,7 +65,7 @@ func (r *chatRepository) getConversationsByIDsWithFallback(ctx context.Context,
}
}
dbMap := make(map[string]*models.ConversationEntity)
dbMap := make(map[string]*models.ConversationEntity, len(missingPgIds))
if len(missingPgIds) > 0 {
dbRows, err := r.q.GetConversationsByIDs(ctx, missingPgIds)
if err == nil {
@@ -114,14 +111,14 @@ func (r *chatRepository) getMessagesByIDsWithFallback(ctx context.Context, ids [
}
keys := make([]string, len(ids))
for i, id := range ids {
keys[i] = fmt.Sprintf("message:id:%s", id)
keys[i] = cache.Key("message:id", id)
}
raws := r.c.MGet(ctx, keys...)
var results []*models.MessageEntity
missingToCache := make(map[string]any)
results := make([]*models.MessageEntity, 0, len(ids))
missingToCache := make(map[string]any, len(ids))
var missingPgIds []pgtype.UUID
missingPgIds := make([]pgtype.UUID, 0, len(ids))
for i, b := range raws {
if len(b) == 0 {
pgId := pgtype.UUID{}
@@ -132,7 +129,7 @@ func (r *chatRepository) getMessagesByIDsWithFallback(ctx context.Context, ids [
}
}
dbMap := make(map[string]*models.MessageEntity)
dbMap := make(map[string]*models.MessageEntity, len(missingPgIds))
if len(missingPgIds) > 0 {
dbRows, err := r.q.GetMessagesByIDs(ctx, missingPgIds)
if err == nil {
@@ -176,14 +173,14 @@ func (r *chatRepository) getChatbotHistoriesByIDsWithFallback(ctx context.Contex
}
keys := make([]string, len(ids))
for i, id := range ids {
keys[i] = fmt.Sprintf("chatbot_history:id:%s", id)
keys[i] = cache.Key("chatbot_history:id", id)
}
raws := r.c.MGet(ctx, keys...)
var results []*models.ChatbotHistoryEntity
missingToCache := make(map[string]any)
results := make([]*models.ChatbotHistoryEntity, 0, len(ids))
missingToCache := make(map[string]any, len(ids))
var missingPgIds []pgtype.UUID
missingPgIds := make([]pgtype.UUID, 0, len(ids))
for i, b := range raws {
if len(b) == 0 {
pgId := pgtype.UUID{}
@@ -194,7 +191,7 @@ func (r *chatRepository) getChatbotHistoriesByIDsWithFallback(ctx context.Contex
}
}
dbMap := make(map[string]*models.ChatbotHistoryEntity)
dbMap := make(map[string]*models.ChatbotHistoryEntity, len(missingPgIds))
if len(missingPgIds) > 0 {
dbRows, err := r.q.GetChatbotHistoriesByIDs(ctx, missingPgIds)
if err == nil {
@@ -263,7 +260,7 @@ func (r *chatRepository) UpdateConversationStatus(ctx context.Context, params sq
CreatedAt: convert.TimeToPtr(row.CreatedAt),
UpdatedAt: convert.TimeToPtr(row.UpdatedAt),
}
_ = r.c.Del(ctx, fmt.Sprintf("conversation:id:%s", entity.ID))
_ = r.c.Del(ctx, cache.Key("conversation:id", entity.ID))
return entity, nil
}
@@ -299,9 +296,9 @@ func (r *chatRepository) GetMessagesByConversation(ctx context.Context, params s
return nil, err
}
var results []*models.MessageEntity
var ids []string
toCache := make(map[string]any)
results := make([]*models.MessageEntity, 0, len(rows))
ids := make([]string, 0, len(rows))
toCache := make(map[string]any, len(rows))
for _, row := range rows {
item := &models.MessageEntity{
@@ -313,7 +310,7 @@ func (r *chatRepository) GetMessagesByConversation(ctx context.Context, params s
}
ids = append(ids, item.ID)
results = append(results, item)
toCache[fmt.Sprintf("message:id:%s", item.ID)] = item
toCache[cache.Key("message:id", item.ID)] = item
}
if len(toCache) > 0 {
@@ -341,7 +338,7 @@ func (r *chatRepository) CreateChatbotHistory(ctx context.Context, params sqlc.C
go func() {
userId := convert.UUIDToString(params.UserID)
if userId != "" {
_ = r.c.DelByPattern(context.Background(), fmt.Sprintf("chatbot_history:userId:%s:*", userId))
_ = r.c.DelByPattern(context.Background(), "chatbot_history:userId:"+userId+":*")
}
}()
@@ -349,12 +346,9 @@ func (r *chatRepository) CreateChatbotHistory(ctx context.Context, params sqlc.C
}
func (r *chatRepository) GetChatbotHistory(ctx context.Context, params sqlc.GetChatbotHistoryParams) ([]*models.ChatbotHistoryEntity, error) {
queryKey := fmt.Sprintf(
"chatbot_history:userId:%s:limit:%d:cursor:%s",
convert.UUIDToString(params.UserID),
params.Limit,
convert.UUIDToString(params.CursorID),
)
queryKey := "chatbot_history:userId:" + convert.UUIDToString(params.UserID) +
":limit:" + strconv.Itoa(int(params.Limit)) +
":cursor:" + convert.UUIDToString(params.CursorID)
var cachedIDs []string
err := r.c.Get(ctx, queryKey, &cachedIDs)
if err == nil {
@@ -369,9 +363,9 @@ func (r *chatRepository) GetChatbotHistory(ctx context.Context, params sqlc.GetC
return nil, err
}
var results []*models.ChatbotHistoryEntity
var ids []string
toCache := make(map[string]any)
results := make([]*models.ChatbotHistoryEntity, 0, len(rows))
ids := make([]string, 0, len(rows))
toCache := make(map[string]any, len(rows))
for _, row := range rows {
item := &models.ChatbotHistoryEntity{
@@ -383,7 +377,7 @@ func (r *chatRepository) GetChatbotHistory(ctx context.Context, params sqlc.GetC
}
ids = append(ids, item.ID)
results = append(results, item)
toCache[fmt.Sprintf("chatbot_history:id:%s", item.ID)] = item
toCache[cache.Key("chatbot_history:id", item.ID)] = item
}
if len(toCache) > 0 {
+17 -20
View File
@@ -2,14 +2,13 @@ package repositories
import (
"context"
"crypto/md5"
"encoding/json"
"fmt"
"history-api/internal/gen/sqlc"
"history-api/internal/models"
"history-api/pkg/cache"
"history-api/pkg/constants"
"history-api/pkg/convert"
"history-api/pkg/jsonx"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
@@ -62,7 +61,7 @@ func (r *commitRepository) Create(ctx context.Context, params sqlc.CreateCommitP
}
func (r *commitRepository) GetByID(ctx context.Context, id pgtype.UUID) (*models.CommitEntity, error) {
cacheId := fmt.Sprintf("commit:id:%s", convert.UUIDToString(id))
cacheId := cache.Key("commit:id", convert.UUIDToString(id))
var commit models.CommitEntity
err := r.c.Get(ctx, cacheId, &commit)
if err == nil {
@@ -92,9 +91,7 @@ func (r *commitRepository) GetByID(ctx context.Context, id pgtype.UUID) (*models
}
func (r *commitRepository) generateQueryKey(prefix string, params any) string {
b, _ := json.Marshal(params)
hash := fmt.Sprintf("%x", md5.Sum(b))
return fmt.Sprintf("%s:query:%s", prefix, hash)
return cache.QueryKey(prefix, params)
}
func (r *commitRepository) getByIDsWithFallback(ctx context.Context, ids []string) ([]*models.CommitEntity, error) {
@@ -103,14 +100,14 @@ func (r *commitRepository) getByIDsWithFallback(ctx context.Context, ids []strin
}
keys := make([]string, len(ids))
for i, id := range ids {
keys[i] = fmt.Sprintf("commit:id:%s", id)
keys[i] = cache.Key("commit:id", id)
}
raws := r.c.MGet(ctx, keys...)
var commits []*models.CommitEntity
missingToCache := make(map[string]any)
commits := make([]*models.CommitEntity, 0, len(ids))
missingToCache := make(map[string]any, len(ids))
var missingPgIds []pgtype.UUID
missingPgIds := make([]pgtype.UUID, 0, len(ids))
for i, b := range raws {
if len(b) == 0 {
pgId := pgtype.UUID{}
@@ -121,7 +118,7 @@ func (r *commitRepository) getByIDsWithFallback(ctx context.Context, ids []strin
}
}
dbMap := make(map[string]*models.CommitEntity)
dbMap := make(map[string]*models.CommitEntity, len(missingPgIds))
if len(missingPgIds) > 0 {
dbRows, err := r.q.GetCommitsByIDs(ctx, missingPgIds)
if err == nil {
@@ -144,7 +141,7 @@ func (r *commitRepository) getByIDsWithFallback(ctx context.Context, ids []strin
for i, b := range raws {
if len(b) > 0 {
var c models.CommitEntity
if err := json.Unmarshal(b, &c); err == nil {
if err := jsonx.Unmarshal(b, &c); err == nil {
commits = append(commits, &c)
}
} else {
@@ -163,7 +160,7 @@ func (r *commitRepository) getByIDsWithFallback(ctx context.Context, ids []strin
}
func (r *commitRepository) GetByProjectID(ctx context.Context, projectID pgtype.UUID) ([]*models.CommitEntity, error) {
queryKey := fmt.Sprintf("commit:project:%s", convert.UUIDToString(projectID))
queryKey := cache.Key("commit:project", convert.UUIDToString(projectID))
var cachedIDs []string
err := r.c.Get(ctx, queryKey, &cachedIDs)
if err == nil {
@@ -180,7 +177,7 @@ func (r *commitRepository) GetByProjectID(ctx context.Context, projectID pgtype.
entities := make([]*models.CommitEntity, 0, len(rows))
ids := make([]string, len(rows))
commitToCache := make(map[string]any)
commitToCache := make(map[string]any, len(rows))
for i, row := range rows {
item := &models.CommitEntity{
ID: convert.UUIDToString(row.ID),
@@ -194,7 +191,7 @@ func (r *commitRepository) GetByProjectID(ctx context.Context, projectID pgtype.
}
entities = append(entities, item)
ids[i] = item.ID
commitToCache[fmt.Sprintf("commit:id:%s", item.ID)] = item
commitToCache[cache.Key("commit:id", item.ID)] = item
}
if len(commitToCache) > 0 {
_ = r.c.MSet(ctx, commitToCache, constants.NormalCacheDuration)
@@ -217,9 +214,9 @@ func (r *commitRepository) Search(ctx context.Context, params sqlc.SearchCommits
if err != nil {
return nil, err
}
var commits []*models.CommitEntity
var ids []string
commitToCache := make(map[string]any)
commits := make([]*models.CommitEntity, 0, len(rows))
ids := make([]string, 0, len(rows))
commitToCache := make(map[string]any, len(rows))
for _, row := range rows {
commit := &models.CommitEntity{
@@ -234,7 +231,7 @@ func (r *commitRepository) Search(ctx context.Context, params sqlc.SearchCommits
}
ids = append(ids, commit.ID)
commits = append(commits, commit)
commitToCache[fmt.Sprintf("commit:id:%s", commit.ID)] = commit
commitToCache[cache.Key("commit:id", commit.ID)] = commit
}
if len(commitToCache) > 0 {
@@ -253,7 +250,7 @@ func (r *commitRepository) UpdateSnapshot(ctx context.Context, id pgtype.UUID, s
if err != nil {
return nil, err
}
r.c.Del(ctx, fmt.Sprintf("commit:id:%s", convert.UUIDToString(id)))
r.c.Del(ctx, cache.Key("commit:id", convert.UUIDToString(id)))
return &models.CommitEntity{
ID: convert.UUIDToString(row.ID),
+33 -38
View File
@@ -2,9 +2,7 @@ package repositories
import (
"context"
"crypto/md5"
"encoding/json"
"fmt"
json "history-api/pkg/jsonx"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
@@ -51,9 +49,7 @@ func (r *entityRepository) WithTx(tx pgx.Tx) EntityRepository {
}
func (r *entityRepository) generateQueryKey(prefix string, params any) string {
b, _ := json.Marshal(params)
hash := fmt.Sprintf("%x", md5.Sum(b))
return fmt.Sprintf("%s:%s", prefix, hash)
return cache.QueryKey(prefix, params)
}
func (r *entityRepository) getByIDsWithFallback(ctx context.Context, ids []string) ([]*models.EntityEntity, error) {
@@ -62,14 +58,14 @@ func (r *entityRepository) getByIDsWithFallback(ctx context.Context, ids []strin
}
keys := make([]string, len(ids))
for i, id := range ids {
keys[i] = fmt.Sprintf("entity:id:%s", id)
keys[i] = cache.Key("entity:id", id)
}
raws := r.c.MGet(ctx, keys...)
var entities []*models.EntityEntity
missingToCache := make(map[string]any)
entities := make([]*models.EntityEntity, 0, len(ids))
missingToCache := make(map[string]any, len(ids))
var missingPgIds []pgtype.UUID
missingPgIds := make([]pgtype.UUID, 0, len(ids))
for i, b := range raws {
if len(b) == 0 {
pgId := pgtype.UUID{}
@@ -80,7 +76,7 @@ func (r *entityRepository) getByIDsWithFallback(ctx context.Context, ids []strin
}
}
dbMap := make(map[string]*models.EntityEntity)
dbMap := make(map[string]*models.EntityEntity, len(missingPgIds))
if len(missingPgIds) > 0 {
dbRows, err := r.q.GetEntitiesByIDs(ctx, missingPgIds)
if err == nil {
@@ -129,7 +125,7 @@ func (r *entityRepository) GetByIDs(ctx context.Context, ids []string) ([]*model
}
func (r *entityRepository) GetByID(ctx context.Context, id pgtype.UUID) (*models.EntityEntity, error) {
cacheId := fmt.Sprintf("entity:id:%s", convert.UUIDToString(id))
cacheId := cache.Key("entity:id", convert.UUIDToString(id))
var entity models.EntityEntity
err := r.c.Get(ctx, cacheId, &entity)
if err == nil {
@@ -175,9 +171,9 @@ func (r *entityRepository) Search(ctx context.Context, params sqlc.SearchEntitie
if err != nil {
return nil, err
}
var entities []*models.EntityEntity
var ids []string
entityToCache := make(map[string]any)
entities := make([]*models.EntityEntity, 0, len(rows))
ids := make([]string, 0, len(rows))
entityToCache := make(map[string]any, len(rows))
for _, row := range rows {
entity := &models.EntityEntity{
@@ -195,7 +191,7 @@ func (r *entityRepository) Search(ctx context.Context, params sqlc.SearchEntitie
}
ids = append(ids, entity.ID)
entities = append(entities, entity)
entityToCache[fmt.Sprintf("entity:id:%s", entity.ID)] = entity
entityToCache[cache.Key("entity:id", entity.ID)] = entity
}
if len(entityToCache) > 0 {
@@ -248,8 +244,7 @@ func (r *entityRepository) Update(ctx context.Context, params sqlc.UpdateEntityP
CreatedAt: convert.TimeToPtr(row.CreatedAt),
UpdatedAt: convert.TimeToPtr(row.UpdatedAt),
}
_ = r.c.Del(ctx, fmt.Sprintf("entity:id:%s", entity.ID))
_ = r.c.Del(ctx, fmt.Sprintf("entity:slug:%s", entity.Slug))
_ = r.c.Del(ctx, cache.Key("entity:id", entity.ID), cache.Key("entity:slug", entity.Slug))
return &entity, nil
}
@@ -258,12 +253,12 @@ func (r *entityRepository) Delete(ctx context.Context, id pgtype.UUID) error {
if err != nil {
return err
}
_ = r.c.Del(ctx, fmt.Sprintf("entity:id:%s", convert.UUIDToString(id)))
_ = r.c.Del(ctx, cache.Key("entity:id", convert.UUIDToString(id)))
return nil
}
func (r *entityRepository) GetByProjectID(ctx context.Context, projectID pgtype.UUID) ([]*models.EntityEntity, error) {
cacheKey := fmt.Sprintf("entity:project:%s", convert.UUIDToString(projectID))
cacheKey := cache.Key("entity:project", convert.UUIDToString(projectID))
var cachedIDs []string
err := r.c.Get(ctx, cacheKey, &cachedIDs)
if err == nil {
@@ -278,9 +273,9 @@ func (r *entityRepository) GetByProjectID(ctx context.Context, projectID pgtype.
return nil, err
}
var entities []*models.EntityEntity
var ids []string
entityToCache := make(map[string]any)
entities := make([]*models.EntityEntity, 0, len(rows))
ids := make([]string, 0, len(rows))
entityToCache := make(map[string]any, len(rows))
for _, row := range rows {
entity := &models.EntityEntity{
@@ -298,7 +293,7 @@ func (r *entityRepository) GetByProjectID(ctx context.Context, projectID pgtype.
}
ids = append(ids, entity.ID)
entities = append(entities, entity)
entityToCache[fmt.Sprintf("entity:id:%s", entity.ID)] = entity
entityToCache[cache.Key("entity:id", entity.ID)] = entity
}
if len(entityToCache) > 0 {
@@ -317,7 +312,7 @@ func (r *entityRepository) DeleteByIDs(ctx context.Context, ids []pgtype.UUID) e
if len(ids) > 0 {
keys := make([]string, len(ids))
for i, id := range ids {
keys[i] = fmt.Sprintf("entity:id:%s", convert.UUIDToString(id))
keys[i] = cache.Key("entity:id", convert.UUIDToString(id))
}
_ = r.c.Del(ctx, keys...)
}
@@ -325,7 +320,7 @@ func (r *entityRepository) DeleteByIDs(ctx context.Context, ids []pgtype.UUID) e
}
func (r *entityRepository) GetBySlug(ctx context.Context, slug string) (*models.EntityEntity, error) {
cacheKey := fmt.Sprintf("entity:slug:%s", slug)
cacheKey := cache.Key("entity:slug", slug)
var entity models.EntityEntity
err := r.c.Get(ctx, cacheKey, &entity)
if err == nil {
@@ -362,13 +357,13 @@ func (r *entityRepository) GetBySlugs(ctx context.Context, slugs []string) ([]*m
}
keys := make([]string, len(slugs))
for i, slug := range slugs {
keys[i] = fmt.Sprintf("entity:slug:%s", slug)
keys[i] = cache.Key("entity:slug", slug)
}
raws := r.c.MGet(ctx, keys...)
var entities []*models.EntityEntity
missingToCache := make(map[string]any)
var missingSlugs []string
entities := make([]*models.EntityEntity, 0, len(slugs))
missingToCache := make(map[string]any, len(slugs))
missingSlugs := make([]string, 0, len(slugs))
for i, b := range raws {
if len(b) == 0 {
@@ -376,7 +371,7 @@ func (r *entityRepository) GetBySlugs(ctx context.Context, slugs []string) ([]*m
}
}
dbMap := make(map[string]*models.EntityEntity)
dbMap := make(map[string]*models.EntityEntity, len(missingSlugs))
if len(missingSlugs) > 0 {
dbRows, err := r.q.GetEntitiesBySlugs(ctx, missingSlugs)
if err == nil {
@@ -427,13 +422,13 @@ func (r *entityRepository) GetEntityIDsByGeometryIDs(ctx context.Context, geomet
keys := make([]string, len(geometryIDs))
for i, id := range geometryIDs {
keys[i] = fmt.Sprintf("entity_geometries:geometry:%s", id)
keys[i] = cache.Key("entity_geometries:geometry", id)
}
raws := r.c.MGet(ctx, keys...)
result := make(map[string][]string)
var missingGeometryIDs []string
var missingPgIDs []pgtype.UUID
result := make(map[string][]string, len(geometryIDs))
missingGeometryIDs := make([]string, 0, len(geometryIDs))
missingPgIDs := make([]pgtype.UUID, 0, len(geometryIDs))
for i, b := range raws {
if len(b) > 0 {
@@ -456,7 +451,7 @@ func (r *entityRepository) GetEntityIDsByGeometryIDs(ctx context.Context, geomet
return nil, err
}
dbMap := make(map[string][]string)
dbMap := make(map[string][]string, len(missingGeometryIDs))
for _, id := range missingGeometryIDs {
dbMap[id] = []string{}
}
@@ -466,10 +461,10 @@ func (r *entityRepository) GetEntityIDsByGeometryIDs(ctx context.Context, geomet
dbMap[gID] = append(dbMap[gID], eID)
}
missingToCache := make(map[string]any)
missingToCache := make(map[string]any, len(dbMap))
for gID, eIDs := range dbMap {
result[gID] = eIDs
missingToCache[fmt.Sprintf("entity_geometries:geometry:%s", gID)] = eIDs
missingToCache[cache.Key("entity_geometries:geometry", gID)] = eIDs
}
if len(missingToCache) > 0 {
_ = r.c.MSet(ctx, missingToCache, constants.NormalCacheDuration)
+37 -41
View File
@@ -2,9 +2,7 @@ package repositories
import (
"context"
"crypto/md5"
"encoding/json"
"fmt"
json "history-api/pkg/jsonx"
"strings"
"github.com/jackc/pgx/v5"
@@ -60,9 +58,7 @@ func (r *geometryRepository) WithTx(tx pgx.Tx) GeometryRepository {
}
func (r *geometryRepository) generateQueryKey(prefix string, params any) string {
b, _ := json.Marshal(params)
hash := fmt.Sprintf("%x", md5.Sum(b))
return fmt.Sprintf("%s:%s", prefix, hash)
return cache.QueryKey(prefix, params)
}
func (r *geometryRepository) getByIDsWithFallback(ctx context.Context, ids []string) ([]*models.GeometryEntity, error) {
@@ -71,14 +67,14 @@ func (r *geometryRepository) getByIDsWithFallback(ctx context.Context, ids []str
}
keys := make([]string, len(ids))
for i, id := range ids {
keys[i] = fmt.Sprintf("geometry:id:%s", id)
keys[i] = cache.Key("geometry:id", id)
}
raws := r.c.MGet(ctx, keys...)
var geometries []*models.GeometryEntity
missingToCache := make(map[string]any)
geometries := make([]*models.GeometryEntity, 0, len(ids))
missingToCache := make(map[string]any, len(ids))
var missingPgIds []pgtype.UUID
missingPgIds := make([]pgtype.UUID, 0, len(ids))
for i, b := range raws {
if len(b) == 0 {
pgId := pgtype.UUID{}
@@ -89,7 +85,7 @@ func (r *geometryRepository) getByIDsWithFallback(ctx context.Context, ids []str
}
}
dbMap := make(map[string]*models.GeometryEntity)
dbMap := make(map[string]*models.GeometryEntity, len(missingPgIds))
if len(missingPgIds) > 0 {
dbRows, err := r.q.GetGeometriesByIDs(ctx, missingPgIds)
if err == nil {
@@ -143,7 +139,7 @@ func (r *geometryRepository) GetByIDs(ctx context.Context, ids []string) ([]*mod
}
func (r *geometryRepository) GetByID(ctx context.Context, id pgtype.UUID) (*models.GeometryEntity, error) {
cacheId := fmt.Sprintf("geometry:id:%s", convert.UUIDToString(id))
cacheId := cache.Key("geometry:id", convert.UUIDToString(id))
var geometry models.GeometryEntity
err := r.c.Get(ctx, cacheId, &geometry)
if err == nil {
@@ -194,9 +190,9 @@ func (r *geometryRepository) Search(ctx context.Context, params sqlc.SearchGeome
if err != nil {
return nil, err
}
var geometries []*models.GeometryEntity
var ids []string
geometryToCache := make(map[string]any)
geometries := make([]*models.GeometryEntity, 0, len(rows))
ids := make([]string, 0, len(rows))
geometryToCache := make(map[string]any, len(rows))
for _, row := range rows {
geometry := &models.GeometryEntity{
@@ -219,7 +215,7 @@ func (r *geometryRepository) Search(ctx context.Context, params sqlc.SearchGeome
}
ids = append(ids, geometry.ID)
geometries = append(geometries, geometry)
geometryToCache[fmt.Sprintf("geometry:id:%s", geometry.ID)] = geometry
geometryToCache[cache.Key("geometry:id", geometry.ID)] = geometry
}
if len(geometryToCache) > 0 {
@@ -281,7 +277,7 @@ func (r *geometryRepository) Update(ctx context.Context, params sqlc.UpdateGeome
CreatedAt: convert.TimeToPtr(row.CreatedAt),
UpdatedAt: convert.TimeToPtr(row.UpdatedAt),
}
_ = r.c.Del(ctx, fmt.Sprintf("geometry:id:%s", geometry.ID))
_ = r.c.Del(ctx, cache.Key("geometry:id", geometry.ID))
return &geometry, nil
}
@@ -290,7 +286,7 @@ func (r *geometryRepository) Delete(ctx context.Context, id pgtype.UUID) error {
if err != nil {
return err
}
_ = r.c.Del(ctx, fmt.Sprintf("geometry:id:%s", convert.UUIDToString(id)))
_ = r.c.Del(ctx, cache.Key("geometry:id", convert.UUIDToString(id)))
return nil
}
@@ -311,7 +307,7 @@ func (r *geometryRepository) BulkDeleteEntityGeometriesByEntityId(ctx context.Co
}
func (r *geometryRepository) GetByProjectID(ctx context.Context, projectID pgtype.UUID) ([]*models.GeometryEntity, error) {
cacheKey := fmt.Sprintf("geometry:project:%s", convert.UUIDToString(projectID))
cacheKey := cache.Key("geometry:project", convert.UUIDToString(projectID))
var cachedIDs []string
err := r.c.Get(ctx, cacheKey, &cachedIDs)
if err == nil {
@@ -326,9 +322,9 @@ func (r *geometryRepository) GetByProjectID(ctx context.Context, projectID pgtyp
return nil, err
}
var geometries []*models.GeometryEntity
var ids []string
geometryToCache := make(map[string]any)
geometries := make([]*models.GeometryEntity, 0, len(rows))
ids := make([]string, 0, len(rows))
geometryToCache := make(map[string]any, len(rows))
for _, row := range rows {
geometry := &models.GeometryEntity{
@@ -351,7 +347,7 @@ func (r *geometryRepository) GetByProjectID(ctx context.Context, projectID pgtyp
}
ids = append(ids, geometry.ID)
geometries = append(geometries, geometry)
geometryToCache[fmt.Sprintf("geometry:id:%s", geometry.ID)] = geometry
geometryToCache[cache.Key("geometry:id", geometry.ID)] = geometry
}
if len(geometryToCache) > 0 {
@@ -363,7 +359,7 @@ func (r *geometryRepository) GetByProjectID(ctx context.Context, projectID pgtyp
}
func (r *geometryRepository) GetGeometriesByBoundWith(ctx context.Context, boundWith pgtype.UUID) ([]*models.GeometryEntity, error) {
cacheKey := fmt.Sprintf("geometry:bound_with:%s", convert.UUIDToString(boundWith))
cacheKey := cache.Key("geometry:bound_with", convert.UUIDToString(boundWith))
var cachedIDs []string
err := r.c.Get(ctx, cacheKey, &cachedIDs)
if err == nil {
@@ -378,9 +374,9 @@ func (r *geometryRepository) GetGeometriesByBoundWith(ctx context.Context, bound
return nil, err
}
var geometries []*models.GeometryEntity
var ids []string
geometryToCache := make(map[string]any)
geometries := make([]*models.GeometryEntity, 0, len(rows))
ids := make([]string, 0, len(rows))
geometryToCache := make(map[string]any, len(rows))
for _, row := range rows {
geometry := &models.GeometryEntity{
@@ -403,7 +399,7 @@ func (r *geometryRepository) GetGeometriesByBoundWith(ctx context.Context, bound
}
ids = append(ids, geometry.ID)
geometries = append(geometries, geometry)
geometryToCache[fmt.Sprintf("geometry:id:%s", geometry.ID)] = geometry
geometryToCache[cache.Key("geometry:id", geometry.ID)] = geometry
}
if len(geometryToCache) > 0 {
@@ -421,7 +417,7 @@ func (r *geometryRepository) DeleteByIDs(ctx context.Context, ids []pgtype.UUID)
if len(ids) > 0 {
keys := make([]string, len(ids))
for i, id := range ids {
keys[i] = fmt.Sprintf("geometry:id:%s", convert.UUIDToString(id))
keys[i] = cache.Key("geometry:id", convert.UUIDToString(id))
}
_ = r.c.Del(ctx, keys...)
}
@@ -445,15 +441,15 @@ func (r *geometryRepository) getSearchByIDsWithFallback(ctx context.Context, pai
}
keys := make([]string, len(pairs))
for i, pair := range pairs {
keys[i] = fmt.Sprintf("geometry:search:item:%s", pair)
keys[i] = cache.Key("geometry:search:item", pair)
}
raws := r.c.MGet(ctx, keys...)
var results []*models.EntityGeometriesSearchEntity
missingToCache := make(map[string]any)
results := make([]*models.EntityGeometriesSearchEntity, 0, len(pairs))
missingToCache := make(map[string]any, len(pairs))
var missingEntityIds []pgtype.UUID
var missingGeometryIds []pgtype.UUID
missingEntityIds := make([]pgtype.UUID, 0, len(pairs))
missingGeometryIds := make([]pgtype.UUID, 0, len(pairs))
for i, b := range raws {
if len(b) == 0 {
@@ -471,7 +467,7 @@ func (r *geometryRepository) getSearchByIDsWithFallback(ctx context.Context, pai
}
}
dbMap := make(map[string]*models.EntityGeometriesSearchEntity)
dbMap := make(map[string]*models.EntityGeometriesSearchEntity, len(missingEntityIds))
if len(missingEntityIds) > 0 {
dbRows, err := r.q.GetEntityGeometriesByPairs(ctx, sqlc.GetEntityGeometriesByPairsParams{
EntityIds: missingEntityIds,
@@ -490,7 +486,7 @@ func (r *geometryRepository) getSearchByIDsWithFallback(ctx context.Context, pai
TimeStart: convert.Int4ToPtr(row.TimeStart),
TimeEnd: convert.Int4ToPtr(row.TimeEnd),
}
key := fmt.Sprintf("%s:%s", item.EntityID, item.GeometryID)
key := cache.Key(item.EntityID, item.GeometryID)
dbMap[key] = item
}
}
@@ -533,9 +529,9 @@ func (r *geometryRepository) SearchByEntityName(ctx context.Context, params sqlc
if err != nil {
return nil, err
}
var geometries []*models.EntityGeometriesSearchEntity
var pairs []string
geometryToCache := make(map[string]any)
geometries := make([]*models.EntityGeometriesSearchEntity, 0, len(rows))
pairs := make([]string, 0, len(rows))
geometryToCache := make(map[string]any, len(rows))
for _, row := range rows {
item := &models.EntityGeometriesSearchEntity{
@@ -549,10 +545,10 @@ func (r *geometryRepository) SearchByEntityName(ctx context.Context, params sqlc
TimeStart: convert.Int4ToPtr(row.TimeStart),
TimeEnd: convert.Int4ToPtr(row.TimeEnd),
}
pair := fmt.Sprintf("%s:%s", item.EntityID, item.GeometryID)
pair := cache.Key(item.EntityID, item.GeometryID)
geometries = append(geometries, item)
pairs = append(pairs, pair)
geometryToCache[fmt.Sprintf("geometry:search:item:%s", pair)] = item
geometryToCache[cache.Key("geometry:search:item", pair)] = item
}
if len(geometryToCache) > 0 {
+20 -24
View File
@@ -2,14 +2,12 @@ package repositories
import (
"context"
"crypto/md5"
"encoding/json"
"fmt"
"history-api/internal/gen/sqlc"
"history-api/internal/models"
"history-api/pkg/cache"
"history-api/pkg/constants"
"history-api/pkg/convert"
json "history-api/pkg/jsonx"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
@@ -47,9 +45,7 @@ func (r *mediaRepository) WithTx(tx pgx.Tx) MediaRepository {
}
func (r *mediaRepository) generateQueryKey(prefix string, params any) string {
b, _ := json.Marshal(params)
hash := fmt.Sprintf("%x", md5.Sum(b))
return fmt.Sprintf("%s:%s", prefix, hash)
return cache.QueryKey(prefix, params)
}
func (r *mediaRepository) getByIDsWithFallback(ctx context.Context, ids []string) ([]*models.MediaEntity, error) {
@@ -58,14 +54,14 @@ func (r *mediaRepository) getByIDsWithFallback(ctx context.Context, ids []string
}
keys := make([]string, len(ids))
for i, id := range ids {
keys[i] = fmt.Sprintf("media:id:%s", id)
keys[i] = cache.Key("media:id", id)
}
raws := r.c.MGet(ctx, keys...)
var medias []*models.MediaEntity
missingMediasToCache := make(map[string]any)
medias := make([]*models.MediaEntity, 0, len(ids))
missingMediasToCache := make(map[string]any, len(ids))
var missingPgIds []pgtype.UUID
missingPgIds := make([]pgtype.UUID, 0, len(ids))
for i, b := range raws {
if len(b) == 0 {
pgId := pgtype.UUID{}
@@ -76,7 +72,7 @@ func (r *mediaRepository) getByIDsWithFallback(ctx context.Context, ids []string
}
}
dbMap := make(map[string]*models.MediaEntity)
dbMap := make(map[string]*models.MediaEntity, len(missingPgIds))
if len(missingPgIds) > 0 {
dbRows, err := r.q.GetMediaByIDs(ctx, missingPgIds)
if err == nil {
@@ -123,7 +119,7 @@ func (r *mediaRepository) GetByIDs(ctx context.Context, ids []string) ([]*models
}
func (r *mediaRepository) GetByID(ctx context.Context, id pgtype.UUID) (*models.MediaEntity, error) {
cacheId := fmt.Sprintf("media:id:%s", convert.UUIDToString(id))
cacheId := cache.Key("media:id", convert.UUIDToString(id))
var media models.MediaEntity
err := r.c.Get(ctx, cacheId, &media)
if err == nil {
@@ -165,7 +161,7 @@ func (r *mediaRepository) Create(ctx context.Context, params sqlc.CreateMediaPar
_ = r.c.DelByPattern(bgCtx, "media:count*")
}()
_ = r.c.Del(ctx, fmt.Sprintf("media:userId:%s", convert.UUIDToString(params.UserID)))
_ = r.c.Del(ctx, cache.Key("media:userId", convert.UUIDToString(params.UserID)))
media := models.MediaEntity{
ID: convert.UUIDToString(row.ID),
@@ -188,7 +184,7 @@ func (r *mediaRepository) Delete(ctx context.Context, id pgtype.UUID) error {
return err
}
cacheId := fmt.Sprintf("media:id:%s", convert.UUIDToString(id))
cacheId := cache.Key("media:id", convert.UUIDToString(id))
_ = r.c.Del(ctx, cacheId)
go func() {
_ = r.c.DelByPattern(context.Background(), "media:count*")
@@ -206,7 +202,7 @@ func (r *mediaRepository) BulkDelete(ctx context.Context, ids []pgtype.UUID) err
}
keys := make([]string, len(ids))
for i, id := range ids {
keys[i] = fmt.Sprintf("media:id:%s", convert.UUIDToString(id))
keys[i] = cache.Key("media:id", convert.UUIDToString(id))
}
_ = r.c.Del(ctx, keys...)
@@ -237,9 +233,9 @@ func (r *mediaRepository) Search(ctx context.Context, params sqlc.SearchMediasPa
if err != nil {
return nil, err
}
var medias []*models.MediaEntity
var ids []string
mediasToCache := make(map[string]any)
medias := make([]*models.MediaEntity, 0, len(rows))
ids := make([]string, 0, len(rows))
mediasToCache := make(map[string]any, len(rows))
for _, row := range rows {
media := &models.MediaEntity{
@@ -256,7 +252,7 @@ func (r *mediaRepository) Search(ctx context.Context, params sqlc.SearchMediasPa
ids = append(ids, media.ID)
medias = append(medias, media)
mediasToCache[fmt.Sprintf("media:id:%s", media.ID)] = media
mediasToCache[cache.Key("media:id", media.ID)] = media
}
if len(mediasToCache) > 0 {
@@ -284,7 +280,7 @@ func (r *mediaRepository) Count(ctx context.Context, params sqlc.CountMediasPara
}
func (r *mediaRepository) GetByUserID(ctx context.Context, userId pgtype.UUID) ([]*models.MediaEntity, error) {
queryKey := fmt.Sprintf("media:userId:%s", convert.UUIDToString(userId))
queryKey := cache.Key("media:userId", convert.UUIDToString(userId))
var cachedIDs []string
err := r.c.Get(ctx, queryKey, &cachedIDs)
if err == nil {
@@ -307,9 +303,9 @@ func (r *mediaRepository) GetByUserID(ctx context.Context, userId pgtype.UUID) (
if err != nil {
return nil, err
}
var medias []*models.MediaEntity
var ids []string
mediasToCache := make(map[string]any)
medias := make([]*models.MediaEntity, 0, len(rows))
ids := make([]string, 0, len(rows))
mediasToCache := make(map[string]any, len(rows))
for _, row := range rows {
media := &models.MediaEntity{
@@ -326,7 +322,7 @@ func (r *mediaRepository) GetByUserID(ctx context.Context, userId pgtype.UUID) (
ids = append(ids, media.ID)
medias = append(medias, media)
mediasToCache[fmt.Sprintf("media:id:%s", media.ID)] = media
mediasToCache[cache.Key("media:id", media.ID)] = media
}
if len(mediasToCache) > 0 {
+28 -32
View File
@@ -2,9 +2,7 @@ package repositories
import (
"context"
"crypto/md5"
"encoding/json"
"fmt"
json "history-api/pkg/jsonx"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
@@ -53,9 +51,7 @@ func (r *projectRepository) WithTx(tx pgx.Tx) ProjectRepository {
}
}
func (r *projectRepository) generateQueryKey(prefix string, params any) string {
b, _ := json.Marshal(params)
hash := fmt.Sprintf("%x", md5.Sum(b))
return fmt.Sprintf("%s:%s", prefix, hash)
return cache.QueryKey(prefix, params)
}
func (r *projectRepository) getByIDsWithFallback(ctx context.Context, ids []string) ([]*models.ProjectEntity, error) {
@@ -64,14 +60,14 @@ func (r *projectRepository) getByIDsWithFallback(ctx context.Context, ids []stri
}
keys := make([]string, len(ids))
for i, id := range ids {
keys[i] = fmt.Sprintf("project:id:%s", id)
keys[i] = cache.Key("project:id", id)
}
raws := r.c.MGet(ctx, keys...)
var projects []*models.ProjectEntity
missingToCache := make(map[string]any)
projects := make([]*models.ProjectEntity, 0, len(ids))
missingToCache := make(map[string]any, len(ids))
var missingPgIds []pgtype.UUID
missingPgIds := make([]pgtype.UUID, 0, len(ids))
for i, b := range raws {
if len(b) == 0 {
pgId := pgtype.UUID{}
@@ -82,7 +78,7 @@ func (r *projectRepository) getByIDsWithFallback(ctx context.Context, ids []stri
}
}
dbMap := make(map[string]*models.ProjectEntity)
dbMap := make(map[string]*models.ProjectEntity, len(missingPgIds))
if len(missingPgIds) > 0 {
dbRows, err := r.q.GetProjectsByIDs(ctx, missingPgIds)
if err == nil {
@@ -134,7 +130,7 @@ func (r *projectRepository) GetByIDs(ctx context.Context, ids []string) ([]*mode
}
func (r *projectRepository) GetByID(ctx context.Context, id pgtype.UUID) (*models.ProjectEntity, error) {
cacheId := fmt.Sprintf("project:id:%s", convert.UUIDToString(id))
cacheId := cache.Key("project:id", convert.UUIDToString(id))
var project models.ProjectEntity
err := r.c.Get(ctx, cacheId, &project)
if err == nil {
@@ -185,9 +181,9 @@ func (r *projectRepository) GetByUserID(ctx context.Context, params sqlc.GetProj
return nil, err
}
var projects []*models.ProjectEntity
var ids []string
projectToCache := make(map[string]any)
projects := make([]*models.ProjectEntity, 0, len(rows))
ids := make([]string, 0, len(rows))
projectToCache := make(map[string]any, len(rows))
for _, row := range rows {
project := &models.ProjectEntity{
@@ -209,7 +205,7 @@ func (r *projectRepository) GetByUserID(ctx context.Context, params sqlc.GetProj
ids = append(ids, project.ID)
projects = append(projects, project)
projectToCache[fmt.Sprintf("project:id:%s", project.ID)] = project
projectToCache[cache.Key("project:id", project.ID)] = project
}
if len(projectToCache) > 0 {
@@ -235,9 +231,9 @@ func (r *projectRepository) Search(ctx context.Context, params sqlc.SearchProjec
if err != nil {
return nil, err
}
var projects []*models.ProjectEntity
var ids []string
projectToCache := make(map[string]any)
projects := make([]*models.ProjectEntity, 0, len(rows))
ids := make([]string, 0, len(rows))
projectToCache := make(map[string]any, len(rows))
for _, row := range rows {
project := &models.ProjectEntity{
@@ -259,7 +255,7 @@ func (r *projectRepository) Search(ctx context.Context, params sqlc.SearchProjec
ids = append(ids, project.ID)
projects = append(projects, project)
projectToCache[fmt.Sprintf("project:id:%s", project.ID)] = project
projectToCache[cache.Key("project:id", project.ID)] = project
}
if len(projectToCache) > 0 {
@@ -340,7 +336,7 @@ func (r *projectRepository) Update(ctx context.Context, params sqlc.UpdateProjec
_ = project.ParseSubmissions(row.Submissions)
_ = project.ParseMembers(row.Members)
_ = r.c.Del(ctx, fmt.Sprintf("project:id:%s", project.ID))
_ = r.c.Del(ctx, cache.Key("project:id", project.ID))
return &project, nil
}
@@ -349,7 +345,7 @@ func (r *projectRepository) Delete(ctx context.Context, id pgtype.UUID) error {
if err != nil {
return err
}
_ = r.c.Del(ctx, fmt.Sprintf("project:id:%s", convert.UUIDToString(id)))
_ = r.c.Del(ctx, cache.Key("project:id", convert.UUIDToString(id)))
go func() {
bgCtx := context.Background()
_ = r.c.DelByPattern(bgCtx, "project:search*")
@@ -367,8 +363,8 @@ func (r *projectRepository) AddMember(ctx context.Context, params sqlc.AddProjec
go func() {
_ = r.c.DelByPattern(context.Background(), "project:user*")
}()
_ = r.c.Del(ctx, fmt.Sprintf("project:id:%s", convert.UUIDToString(params.ProjectID)))
_ = r.c.Del(ctx, fmt.Sprintf("project:perm:%s:%s", convert.UUIDToString(params.ProjectID), convert.UUIDToString(params.UserID)))
_ = r.c.Del(ctx, cache.Key("project:id", convert.UUIDToString(params.ProjectID)))
_ = r.c.Del(ctx, cache.Key2("project:perm", convert.UUIDToString(params.ProjectID), convert.UUIDToString(params.UserID)))
return nil
}
@@ -380,8 +376,8 @@ func (r *projectRepository) UpdateMemberRole(ctx context.Context, params sqlc.Up
go func() {
_ = r.c.DelByPattern(context.Background(), "project:user*")
}()
_ = r.c.Del(ctx, fmt.Sprintf("project:id:%s", convert.UUIDToString(params.ProjectID)))
_ = r.c.Del(ctx, fmt.Sprintf("project:perm:%s:%s", convert.UUIDToString(params.ProjectID), convert.UUIDToString(params.UserID)))
_ = r.c.Del(ctx, cache.Key("project:id", convert.UUIDToString(params.ProjectID)))
_ = r.c.Del(ctx, cache.Key2("project:perm", convert.UUIDToString(params.ProjectID), convert.UUIDToString(params.UserID)))
return nil
}
@@ -393,13 +389,13 @@ func (r *projectRepository) RemoveMember(ctx context.Context, params sqlc.Remove
go func() {
_ = r.c.DelByPattern(context.Background(), "project:user*")
}()
_ = r.c.Del(ctx, fmt.Sprintf("project:id:%s", convert.UUIDToString(params.ProjectID)))
_ = r.c.Del(ctx, fmt.Sprintf("project:perm:%s:%s", convert.UUIDToString(params.ProjectID), convert.UUIDToString(params.UserID)))
_ = r.c.Del(ctx, cache.Key("project:id", convert.UUIDToString(params.ProjectID)))
_ = r.c.Del(ctx, cache.Key2("project:perm", convert.UUIDToString(params.ProjectID), convert.UUIDToString(params.UserID)))
return nil
}
func (r *projectRepository) CheckPermission(ctx context.Context, params sqlc.CheckProjectPermissionParams) (int16, error) {
cacheKey := fmt.Sprintf("project:perm:%s:%s", convert.UUIDToString(params.ProjectID), convert.UUIDToString(params.UserID))
cacheKey := cache.Key2("project:perm", convert.UUIDToString(params.ProjectID), convert.UUIDToString(params.UserID))
var role int16
if err := r.c.Get(ctx, cacheKey, &role); err == nil {
return role, nil
@@ -420,9 +416,9 @@ func (r *projectRepository) ChangeOwner(ctx context.Context, params sqlc.ChangeP
return err
}
projectID := convert.UUIDToString(params.ID)
_ = r.c.Del(ctx, fmt.Sprintf("project:id:%s", projectID))
_ = r.c.Del(ctx, cache.Key("project:id", projectID))
go func() {
_ = r.c.DelByPattern(context.Background(), fmt.Sprintf("project:perm:%s:*", projectID))
_ = r.c.DelByPattern(context.Background(), "project:perm:"+projectID+":*")
}()
return nil
}
@@ -432,6 +428,6 @@ func (r *projectRepository) UpdateLatestCommit(ctx context.Context, params sqlc.
if err != nil {
return err
}
_ = r.c.Del(ctx, fmt.Sprintf("project:id:%s", convert.UUIDToString(params.ID)))
_ = r.c.Del(ctx, cache.Key("project:id", convert.UUIDToString(params.ID)))
return nil
}
+36 -8
View File
@@ -6,17 +6,23 @@ import (
"fmt"
"history-api/pkg/cache"
"history-api/pkg/constants"
"strconv"
"sync"
"time"
)
const rasterTileCacheDuration = 5 * time.Minute
type RasterTileRepository interface {
GetMetadata(ctx context.Context) (map[string]string, error)
GetTile(ctx context.Context, z, x, y int) ([]byte, string, error)
}
type rasterTileRepository struct {
db *sql.DB
c cache.Cache
db *sql.DB
c cache.Cache
metadataMu sync.RWMutex
metadata map[string]string
}
func NewRasterTileRepository(db *sql.DB, c cache.Cache) RasterTileRepository {
@@ -27,11 +33,27 @@ func NewRasterTileRepository(db *sql.DB, c cache.Cache) RasterTileRepository {
}
func (r *rasterTileRepository) GetMetadata(ctx context.Context) (map[string]string, error) {
r.metadataMu.RLock()
if r.metadata != nil {
metadata := r.metadata
r.metadataMu.RUnlock()
return metadata, nil
}
r.metadataMu.RUnlock()
r.metadataMu.Lock()
defer r.metadataMu.Unlock()
if r.metadata != nil {
return r.metadata, nil
}
cacheId := "rasterTile:metadata"
var cached map[string]string
err := r.c.Get(ctx, cacheId, &cached)
if err == nil {
r.metadata = cached
return cached, nil
}
@@ -41,7 +63,7 @@ func (r *rasterTileRepository) GetMetadata(ctx context.Context) (map[string]stri
}
defer rows.Close()
metadata := make(map[string]string)
metadata := make(map[string]string, 8)
for rows.Next() {
var name, value string
@@ -50,8 +72,12 @@ func (r *rasterTileRepository) GetMetadata(ctx context.Context) (map[string]stri
}
metadata[name] = value
}
if err := rows.Err(); err != nil {
return nil, err
}
_ = r.c.Set(ctx, cacheId, metadata, constants.NormalCacheDuration)
r.metadata = metadata
return metadata, nil
}
@@ -61,12 +87,14 @@ func (r *rasterTileRepository) GetTile(ctx context.Context, z, x, y int) ([]byte
return nil, "", fmt.Errorf("invalid tile coordinates")
}
cacheId := fmt.Sprintf("rasterTile:%d:%d:%d", z, x, y)
cacheId := "rasterTile:raw:" + strconv.Itoa(z) + ":" + strconv.Itoa(x) + ":" + strconv.Itoa(y)
var cached []byte
err := r.c.Get(ctx, cacheId, &cached)
cached, err := r.c.GetRawClient().Get(ctx, cacheId).Bytes()
if err == nil {
meta, _ := r.GetMetadata(ctx)
meta, err := r.GetMetadata(ctx)
if err != nil {
return nil, "", err
}
return cached, meta["format"], nil
}
@@ -92,7 +120,7 @@ func (r *rasterTileRepository) GetTile(ctx context.Context, z, x, y int) ([]byte
return nil, "", err
}
_ = r.c.Set(ctx, cacheId, tileData, 5*time.Minute)
_ = r.c.GetRawClient().Set(ctx, cacheId, tileData, rasterTileCacheDuration).Err()
return tileData, meta["format"], nil
}
+16 -20
View File
@@ -2,9 +2,7 @@ package repositories
import (
"context"
"crypto/md5"
"encoding/json"
"fmt"
json "history-api/pkg/jsonx"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
@@ -52,9 +50,7 @@ func (r *roleRepository) WithTx(tx pgx.Tx) RoleRepository {
}
func (r *roleRepository) generateQueryKey(prefix string, params any) string {
b, _ := json.Marshal(params)
hash := fmt.Sprintf("%x", md5.Sum(b))
return fmt.Sprintf("%s:%s", prefix, hash)
return cache.QueryKey(prefix, params)
}
func (r *roleRepository) getByIDsWithFallback(ctx context.Context, ids []string) ([]*models.RoleEntity, error) {
@@ -63,14 +59,14 @@ func (r *roleRepository) getByIDsWithFallback(ctx context.Context, ids []string)
}
keys := make([]string, len(ids))
for i, id := range ids {
keys[i] = fmt.Sprintf("role:id:%s", id)
keys[i] = cache.Key("role:id", id)
}
raws := r.c.MGet(ctx, keys...)
var roles []*models.RoleEntity
missingRolesToCache := make(map[string]any)
roles := make([]*models.RoleEntity, 0, len(ids))
missingRolesToCache := make(map[string]any, len(ids))
var missingPgIds []pgtype.UUID
missingPgIds := make([]pgtype.UUID, 0, len(ids))
for i, b := range raws {
if len(b) == 0 {
pgId := pgtype.UUID{}
@@ -81,7 +77,7 @@ func (r *roleRepository) getByIDsWithFallback(ctx context.Context, ids []string)
}
}
dbMap := make(map[string]*models.RoleEntity)
dbMap := make(map[string]*models.RoleEntity, len(missingPgIds))
if len(missingPgIds) > 0 {
dbRows, err := r.q.GetRolesByIDs(ctx, missingPgIds)
if err == nil {
@@ -124,7 +120,7 @@ func (r *roleRepository) GetByIDs(ctx context.Context, ids []string) ([]*models.
}
func (r *roleRepository) GetByID(ctx context.Context, id pgtype.UUID) (*models.RoleEntity, error) {
cacheId := fmt.Sprintf("role:id:%s", convert.UUIDToString(id))
cacheId := cache.Key("role:id", convert.UUIDToString(id))
var role models.RoleEntity
err := r.c.Get(ctx, cacheId, &role)
if err == nil {
@@ -150,7 +146,7 @@ func (r *roleRepository) GetByID(ctx context.Context, id pgtype.UUID) (*models.R
}
func (r *roleRepository) GetByName(ctx context.Context, name string) (*models.RoleEntity, error) {
cacheId := fmt.Sprintf("role:name:%s", name)
cacheId := cache.Key("role:name", name)
var role models.RoleEntity
err := r.c.Get(ctx, cacheId, &role)
if err == nil {
@@ -208,7 +204,7 @@ func (r *roleRepository) Update(ctx context.Context, params sqlc.UpdateRoleParam
UpdatedAt: convert.TimeToPtr(row.UpdatedAt),
}
_ = r.c.Del(ctx, fmt.Sprintf("role:id:%s", convert.UUIDToString(row.ID)), fmt.Sprintf("role:name:%s", row.Name))
_ = r.c.Del(ctx, cache.Key("role:id", convert.UUIDToString(row.ID)), cache.Key("role:name", row.Name))
return &role, nil
}
@@ -236,9 +232,9 @@ func (r *roleRepository) All(ctx context.Context) ([]*models.RoleEntity, error)
if err != nil {
return nil, err
}
var roles []*models.RoleEntity
var ids []string
roleToCache := make(map[string]any)
roles := make([]*models.RoleEntity, 0, len(rows))
ids := make([]string, 0, len(rows))
roleToCache := make(map[string]any, len(rows))
for _, row := range rows {
role := &models.RoleEntity{
@@ -251,7 +247,7 @@ func (r *roleRepository) All(ctx context.Context) ([]*models.RoleEntity, error)
ids = append(ids, role.ID)
roles = append(roles, role)
roleToCache[fmt.Sprintf("role:id:%s", role.ID)] = role
roleToCache[cache.Key("role:id", role.ID)] = role
}
if len(roleToCache) > 0 {
@@ -273,7 +269,7 @@ func (r *roleRepository) Delete(ctx context.Context, id pgtype.UUID) error {
if err != nil {
return err
}
_ = r.c.Del(ctx, fmt.Sprintf("role:id:%s", role.ID), fmt.Sprintf("role:name:%s", role.Name))
_ = r.c.Del(ctx, cache.Key("role:id", role.ID), cache.Key("role:name", role.Name))
return nil
}
@@ -282,7 +278,7 @@ func (r *roleRepository) Restore(ctx context.Context, id pgtype.UUID) error {
if err != nil {
return err
}
_ = r.c.Del(ctx, fmt.Sprintf("role:id:%s", convert.UUIDToString(id)))
_ = r.c.Del(ctx, cache.Key("role:id", convert.UUIDToString(id)))
return nil
}
+16 -22
View File
@@ -2,14 +2,12 @@ package repositories
import (
"context"
"crypto/md5"
"encoding/json"
"fmt"
"history-api/internal/gen/sqlc"
"history-api/internal/models"
"history-api/pkg/cache"
"history-api/pkg/constants"
"history-api/pkg/convert"
json "history-api/pkg/jsonx"
"time"
"github.com/jackc/pgx/v5"
@@ -47,9 +45,7 @@ func (r *statisticRepository) WithTx(tx pgx.Tx) StatisticRepository {
}
func (r *statisticRepository) generateQueryKey(prefix string, params any) string {
b, _ := json.Marshal(params)
hash := fmt.Sprintf("%x", md5.Sum(b))
return fmt.Sprintf("%s:%s", prefix, hash)
return cache.QueryKey(prefix, params)
}
func mapToEntity(row sqlc.SystemStatistic) *models.StatisticEntity {
@@ -84,14 +80,14 @@ func (r *statisticRepository) getByIDsWithFallback(ctx context.Context, ids []st
}
keys := make([]string, len(ids))
for i, id := range ids {
keys[i] = fmt.Sprintf("statistic:id:%s", id)
keys[i] = cache.Key("statistic:id", id)
}
raws := r.c.MGet(ctx, keys...)
var stats []*models.StatisticEntity
missingStatsToCache := make(map[string]any)
stats := make([]*models.StatisticEntity, 0, len(ids))
missingStatsToCache := make(map[string]any, len(ids))
var missingPgIds []pgtype.UUID
missingPgIds := make([]pgtype.UUID, 0, len(ids))
for i, b := range raws {
if len(b) == 0 {
pgId := pgtype.UUID{}
@@ -102,7 +98,7 @@ func (r *statisticRepository) getByIDsWithFallback(ctx context.Context, ids []st
}
}
dbMap := make(map[string]*models.StatisticEntity)
dbMap := make(map[string]*models.StatisticEntity, len(missingPgIds))
if len(missingPgIds) > 0 {
dbRows, err := r.q.GetSystemStatisticsByIDs(ctx, missingPgIds)
if err == nil {
@@ -151,15 +147,15 @@ func (r *statisticRepository) Search(ctx context.Context, params sqlc.SearchSyst
return nil, err
}
var ids []string
statsToCache := make(map[string]any)
var stats []*models.StatisticEntity
ids := make([]string, 0, len(rows))
statsToCache := make(map[string]any, len(rows))
stats := make([]*models.StatisticEntity, 0, len(rows))
for _, row := range rows {
entity := mapToEntity(row)
ids = append(ids, entity.ID)
stats = append(stats, entity)
statsToCache[fmt.Sprintf("statistic:id:%s", entity.ID)] = entity
statsToCache[cache.Key("statistic:id", entity.ID)] = entity
}
if len(statsToCache) > 0 {
@@ -171,7 +167,7 @@ func (r *statisticRepository) Search(ctx context.Context, params sqlc.SearchSyst
}
func (r *statisticRepository) GetByID(ctx context.Context, id pgtype.UUID) (*models.StatisticEntity, error) {
cacheId := fmt.Sprintf("statistic:id:%s", convert.UUIDToString(id))
cacheId := cache.Key("statistic:id", convert.UUIDToString(id))
var stat models.StatisticEntity
err := r.c.Get(ctx, cacheId, &stat)
if err == nil {
@@ -194,7 +190,7 @@ func (r *statisticRepository) GetByID(ctx context.Context, id pgtype.UUID) (*mod
func (r *statisticRepository) GetByDate(ctx context.Context, date time.Time) (*models.StatisticEntity, error) {
dateStr := date.Format("2006-01-02")
cacheId := fmt.Sprintf("statistic:date:%s", dateStr)
cacheId := cache.Key("statistic:date", dateStr)
var stat models.StatisticEntity
err := r.c.Get(ctx, cacheId, &stat)
@@ -213,7 +209,7 @@ func (r *statisticRepository) GetByDate(ctx context.Context, date time.Time) (*m
entity := mapToEntity(row)
_ = r.c.Set(ctx, cacheId, entity, constants.NormalCacheDuration)
_ = r.c.Set(ctx, fmt.Sprintf("statistic:id:%s", entity.ID), entity, constants.NormalCacheDuration)
_ = r.c.Set(ctx, cache.Key("statistic:id", entity.ID), entity, constants.NormalCacheDuration)
return entity, nil
}
@@ -231,12 +227,10 @@ func (r *statisticRepository) Upsert(ctx context.Context, date time.Time) (*mode
_ = r.c.DelByPattern(bgCtx, "statistic:search*")
_ = r.c.Del(
bgCtx,
fmt.Sprintf("statistic:id:%s", entity.ID),
fmt.Sprintf("statistic:date:%s", date.Format("2006-01-02")),
cache.Key("statistic:id", entity.ID),
cache.Key("statistic:date", date.Format("2006-01-02")),
)
}()
return entity, nil
}
+15 -19
View File
@@ -2,14 +2,12 @@ package repositories
import (
"context"
"crypto/md5"
"encoding/json"
"fmt"
"history-api/internal/gen/sqlc"
"history-api/internal/models"
"history-api/pkg/cache"
"history-api/pkg/constants"
"history-api/pkg/convert"
json "history-api/pkg/jsonx"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
@@ -48,7 +46,7 @@ func (r *submissionRepository) WithTx(tx pgx.Tx) SubmissionRepository {
}
func (r *submissionRepository) GetByID(ctx context.Context, id pgtype.UUID) (*models.SubmissionEntity, error) {
cacheId := fmt.Sprintf("submission:id:%s", convert.UUIDToString(id))
cacheId := cache.Key("submission:id", convert.UUIDToString(id))
var submission models.SubmissionEntity
err := r.c.Get(ctx, cacheId, &submission)
if err == nil {
@@ -82,9 +80,7 @@ func (r *submissionRepository) GetByID(ctx context.Context, id pgtype.UUID) (*mo
}
func (r *submissionRepository) generateQueryKey(prefix string, params any) string {
b, _ := json.Marshal(params)
hash := fmt.Sprintf("%x", md5.Sum(b))
return fmt.Sprintf("%s:%s", prefix, hash)
return cache.QueryKey(prefix, params)
}
func (r *submissionRepository) getByIDsWithFallback(ctx context.Context, ids []string) ([]*models.SubmissionEntity, error) {
@@ -93,14 +89,14 @@ func (r *submissionRepository) getByIDsWithFallback(ctx context.Context, ids []s
}
keys := make([]string, len(ids))
for i, id := range ids {
keys[i] = fmt.Sprintf("submission:id:%s", id)
keys[i] = cache.Key("submission:id", id)
}
raws := r.c.MGet(ctx, keys...)
var submission []*models.SubmissionEntity
missingSubmisstionToCache := make(map[string]any)
submission := make([]*models.SubmissionEntity, 0, len(ids))
missingSubmisstionToCache := make(map[string]any, len(ids))
var missingPgIds []pgtype.UUID
missingPgIds := make([]pgtype.UUID, 0, len(ids))
for i, b := range raws {
if len(b) == 0 {
pgId := pgtype.UUID{}
@@ -111,7 +107,7 @@ func (r *submissionRepository) getByIDsWithFallback(ctx context.Context, ids []s
}
}
dbMap := make(map[string]*models.SubmissionEntity)
dbMap := make(map[string]*models.SubmissionEntity, len(missingPgIds))
if len(missingPgIds) > 0 {
dbRows, err := r.q.GetSubmissionsByIDs(ctx, missingPgIds)
if err == nil {
@@ -164,7 +160,7 @@ func (r *submissionRepository) GetByIDs(ctx context.Context, ids []string) ([]*m
}
func (r *submissionRepository) Search(ctx context.Context, params sqlc.SearchSubmissionsParams) ([]*models.SubmissionEntity, error) {
queryKey := r.generateQueryKey("verification:search", params)
queryKey := r.generateQueryKey("submission:search", params)
var cachedIDs []string
err := r.c.Get(ctx, queryKey, &cachedIDs)
if err == nil {
@@ -187,9 +183,9 @@ func (r *submissionRepository) Search(ctx context.Context, params sqlc.SearchSub
if err != nil {
return nil, err
}
var items []*models.SubmissionEntity
var ids []string
itemToCache := make(map[string]any)
items := make([]*models.SubmissionEntity, 0, len(rows))
ids := make([]string, 0, len(rows))
itemToCache := make(map[string]any, len(rows))
for _, row := range rows {
entity := &models.SubmissionEntity{
@@ -213,7 +209,7 @@ func (r *submissionRepository) Search(ctx context.Context, params sqlc.SearchSub
ids = append(ids, entity.ID)
items = append(items, entity)
itemToCache[fmt.Sprintf("submission:id:%s", entity.ID)] = entity
itemToCache[cache.Key("submission:id", entity.ID)] = entity
}
if len(itemToCache) > 0 {
@@ -308,7 +304,7 @@ func (r *submissionRepository) Update(ctx context.Context, params sqlc.UpdateSub
return nil, err
}
_ = r.c.Del(ctx, fmt.Sprintf("submission:id:%s", submission.ID))
_ = r.c.Del(ctx, cache.Key("submission:id", submission.ID))
return &submission, nil
}
@@ -319,7 +315,7 @@ func (r *submissionRepository) Delete(ctx context.Context, id pgtype.UUID) error
return err
}
_ = r.c.Del(ctx, fmt.Sprintf("submission:id:%s", convert.UUIDToString(id)))
_ = r.c.Del(ctx, cache.Key("submission:id", convert.UUIDToString(id)))
go func() {
bgCtx := context.Background()
_ = r.c.DelByPattern(bgCtx, "submission:search*")
+38 -9
View File
@@ -6,17 +6,23 @@ import (
"fmt"
"history-api/pkg/cache"
"history-api/pkg/constants"
"strconv"
"sync"
"time"
)
const tileCacheDuration = 5 * time.Minute
type TileRepository interface {
GetMetadata(ctx context.Context) (map[string]string, error)
GetTile(ctx context.Context, z, x, y int) ([]byte, string, bool, error)
}
type tileRepository struct {
db *sql.DB
c cache.Cache
db *sql.DB
c cache.Cache
metadataMu sync.RWMutex
metadata map[string]string
}
func NewTileRepository(db *sql.DB, c cache.Cache) TileRepository {
@@ -27,11 +33,27 @@ func NewTileRepository(db *sql.DB, c cache.Cache) TileRepository {
}
func (r *tileRepository) GetMetadata(ctx context.Context) (map[string]string, error) {
r.metadataMu.RLock()
if r.metadata != nil {
metadata := r.metadata
r.metadataMu.RUnlock()
return metadata, nil
}
r.metadataMu.RUnlock()
r.metadataMu.Lock()
defer r.metadataMu.Unlock()
if r.metadata != nil {
return r.metadata, nil
}
cacheId := "tile:metadata"
var cached map[string]string
err := r.c.Get(ctx, cacheId, &cached)
if err == nil {
r.metadata = cached
return cached, nil
}
@@ -41,7 +63,7 @@ func (r *tileRepository) GetMetadata(ctx context.Context) (map[string]string, er
}
defer rows.Close()
metadata := make(map[string]string)
metadata := make(map[string]string, 8)
for rows.Next() {
var name, value string
@@ -50,8 +72,12 @@ func (r *tileRepository) GetMetadata(ctx context.Context) (map[string]string, er
}
metadata[name] = value
}
if err := rows.Err(); err != nil {
return nil, err
}
_ = r.c.Set(ctx, cacheId, metadata, constants.NormalCacheDuration)
r.metadata = metadata
return metadata, nil
}
@@ -61,13 +87,16 @@ func (r *tileRepository) GetTile(ctx context.Context, z, x, y int) ([]byte, stri
return nil, "", false, fmt.Errorf("invalid tile coordinates")
}
cacheId := fmt.Sprintf("tile:%d:%d:%d", z, x, y)
cacheId := "tile:raw:" + strconv.Itoa(z) + ":" + strconv.Itoa(x) + ":" + strconv.Itoa(y)
var cached []byte
err := r.c.Get(ctx, cacheId, &cached)
cached, err := r.c.GetRawClient().Get(ctx, cacheId).Bytes()
if err == nil {
meta, _ := r.GetMetadata(ctx)
return cached, meta["format"], meta["format"] == "pbf", nil
meta, err := r.GetMetadata(ctx)
if err != nil {
return nil, "", false, err
}
format := meta["format"]
return cached, format, format == "pbf", nil
}
// XYZ -> TMS
@@ -92,7 +121,7 @@ func (r *tileRepository) GetTile(ctx context.Context, z, x, y int) ([]byte, stri
return nil, "", false, err
}
_ = r.c.Set(ctx, cacheId, tileData, 5*time.Minute)
_ = r.c.GetRawClient().Set(ctx, cacheId, tileData, tileCacheDuration).Err()
return tileData, meta["format"], meta["format"] == "pbf", nil
}
+17 -13
View File
@@ -2,10 +2,10 @@ package repositories
import (
"context"
"fmt"
"history-api/internal/models"
"history-api/pkg/cache"
"history-api/pkg/constants"
"strconv"
)
type TokenRepository interface {
@@ -33,23 +33,27 @@ func NewTokenRepository(c cache.Cache) TokenRepository {
}
}
func tokenTypeValue(t constants.TokenType) string {
return strconv.Itoa(int(t.Value()))
}
func (t *tokenRepository) CreateVerified(ctx context.Context, email string, tokenType constants.TokenType, id string) error {
cacheKey := fmt.Sprintf("token:verified:%d:%s:%s", tokenType.Value(), email, id)
cacheKey := cache.Key2("token:verified:"+tokenTypeValue(tokenType), email, id)
return t.c.Set(ctx, cacheKey, true, constants.TokenVerifiedDuration)
}
func (t *tokenRepository) DeleteVerified(ctx context.Context, email string, tokenType constants.TokenType, id string) error {
cacheKey := fmt.Sprintf("token:verified:%d:%s:%s", tokenType.Value(), email, id)
cacheKey := cache.Key2("token:verified:"+tokenTypeValue(tokenType), email, id)
return t.c.Del(ctx, cacheKey)
}
func (t *tokenRepository) CheckVerified(ctx context.Context, email string, tokenType constants.TokenType, id string) (bool, error) {
cacheKey := fmt.Sprintf("token:verified:%d:%s:%s", tokenType.Value(), email, id)
cacheKey := cache.Key2("token:verified:"+tokenTypeValue(tokenType), email, id)
exists, err := t.c.Exists(ctx, cacheKey)
return exists, err
}
func (t *tokenRepository) CreateUploadToken(ctx context.Context, userId string, token *models.TokenUploadEntity) error {
cacheKey := fmt.Sprintf("token:%d:%s:%s", constants.TokenTypeUpload.Value(), userId, token.ID)
cacheKey := cache.Key2("token:"+tokenTypeValue(constants.TokenTypeUpload), userId, token.ID)
err := t.c.Set(ctx, cacheKey, token, constants.TokenUploadDuration)
if err != nil {
return err
@@ -58,7 +62,7 @@ func (t *tokenRepository) CreateUploadToken(ctx context.Context, userId string,
}
func (t *tokenRepository) GetUploadToken(ctx context.Context, userId string, id string) (*models.TokenUploadEntity, error) {
cacheKey := fmt.Sprintf("token:%d:%s:%s", constants.TokenTypeUpload.Value(), userId, id)
cacheKey := cache.Key2("token:"+tokenTypeValue(constants.TokenTypeUpload), userId, id)
var token models.TokenUploadEntity
err := t.c.Get(ctx, cacheKey, &token)
if err != nil {
@@ -68,35 +72,35 @@ func (t *tokenRepository) GetUploadToken(ctx context.Context, userId string, id
}
func (t *tokenRepository) DeleteUploadToken(ctx context.Context, userId string, id string) error {
cacheKey := fmt.Sprintf("token:%d:%s:%s", constants.TokenTypeUpload.Value(), userId, id)
cacheKey := cache.Key2("token:"+tokenTypeValue(constants.TokenTypeUpload), userId, id)
return t.c.Del(ctx, cacheKey)
}
func (t *tokenRepository) CheckCooldown(ctx context.Context, email string, tokenType constants.TokenType) (bool, error) {
cacheKey := fmt.Sprintf("token:cooldown:%d:%s", tokenType.Value(), email)
cacheKey := cache.Key("token:cooldown:"+tokenTypeValue(tokenType), email)
exists, err := t.c.Exists(ctx, cacheKey)
return exists, err
}
func (t *tokenRepository) Create(ctx context.Context, token *models.TokenEntity) error {
cacheKey := fmt.Sprintf("token:%d:%s", token.TokenType.Value(), token.Email)
cacheKey := cache.Key("token:"+tokenTypeValue(token.TokenType), token.Email)
err := t.c.Set(ctx, cacheKey, token, constants.TokenExpirationDuration)
if err != nil {
return err
}
cooldownKey := fmt.Sprintf("token:cooldown:%d:%s", token.TokenType.Value(), token.Email)
cooldownKey := cache.Key("token:cooldown:"+tokenTypeValue(token.TokenType), token.Email)
return t.c.Set(ctx, cooldownKey, true, constants.TokenCooldownDuration)
}
func (t *tokenRepository) Delete(ctx context.Context, email string, tokenType constants.TokenType) error {
cacheKey := fmt.Sprintf("token:%d:%s", tokenType.Value(), email)
cooldownKey := fmt.Sprintf("token:cooldown:%d:%s", tokenType.Value(), email)
cacheKey := cache.Key("token:"+tokenTypeValue(tokenType), email)
cooldownKey := cache.Key("token:cooldown:"+tokenTypeValue(tokenType), email)
_ = t.c.Del(ctx, cooldownKey)
return t.c.Del(ctx, cacheKey)
}
func (t *tokenRepository) Get(ctx context.Context, email string, tokenType constants.TokenType) (*models.TokenEntity, error) {
cacheKey := fmt.Sprintf("token:%d:%s", tokenType.Value(), email)
cacheKey := cache.Key("token:"+tokenTypeValue(tokenType), email)
var token models.TokenEntity
err := t.c.Get(ctx, cacheKey, &token)
if err != nil {
+1 -2
View File
@@ -2,7 +2,6 @@ package repositories
import (
"context"
"fmt"
"history-api/pkg/cache"
"history-api/pkg/constants"
"time"
@@ -25,7 +24,7 @@ func NewUsageRepository(c cache.Cache) UsageRepository {
func (r *usageRepository) getUsageKey(userID string) string {
dateStr := time.Now().Format("20060102")
return fmt.Sprintf("usage:ai:%s:%s", userID, dateStr)
return cache.Key2("usage:ai", userID, dateStr)
}
func (r *usageRepository) GetAIUsage(ctx context.Context, userID string) (int, error) {
+25 -29
View File
@@ -2,9 +2,7 @@ package repositories
import (
"context"
"crypto/md5"
"encoding/json"
"fmt"
json "history-api/pkg/jsonx"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
@@ -54,9 +52,7 @@ func (r *userRepository) WithTx(tx pgx.Tx) UserRepository {
}
func (r *userRepository) generateQueryKey(prefix string, params any) string {
b, _ := json.Marshal(params)
hash := fmt.Sprintf("%x", md5.Sum(b))
return fmt.Sprintf("%s:%s", prefix, hash)
return cache.QueryKey(prefix, params)
}
func (r *userRepository) getByIDsWithFallback(ctx context.Context, ids []string) ([]*models.UserEntity, error) {
@@ -65,14 +61,14 @@ func (r *userRepository) getByIDsWithFallback(ctx context.Context, ids []string)
}
keys := make([]string, len(ids))
for i, id := range ids {
keys[i] = fmt.Sprintf("user:id:%s", id)
keys[i] = cache.Key("user:id", id)
}
raws := r.c.MGet(ctx, keys...)
var users []*models.UserEntity
missingUsersToCache := make(map[string]any)
users := make([]*models.UserEntity, 0, len(ids))
missingUsersToCache := make(map[string]any, len(ids))
var missingPgIds []pgtype.UUID
missingPgIds := make([]pgtype.UUID, 0, len(ids))
for i, b := range raws {
if len(b) == 0 {
pgId := pgtype.UUID{}
@@ -83,7 +79,7 @@ func (r *userRepository) getByIDsWithFallback(ctx context.Context, ids []string)
}
}
dbMap := make(map[string]*models.UserEntity)
dbMap := make(map[string]*models.UserEntity, len(missingPgIds))
if len(missingPgIds) > 0 {
dbRows, err := r.q.GetUsersByIDs(ctx, missingPgIds)
if err == nil {
@@ -126,7 +122,7 @@ func (r *userRepository) getByIDsWithFallback(ctx context.Context, ids []string)
}
func (r *userRepository) GetByID(ctx context.Context, id pgtype.UUID) (*models.UserEntity, error) {
cacheId := fmt.Sprintf("user:id:%s", convert.UUIDToString(id))
cacheId := cache.Key("user:id", convert.UUIDToString(id))
var user models.UserEntity
err := r.c.Get(ctx, cacheId, &user)
if err == nil {
@@ -164,7 +160,7 @@ func (r *userRepository) GetByID(ctx context.Context, id pgtype.UUID) (*models.U
}
func (r *userRepository) GetByIDWithoutDeleted(ctx context.Context, id pgtype.UUID) (*models.UserEntity, error) {
cacheId := fmt.Sprintf("user:deleted:id:%s", convert.UUIDToString(id))
cacheId := cache.Key("user:deleted:id", convert.UUIDToString(id))
var user models.UserEntity
err := r.c.Get(ctx, cacheId, &user)
if err == nil {
@@ -202,7 +198,7 @@ func (r *userRepository) GetByIDWithoutDeleted(ctx context.Context, id pgtype.UU
}
func (r *userRepository) GetByEmail(ctx context.Context, email string) (*models.UserEntity, error) {
cacheId := fmt.Sprintf("user:email:%s", email)
cacheId := cache.Key("user:email", email)
var user models.UserEntity
err := r.c.Get(ctx, cacheId, &user)
@@ -287,7 +283,7 @@ func (r *userRepository) UpdateProfile(ctx context.Context, params sqlc.UpdateUs
}
user.Profile = &profile
_ = r.c.Del(ctx, fmt.Sprintf("user:email:%s", user.Email), fmt.Sprintf("user:id:%s", user.ID))
_ = r.c.Del(ctx, cache.Key("user:email", user.Email), cache.Key("user:id", user.ID))
return user, nil
}
@@ -326,9 +322,9 @@ func (r *userRepository) Search(ctx context.Context, params sqlc.SearchUsersPara
return nil, err
}
var users []*models.UserEntity
var ids []string
usersToCache := make(map[string]any)
users := make([]*models.UserEntity, 0, len(rows))
ids := make([]string, 0, len(rows))
usersToCache := make(map[string]any, len(rows))
for _, row := range rows {
user := &models.UserEntity{
@@ -352,7 +348,7 @@ func (r *userRepository) Search(ctx context.Context, params sqlc.SearchUsersPara
users = append(users, user)
ids = append(ids, user.ID)
usersToCache[fmt.Sprintf("user:id:%s", user.ID)] = user
usersToCache[cache.Key("user:id", user.ID)] = user
}
if len(usersToCache) > 0 {
@@ -392,9 +388,9 @@ func (r *userRepository) Delete(ctx context.Context, id pgtype.UUID) error {
_ = r.c.Del(
ctx,
fmt.Sprintf("user:id:%s", user.ID),
fmt.Sprintf("user:email:%s", user.Email),
fmt.Sprintf("user:token:%s", user.ID),
cache.Key("user:id", user.ID),
cache.Key("user:email", user.Email),
cache.Key("user:token", user.ID),
)
go func() {
bgCtx := context.Background()
@@ -411,9 +407,9 @@ func (r *userRepository) Restore(ctx context.Context, id pgtype.UUID) error {
}
_ = r.c.Del(
ctx,
fmt.Sprintf("user:deleted:id:%s", convert.UUIDToString(id)),
fmt.Sprintf("user:email:%s", convert.UUIDToString(id)),
fmt.Sprintf("user:id:%s", convert.UUIDToString(id)),
cache.Key("user:deleted:id", convert.UUIDToString(id)),
cache.Key("user:email", convert.UUIDToString(id)),
cache.Key("user:id", convert.UUIDToString(id)),
)
go func() {
bgCtx := context.Background()
@@ -424,7 +420,7 @@ func (r *userRepository) Restore(ctx context.Context, id pgtype.UUID) error {
}
func (r *userRepository) GetTokenVersion(ctx context.Context, id pgtype.UUID) (int32, error) {
cacheId := fmt.Sprintf("user:token:%s", convert.UUIDToString(id))
cacheId := cache.Key("user:token", convert.UUIDToString(id))
var token int32
err := r.c.Get(ctx, cacheId, &token)
if err == nil {
@@ -445,7 +441,7 @@ func (r *userRepository) UpdateTokenVersion(ctx context.Context, params sqlc.Upd
if err != nil {
return err
}
_ = r.c.Del(ctx, fmt.Sprintf("user:token:%s", convert.UUIDToString(params.ID)))
_ = r.c.Del(ctx, cache.Key("user:token", convert.UUIDToString(params.ID)))
return nil
}
@@ -458,7 +454,7 @@ func (r *userRepository) UpdatePassword(ctx context.Context, params sqlc.UpdateU
if err != nil {
return err
}
_ = r.c.Del(ctx, fmt.Sprintf("user:email:%s", user.Email), fmt.Sprintf("user:id:%s", user.ID))
_ = r.c.Del(ctx, cache.Key("user:email", user.Email), cache.Key("user:id", user.ID))
return nil
}
@@ -474,6 +470,6 @@ func (r *userRepository) UpdateRefreshToken(ctx context.Context, params sqlc.Upd
user.RefreshToken = convert.TextToString(params.RefreshToken)
_ = r.c.Del(ctx, fmt.Sprintf("user:email:%s", user.Email), fmt.Sprintf("user:id:%s", user.ID))
_ = r.c.Del(ctx, cache.Key("user:email", user.Email), cache.Key("user:id", user.ID))
return nil
}
+22 -26
View File
@@ -2,14 +2,12 @@ package repositories
import (
"context"
"crypto/md5"
"encoding/json"
"fmt"
"history-api/internal/gen/sqlc"
"history-api/internal/models"
"history-api/pkg/cache"
"history-api/pkg/constants"
"history-api/pkg/convert"
json "history-api/pkg/jsonx"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
@@ -49,13 +47,11 @@ func (v *verificationRepository) WithTx(tx pgx.Tx) VerificationRepository {
}
func (v *verificationRepository) generateQueryKey(prefix string, params any) string {
b, _ := json.Marshal(params)
hash := fmt.Sprintf("%x", md5.Sum(b))
return fmt.Sprintf("%s:%s", prefix, hash)
return cache.QueryKey(prefix, params)
}
func (v *verificationRepository) GetByID(ctx context.Context, id pgtype.UUID) (*models.UserVerificationEntity, error) {
cacheId := fmt.Sprintf("verification:id:%s", convert.UUIDToString(id))
cacheId := cache.Key("verification:id", convert.UUIDToString(id))
var verification models.UserVerificationEntity
err := v.c.Get(ctx, cacheId, &verification)
if err == nil {
@@ -101,14 +97,14 @@ func (v *verificationRepository) getByIDsWithFallback(ctx context.Context, ids [
}
keys := make([]string, len(ids))
for i, id := range ids {
keys[i] = fmt.Sprintf("verification:id:%s", id)
keys[i] = cache.Key("verification:id", id)
}
raws := v.c.MGet(ctx, keys...)
var verification []*models.UserVerificationEntity
missingVerificationToCache := make(map[string]any)
verification := make([]*models.UserVerificationEntity, 0, len(ids))
missingVerificationToCache := make(map[string]any, len(ids))
var missingPgIds []pgtype.UUID
missingPgIds := make([]pgtype.UUID, 0, len(ids))
for i, b := range raws {
if len(b) == 0 {
pgId := pgtype.UUID{}
@@ -119,7 +115,7 @@ func (v *verificationRepository) getByIDsWithFallback(ctx context.Context, ids [
}
}
dbMap := make(map[string]*models.UserVerificationEntity)
dbMap := make(map[string]*models.UserVerificationEntity, len(missingPgIds))
if len(missingPgIds) > 0 {
dbRows, err := v.q.GetUserVerificationsByIDs(ctx, missingPgIds)
if err == nil {
@@ -212,7 +208,7 @@ func (v *verificationRepository) Create(ctx context.Context, params sqlc.CreateU
_ = v.c.DelByPattern(bgCtx, "verification:count*")
}()
_ = v.c.Del(ctx, fmt.Sprintf("verification:userId:%s", convert.UUIDToString(params.UserID)))
_ = v.c.Del(ctx, cache.Key("verification:userId", convert.UUIDToString(params.UserID)))
return &verification, nil
}
@@ -222,7 +218,7 @@ func (v *verificationRepository) UpdateStatus(ctx context.Context, params sqlc.U
if err != nil {
return err
}
_ = v.c.Del(ctx, fmt.Sprintf("verification:id:%s", convert.UUIDToString(params.ID)))
_ = v.c.Del(ctx, cache.Key("verification:id", convert.UUIDToString(params.ID)))
return nil
}
@@ -232,7 +228,7 @@ func (v *verificationRepository) Delete(ctx context.Context, id pgtype.UUID) err
return err
}
_ = v.c.Del(ctx, fmt.Sprintf("verification:id:%s", convert.UUIDToString(id)))
_ = v.c.Del(ctx, cache.Key("verification:id", convert.UUIDToString(id)))
go func() {
_ = v.c.DelByPattern(context.Background(), "verification:count*")
}()
@@ -249,13 +245,13 @@ func (v *verificationRepository) BulkVerificationMediaByMediaId(ctx context.Cont
return nil
}
listCacheId := make([]string, 0)
listCacheId := make([]string, 0, len(ids))
for _, it := range ids {
id := convert.UUIDToString(it)
if id == "" {
continue
}
listCacheId = append(listCacheId, fmt.Sprintf("verification:id:%s", id))
listCacheId = append(listCacheId, cache.Key("verification:id", id))
}
go func() {
@@ -276,7 +272,7 @@ func (v *verificationRepository) DeleteVerificationMedia(ctx context.Context, pa
}
func (v *verificationRepository) GetByUserID(ctx context.Context, userId pgtype.UUID) ([]*models.UserVerificationEntity, error) {
queryKey := fmt.Sprintf("verification:userId:%s", convert.UUIDToString(userId))
queryKey := cache.Key("verification:userId", convert.UUIDToString(userId))
var cachedIDs []string
err := v.c.Get(ctx, queryKey, &cachedIDs)
if err == nil {
@@ -299,9 +295,9 @@ func (v *verificationRepository) GetByUserID(ctx context.Context, userId pgtype.
if err != nil {
return nil, err
}
var items []*models.UserVerificationEntity
var ids []string
itemToCache := make(map[string]any)
items := make([]*models.UserVerificationEntity, 0, len(rows))
ids := make([]string, 0, len(rows))
itemToCache := make(map[string]any, len(rows))
for _, row := range rows {
verification := &models.UserVerificationEntity{
@@ -329,7 +325,7 @@ func (v *verificationRepository) GetByUserID(ctx context.Context, userId pgtype.
ids = append(ids, verification.ID)
items = append(items, verification)
itemToCache[fmt.Sprintf("verification:id:%s", verification.ID)] = verification
itemToCache[cache.Key("verification:id", verification.ID)] = verification
}
if len(itemToCache) > 0 {
@@ -365,9 +361,9 @@ func (v *verificationRepository) Search(ctx context.Context, params sqlc.SearchU
if err != nil {
return nil, err
}
var items []*models.UserVerificationEntity
var ids []string
itemToCache := make(map[string]any)
items := make([]*models.UserVerificationEntity, 0, len(rows))
ids := make([]string, 0, len(rows))
itemToCache := make(map[string]any, len(rows))
for _, row := range rows {
verification := &models.UserVerificationEntity{
@@ -396,7 +392,7 @@ func (v *verificationRepository) Search(ctx context.Context, params sqlc.SearchU
ids = append(ids, verification.ID)
items = append(items, verification)
itemToCache[fmt.Sprintf("verification:id:%s", verification.ID)] = verification
itemToCache[cache.Key("verification:id", verification.ID)] = verification
}
if len(itemToCache) > 0 {
+47 -50
View File
@@ -2,9 +2,7 @@ package repositories
import (
"context"
"crypto/md5"
"encoding/json"
"fmt"
json "history-api/pkg/jsonx"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
@@ -60,9 +58,7 @@ func (r *wikiRepository) WithTx(tx pgx.Tx) WikiRepository {
}
func (r *wikiRepository) generateQueryKey(prefix string, params any) string {
b, _ := json.Marshal(params)
hash := fmt.Sprintf("%x", md5.Sum(b))
return fmt.Sprintf("%s:%s", prefix, hash)
return cache.QueryKey(prefix, params)
}
func (r *wikiRepository) getByIDsWithFallback(ctx context.Context, ids []string) ([]*models.WikiEntity, error) {
@@ -71,14 +67,14 @@ func (r *wikiRepository) getByIDsWithFallback(ctx context.Context, ids []string)
}
keys := make([]string, len(ids))
for i, id := range ids {
keys[i] = fmt.Sprintf("wiki:id:%s", id)
keys[i] = cache.Key("wiki:id", id)
}
raws := r.c.MGet(ctx, keys...)
var wikis []*models.WikiEntity
missingToCache := make(map[string]any)
wikis := make([]*models.WikiEntity, 0, len(ids))
missingToCache := make(map[string]any, len(ids))
var missingPgIds []pgtype.UUID
missingPgIds := make([]pgtype.UUID, 0, len(ids))
for i, b := range raws {
if len(b) == 0 {
pgId := pgtype.UUID{}
@@ -89,7 +85,7 @@ func (r *wikiRepository) getByIDsWithFallback(ctx context.Context, ids []string)
}
}
dbMap := make(map[string]*models.WikiEntity)
dbMap := make(map[string]*models.WikiEntity, len(missingPgIds))
if len(missingPgIds) > 0 {
dbRows, err := r.q.GetWikisByIDs(ctx, missingPgIds)
if err == nil {
@@ -148,7 +144,7 @@ func (r *wikiRepository) GetByIDs(ctx context.Context, ids []string) ([]*models.
}
func (r *wikiRepository) GetByID(ctx context.Context, id pgtype.UUID) (*models.WikiEntity, error) {
cacheId := fmt.Sprintf("wiki:id:%s", convert.UUIDToString(id))
cacheId := cache.Key("wiki:id", convert.UUIDToString(id))
var wiki models.WikiEntity
err := r.c.Get(ctx, cacheId, &wiki)
if err == nil {
@@ -173,6 +169,7 @@ func (r *wikiRepository) GetByID(ctx context.Context, id pgtype.UUID) (*models.W
samples, err := r.q.GetWikiContentByWikiID(ctx, row.ID)
if err == nil {
wiki.ContentSample = make([]models.WikiContentSample, 0, len(samples))
for _, sample := range samples {
wiki.ContentSample = append(wiki.ContentSample, models.WikiContentSample{
ID: convert.UUIDToString(sample.ID),
@@ -202,11 +199,11 @@ func (r *wikiRepository) Search(ctx context.Context, params sqlc.SearchWikisPara
if err != nil {
return nil, err
}
var wikis []*models.WikiEntity
var ids []string
var pgIds []pgtype.UUID
wikiMap := make(map[string]*models.WikiEntity)
wikiToCache := make(map[string]any)
wikis := make([]*models.WikiEntity, 0, len(rows))
ids := make([]string, 0, len(rows))
pgIds := make([]pgtype.UUID, 0, len(rows))
wikiMap := make(map[string]*models.WikiEntity, len(rows))
wikiToCache := make(map[string]any, len(rows))
for _, row := range rows {
wiki := &models.WikiEntity{
@@ -241,7 +238,7 @@ func (r *wikiRepository) Search(ctx context.Context, params sqlc.SearchWikisPara
}
for _, wiki := range wikis {
wikiToCache[fmt.Sprintf("wiki:id:%s", wiki.ID)] = wiki
wikiToCache[cache.Key("wiki:id", wiki.ID)] = wiki
}
if len(wikiToCache) > 0 {
_ = r.c.MSet(ctx, wikiToCache, constants.NormalCacheDuration)
@@ -284,8 +281,7 @@ func (r *wikiRepository) Update(ctx context.Context, params sqlc.UpdateWikiParam
CreatedAt: convert.TimeToPtr(row.CreatedAt),
UpdatedAt: convert.TimeToPtr(row.UpdatedAt),
}
_ = r.c.Del(ctx, fmt.Sprintf("wiki:id:%s", wiki.ID))
_ = r.c.Del(ctx, fmt.Sprintf("wiki:slug:%s", wiki.Slug))
_ = r.c.Del(ctx, cache.Key("wiki:id", wiki.ID), cache.Key("wiki:slug", wiki.Slug))
return &wiki, nil
}
@@ -294,7 +290,7 @@ func (r *wikiRepository) Delete(ctx context.Context, id pgtype.UUID) error {
if err != nil {
return err
}
_ = r.c.Del(ctx, fmt.Sprintf("wiki:id:%s", convert.UUIDToString(id)))
_ = r.c.Del(ctx, cache.Key("wiki:id", convert.UUIDToString(id)))
return nil
}
@@ -315,7 +311,7 @@ func (r *wikiRepository) BulkDeleteEntityWikisByEntityId(ctx context.Context, en
}
func (r *wikiRepository) GetByProjectID(ctx context.Context, projectID pgtype.UUID) ([]*models.WikiEntity, error) {
cacheKey := fmt.Sprintf("wiki:project:%s", convert.UUIDToString(projectID))
cacheKey := cache.Key("wiki:project", convert.UUIDToString(projectID))
var cachedIDs []string
err := r.c.Get(ctx, cacheKey, &cachedIDs)
if err == nil {
@@ -330,11 +326,11 @@ func (r *wikiRepository) GetByProjectID(ctx context.Context, projectID pgtype.UU
return nil, err
}
var wikis []*models.WikiEntity
var ids []string
var pgIds []pgtype.UUID
wikiMap := make(map[string]*models.WikiEntity)
wikiToCache := make(map[string]any)
wikis := make([]*models.WikiEntity, 0, len(rows))
ids := make([]string, 0, len(rows))
pgIds := make([]pgtype.UUID, 0, len(rows))
wikiMap := make(map[string]*models.WikiEntity, len(rows))
wikiToCache := make(map[string]any, len(rows))
for _, row := range rows {
wiki := &models.WikiEntity{
@@ -369,7 +365,7 @@ func (r *wikiRepository) GetByProjectID(ctx context.Context, projectID pgtype.UU
}
for _, wiki := range wikis {
wikiToCache[fmt.Sprintf("wiki:id:%s", wiki.ID)] = wiki
wikiToCache[cache.Key("wiki:id", wiki.ID)] = wiki
}
if len(wikiToCache) > 0 {
_ = r.c.MSet(ctx, wikiToCache, constants.NormalCacheDuration)
@@ -387,7 +383,7 @@ func (r *wikiRepository) DeleteByIDs(ctx context.Context, ids []pgtype.UUID) err
if len(ids) > 0 {
keys := make([]string, len(ids))
for i, id := range ids {
keys[i] = fmt.Sprintf("wiki:id:%s", convert.UUIDToString(id))
keys[i] = cache.Key("wiki:id", convert.UUIDToString(id))
}
_ = r.c.Del(ctx, keys...)
}
@@ -406,7 +402,7 @@ func (r *wikiRepository) DeleteEntityWiki(ctx context.Context, entityID pgtype.U
}
func (r *wikiRepository) GetBySlug(ctx context.Context, slug string) (*models.WikiEntity, error) {
cacheKey := fmt.Sprintf("wiki:slug:%s", slug)
cacheKey := cache.Key("wiki:slug", slug)
var wiki models.WikiEntity
err := r.c.Get(ctx, cacheKey, &wiki)
if err == nil {
@@ -431,6 +427,7 @@ func (r *wikiRepository) GetBySlug(ctx context.Context, slug string) (*models.Wi
samples, err := r.q.GetWikiContentByWikiID(ctx, row.ID)
if err == nil {
wiki.ContentSample = make([]models.WikiContentSample, 0, len(samples))
for _, sample := range samples {
wiki.ContentSample = append(wiki.ContentSample, models.WikiContentSample{
ID: convert.UUIDToString(sample.ID),
@@ -451,13 +448,13 @@ func (r *wikiRepository) GetBySlugs(ctx context.Context, slugs []string) ([]*mod
}
keys := make([]string, len(slugs))
for i, slug := range slugs {
keys[i] = fmt.Sprintf("wiki:slug:%s", slug)
keys[i] = cache.Key("wiki:slug", slug)
}
raws := r.c.MGet(ctx, keys...)
var wikis []*models.WikiEntity
missingToCache := make(map[string]any)
var missingSlugs []string
wikis := make([]*models.WikiEntity, 0, len(slugs))
missingToCache := make(map[string]any, len(slugs))
missingSlugs := make([]string, 0, len(slugs))
for i, b := range raws {
if len(b) == 0 {
@@ -465,11 +462,11 @@ func (r *wikiRepository) GetBySlugs(ctx context.Context, slugs []string) ([]*mod
}
}
dbMap := make(map[string]*models.WikiEntity)
dbMap := make(map[string]*models.WikiEntity, len(missingSlugs))
if len(missingSlugs) > 0 {
dbRows, err := r.q.GetWikisBySlugs(ctx, missingSlugs)
if err == nil {
var pgIds []pgtype.UUID
pgIds := make([]pgtype.UUID, 0, len(dbRows))
for _, row := range dbRows {
item := models.WikiEntity{
ID: convert.UUIDToString(row.ID),
@@ -487,7 +484,7 @@ func (r *wikiRepository) GetBySlugs(ctx context.Context, slugs []string) ([]*mod
if len(pgIds) > 0 {
samples, sErr := r.q.GetWikiContentByWikiIDs(ctx, pgIds)
if sErr == nil {
wikiByID := make(map[string]*models.WikiEntity)
wikiByID := make(map[string]*models.WikiEntity, len(dbMap))
for _, item := range dbMap {
wikiByID[item.ID] = item
}
@@ -554,14 +551,14 @@ func (r *wikiRepository) getContentByIDsWithFallback(ctx context.Context, ids []
}
keys := make([]string, len(ids))
for i, id := range ids {
keys[i] = fmt.Sprintf("wiki_content:id:%s", id)
keys[i] = cache.Key("wiki_content:id", id)
}
raws := r.c.MGet(ctx, keys...)
var contents []*models.WikiContentEntity
missingToCache := make(map[string]any)
contents := make([]*models.WikiContentEntity, 0, len(ids))
missingToCache := make(map[string]any, len(ids))
var missingPgIds []pgtype.UUID
missingPgIds := make([]pgtype.UUID, 0, len(ids))
for i, b := range raws {
if len(b) == 0 {
pgId := pgtype.UUID{}
@@ -572,7 +569,7 @@ func (r *wikiRepository) getContentByIDsWithFallback(ctx context.Context, ids []
}
}
dbMap := make(map[string]*models.WikiContentEntity)
dbMap := make(map[string]*models.WikiContentEntity, len(missingPgIds))
if len(missingPgIds) > 0 {
dbRows, err := r.q.GetWikiContentByIDs(ctx, missingPgIds)
if err == nil {
@@ -613,7 +610,7 @@ func (r *wikiRepository) getContentByIDsWithFallback(ctx context.Context, ids []
}
func (r *wikiRepository) GetContentByID(ctx context.Context, id pgtype.UUID) (*models.WikiContentEntity, error) {
cacheId := fmt.Sprintf("wiki_content:id:%s", convert.UUIDToString(id))
cacheId := cache.Key("wiki_content:id", convert.UUIDToString(id))
var content models.WikiContentEntity
err := r.c.Get(ctx, cacheId, &content)
if err == nil {
@@ -651,13 +648,13 @@ func (r *wikiRepository) GetWikiIDsByEntityIDs(ctx context.Context, entityIDs []
keys := make([]string, len(entityIDs))
for i, id := range entityIDs {
keys[i] = fmt.Sprintf("entity_wikis:entity:%s", id)
keys[i] = cache.Key("entity_wikis:entity", id)
}
raws := r.c.MGet(ctx, keys...)
result := make(map[string][]string)
var missingEntityIDs []string
var missingPgIDs []pgtype.UUID
result := make(map[string][]string, len(entityIDs))
missingEntityIDs := make([]string, 0, len(entityIDs))
missingPgIDs := make([]pgtype.UUID, 0, len(entityIDs))
for i, b := range raws {
if len(b) > 0 {
@@ -680,7 +677,7 @@ func (r *wikiRepository) GetWikiIDsByEntityIDs(ctx context.Context, entityIDs []
return nil, err
}
dbMap := make(map[string][]string)
dbMap := make(map[string][]string, len(missingEntityIDs))
for _, id := range missingEntityIDs {
dbMap[id] = []string{}
}
@@ -690,10 +687,10 @@ func (r *wikiRepository) GetWikiIDsByEntityIDs(ctx context.Context, entityIDs []
dbMap[eID] = append(dbMap[eID], wID)
}
missingToCache := make(map[string]any)
missingToCache := make(map[string]any, len(dbMap))
for eID, wIDs := range dbMap {
result[eID] = wIDs
missingToCache[fmt.Sprintf("entity_wikis:entity:%s", eID)] = wIDs
missingToCache[cache.Key("entity_wikis:entity", eID)] = wIDs
}
if len(missingToCache) > 0 {
_ = r.c.MSet(ctx, missingToCache, constants.NormalCacheDuration)