redis.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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. Add an image to the image store
  79. :param img: an ImageStoreItem struct with the appropriate metadata
  80. */
  81. func (r *RedisCaller) AddImage(img *ImageStoreItem) error {
  82. val, err := r.Client.Get(r.ctx, img.Identifier).Result()
  83. if err == redis.Nil {
  84. data, err := json.Marshal(img)
  85. if err != nil {
  86. return err
  87. }
  88. err = r.Client.Set(r.ctx, img.Identifier, data, 0).Err()
  89. if err != nil {
  90. return err
  91. }
  92. return nil
  93. } else if err != nil {
  94. return err
  95. }
  96. return &DocAlreadyExists{Key: img.Identifier, Value: val}
  97. }
  98. /*
  99. Gets the item stored at the key (id)
  100. :param id: the id of the object to get
  101. */
  102. func (r *RedisCaller) GetItem(id string) (*Document, error) {
  103. var doc Document
  104. val, err := r.Client.Get(r.ctx, id).Result()
  105. if err == redis.Nil {
  106. return nil, err
  107. } else if err != nil {
  108. return nil, err
  109. }
  110. data := []byte(val)
  111. err = json.Unmarshal(data, &doc)
  112. if err != nil {
  113. return nil, err
  114. }
  115. return &doc, nil
  116. }
  117. /*
  118. Delete the target document in redis
  119. :param id: the id to delete from redis
  120. */
  121. func (r *RedisCaller) DeleteDoc(id string) error {
  122. _, err := r.Client.Get(r.ctx, id).Result()
  123. if err == redis.Nil {
  124. return &DocDoesntExist{id}
  125. } else if err != nil {
  126. return err
  127. }
  128. err = r.Client.Del(r.ctx, id).Err()
  129. if err != nil {
  130. return err
  131. }
  132. return nil
  133. }
  134. /*
  135. Update a value in redis
  136. :param id: the id of the document to edit
  137. */
  138. func (r *RedisCaller) editVal(id string, in interface{}) error {
  139. _, err := r.Client.Get(r.ctx, id).Result()
  140. if err != nil {
  141. if err == redis.Nil {
  142. return &DocDoesntExist{Key: id}
  143. }
  144. return err
  145. }
  146. data, err := json.Marshal(&in)
  147. if err != nil {
  148. return err
  149. }
  150. err = r.Client.Set(r.ctx, id, data, 0).Err()
  151. if err != nil {
  152. return err
  153. }
  154. return nil
  155. }
  156. func (r *RedisCaller) SeedData(seedLoc string) error {
  157. dirs, err := os.ReadDir(seedLoc)
  158. if err != nil {
  159. return err
  160. }
  161. for i := range dirs {
  162. key := strings.Split(dirs[i].Name(), ".")[0]
  163. b, err := os.ReadFile(fmt.Sprintf("%s/%s", seedLoc, dirs[i].Name()))
  164. if err != nil {
  165. return err
  166. }
  167. err = r.Client.Set(r.ctx, key, b, 0).Err()
  168. if err != nil {
  169. return err
  170. }
  171. }
  172. return nil
  173. }
  174. func (r *RedisCaller) UpdatePost(id string, new Document) error {
  175. return r.editVal(id, new)
  176. }
  177. func (r *RedisCaller) UpdateHeader(id string, new HeaderCollection) error {
  178. return r.editVal(id, new)
  179. }
  180. func (r *RedisCaller) UpdateMenu(id string, new MenuElement) error {
  181. return r.editVal(id, new)
  182. }