user_setting.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. package store
  2. import (
  3. "context"
  4. "database/sql"
  5. "strings"
  6. "github.com/usememos/memos/api"
  7. )
  8. type userSettingRaw struct {
  9. UserID int
  10. Key api.UserSettingKey
  11. Value string
  12. }
  13. func (raw *userSettingRaw) toUserSetting() *api.UserSetting {
  14. return &api.UserSetting{
  15. UserID: raw.UserID,
  16. Key: raw.Key,
  17. Value: raw.Value,
  18. }
  19. }
  20. func (s *Store) UpsertUserSetting(ctx context.Context, upsert *api.UserSettingUpsert) (*api.UserSetting, error) {
  21. tx, err := s.db.BeginTx(ctx, nil)
  22. if err != nil {
  23. return nil, FormatError(err)
  24. }
  25. defer tx.Rollback()
  26. userSettingRaw, err := upsertUserSetting(ctx, tx, upsert)
  27. if err != nil {
  28. return nil, err
  29. }
  30. if err := tx.Commit(); err != nil {
  31. return nil, err
  32. }
  33. s.userSettingCache.Store(getUserSettingCacheKey(*userSettingRaw), userSettingRaw)
  34. userSetting := userSettingRaw.toUserSetting()
  35. return userSetting, nil
  36. }
  37. func (s *Store) FindUserSettingList(ctx context.Context, find *api.UserSettingFind) ([]*api.UserSetting, error) {
  38. tx, err := s.db.BeginTx(ctx, nil)
  39. if err != nil {
  40. return nil, FormatError(err)
  41. }
  42. defer tx.Rollback()
  43. userSettingRawList, err := findUserSettingList(ctx, tx, find)
  44. if err != nil {
  45. return nil, err
  46. }
  47. list := []*api.UserSetting{}
  48. for _, raw := range userSettingRawList {
  49. s.userSettingCache.Store(getUserSettingCacheKey(*raw), raw)
  50. list = append(list, raw.toUserSetting())
  51. }
  52. return list, nil
  53. }
  54. func (s *Store) FindUserSetting(ctx context.Context, find *api.UserSettingFind) (*api.UserSetting, error) {
  55. if userSetting, ok := s.userSettingCache.Load(getUserSettingFindCacheKey(find)); ok {
  56. if userSetting == nil {
  57. return nil, nil
  58. }
  59. return userSetting.(*userSettingRaw).toUserSetting(), nil
  60. }
  61. tx, err := s.db.BeginTx(ctx, nil)
  62. if err != nil {
  63. return nil, FormatError(err)
  64. }
  65. defer tx.Rollback()
  66. list, err := findUserSettingList(ctx, tx, find)
  67. if err != nil {
  68. return nil, err
  69. }
  70. if len(list) == 0 {
  71. s.userSettingCache.Store(getUserSettingFindCacheKey(find), nil)
  72. return nil, nil
  73. }
  74. userSettingRaw := list[0]
  75. s.userSettingCache.Store(getUserSettingCacheKey(*userSettingRaw), userSettingRaw)
  76. return userSettingRaw.toUserSetting(), nil
  77. }
  78. func upsertUserSetting(ctx context.Context, tx *sql.Tx, upsert *api.UserSettingUpsert) (*userSettingRaw, error) {
  79. query := `
  80. INSERT INTO user_setting (
  81. user_id, key, value
  82. )
  83. VALUES (?, ?, ?)
  84. ON CONFLICT(user_id, key) DO UPDATE
  85. SET
  86. value = EXCLUDED.value
  87. RETURNING user_id, key, value
  88. `
  89. var userSettingRaw userSettingRaw
  90. if err := tx.QueryRowContext(ctx, query, upsert.UserID, upsert.Key, upsert.Value).Scan(
  91. &userSettingRaw.UserID,
  92. &userSettingRaw.Key,
  93. &userSettingRaw.Value,
  94. ); err != nil {
  95. return nil, FormatError(err)
  96. }
  97. return &userSettingRaw, nil
  98. }
  99. func findUserSettingList(ctx context.Context, tx *sql.Tx, find *api.UserSettingFind) ([]*userSettingRaw, error) {
  100. where, args := []string{"1 = 1"}, []any{}
  101. if v := find.Key.String(); v != "" {
  102. where, args = append(where, "key = ?"), append(args, v)
  103. }
  104. where, args = append(where, "user_id = ?"), append(args, find.UserID)
  105. query := `
  106. SELECT
  107. user_id,
  108. key,
  109. value
  110. FROM user_setting
  111. WHERE ` + strings.Join(where, " AND ")
  112. rows, err := tx.QueryContext(ctx, query, args...)
  113. if err != nil {
  114. return nil, FormatError(err)
  115. }
  116. defer rows.Close()
  117. userSettingRawList := make([]*userSettingRaw, 0)
  118. for rows.Next() {
  119. var userSettingRaw userSettingRaw
  120. if err := rows.Scan(
  121. &userSettingRaw.UserID,
  122. &userSettingRaw.Key,
  123. &userSettingRaw.Value,
  124. ); err != nil {
  125. return nil, FormatError(err)
  126. }
  127. userSettingRawList = append(userSettingRawList, &userSettingRaw)
  128. }
  129. if err := rows.Err(); err != nil {
  130. return nil, FormatError(err)
  131. }
  132. return userSettingRawList, nil
  133. }
  134. func vacuumUserSetting(ctx context.Context, tx *sql.Tx) error {
  135. stmt := `
  136. DELETE FROM
  137. user_setting
  138. WHERE
  139. user_id NOT IN (
  140. SELECT
  141. id
  142. FROM
  143. user
  144. )`
  145. _, err := tx.ExecContext(ctx, stmt)
  146. if err != nil {
  147. return FormatError(err)
  148. }
  149. return nil
  150. }