redis.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. package helpers
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "os"
  7. "strings"
  8. "github.com/redis/go-redis/v9"
  9. )
  10. type DocAlreadyExists struct {
  11. Key string
  12. Value string
  13. }
  14. func (d *DocAlreadyExists) Error() string {
  15. return fmt.Sprintf("Key: '%s' already exists with value: '%s'", d.Key, d.Value)
  16. }
  17. type DocDoesntExist struct {
  18. Key string
  19. }
  20. func (d *DocDoesntExist) Error() string {
  21. return fmt.Sprintf("Document with ID: '%s' does not exist.", d.Key)
  22. }
  23. type InvalidTopic struct {Topic string}
  24. func (i *InvalidTopic) Error() string {
  25. return fmt.Sprintf("Topic: %s is not a valid topic category.", i.Topic)
  26. }
  27. type RedisConf struct {
  28. Addr string
  29. Port string
  30. }
  31. type RedisCaller struct {
  32. ctx context.Context
  33. Client *redis.Client
  34. }
  35. /*
  36. Creates a new RedisCaller struct
  37. :param redisCfg: a redis configuration struct
  38. */
  39. func NewRedisClient(redisCfg RedisConf) *RedisCaller {
  40. return &RedisCaller{Client: redis.NewClient(&redis.Options{
  41. Addr: fmt.Sprintf("%s:%v", redisCfg.Addr, redisCfg.Port),
  42. DB: 0, // use default DB
  43. }),
  44. ctx: context.Background(),}
  45. }
  46. /*
  47. retrieves all of the document IDs in the Redis database
  48. */
  49. func (r *RedisCaller) AllDocIds() ([]string, error) {
  50. return r.Client.Keys(r.ctx, "*").Result()
  51. }
  52. /*
  53. Sets the item (id) to the value supplied in value
  54. :param doc: the documents.Document struct to input to the database
  55. */
  56. func (r *RedisCaller) AddDoc(doc Document) error {
  57. _, ok := TopicMap[doc.Category]
  58. if !ok {
  59. return &InvalidTopic{Topic: doc.Category}
  60. }
  61. val, err := r.Client.Get(r.ctx, doc.Ident).Result()
  62. if err == redis.Nil {
  63. data, err := json.Marshal(&doc)
  64. if err != nil {
  65. return err
  66. }
  67. err = r.Client.Set(r.ctx, doc.Ident, data, 0).Err()
  68. if err != nil {
  69. return err
  70. }
  71. return nil
  72. } else if err != nil {
  73. return err
  74. }
  75. return &DocAlreadyExists{Key: doc.Ident, Value: val}
  76. }
  77. /*
  78. Gets the item stored at the key (id)
  79. :param id: the id of the object to get
  80. */
  81. func (r *RedisCaller) GetItem(id string) (*Document, error) {
  82. var doc Document
  83. val, err := r.Client.Get(r.ctx, id).Result()
  84. if err == redis.Nil {
  85. return nil, err
  86. } else if err != nil {
  87. return nil, err
  88. }
  89. data := []byte(val)
  90. err = json.Unmarshal(data, &doc)
  91. if err != nil {
  92. return nil, err
  93. }
  94. return &doc, nil
  95. }
  96. /*
  97. Delete the target document in redis
  98. :param id: the id to delete from redis
  99. */
  100. func (r *RedisCaller) DeleteDoc(id string) error {
  101. _, err := r.Client.Get(r.ctx, id).Result()
  102. if err == redis.Nil {
  103. return &DocDoesntExist{id}
  104. } else if err != nil {
  105. return err
  106. }
  107. err = r.Client.Del(r.ctx, id).Err()
  108. if err != nil {
  109. return err
  110. }
  111. return nil
  112. }
  113. /*
  114. Update a value in redis
  115. :param id: the id of the document to edit
  116. */
  117. func (r *RedisCaller) editVal(id string, in interface{}) error {
  118. _, err := r.Client.Get(r.ctx, id).Result()
  119. if err != nil {
  120. if err == redis.Nil {
  121. return &DocDoesntExist{Key: id}
  122. }
  123. return err
  124. }
  125. data, err := json.Marshal(&in)
  126. if err != nil {
  127. return err
  128. }
  129. err = r.Client.Set(r.ctx, id, data, 0).Err()
  130. if err != nil {
  131. return err
  132. }
  133. return nil
  134. }
  135. func (r *RedisCaller) SeedData(seedLoc string) error {
  136. dirs, err := os.ReadDir(seedLoc)
  137. if err != nil {
  138. return err
  139. }
  140. for i := range dirs {
  141. key := strings.Split(dirs[i].Name(), ".")[0]
  142. b, err := os.ReadFile(fmt.Sprintf("%s/%s", seedLoc, dirs[i].Name()))
  143. if err != nil {
  144. return err
  145. }
  146. err = r.Client.Set(r.ctx, key, b, 0).Err()
  147. if err != nil {
  148. return err
  149. }
  150. }
  151. return nil
  152. }
  153. func (r *RedisCaller) UpdatePost(id string, new Document) error {
  154. return r.editVal(id, new)
  155. }
  156. func (r *RedisCaller) UpdateHeader(id string, new HeaderCollection) error {
  157. return r.editVal(id, new)
  158. }
  159. func (r *RedisCaller) UpdateMenu(id string, new MenuElement) error {
  160. return r.editVal(id, new)
  161. }