GraphQL API and utilities for the rpdata project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

246 lines
5.1 KiB

  1. package postgres
  2. import (
  3. "context"
  4. "database/sql"
  5. "fmt"
  6. "git.aiterp.net/rpdata/api/database/postgres/psqlcore"
  7. "git.aiterp.net/rpdata/api/internal/generate"
  8. "git.aiterp.net/rpdata/api/models"
  9. "strconv"
  10. "time"
  11. )
  12. type logRepository struct {
  13. insertWithIDs bool
  14. db *sql.DB
  15. }
  16. func (r *logRepository) Find(ctx context.Context, id string) (*models.Log, error) {
  17. log, err := psqlcore.New(r.db).SelectLog(ctx, id)
  18. if err != nil {
  19. return nil, err
  20. }
  21. return r.log(log), nil
  22. }
  23. func (r *logRepository) List(ctx context.Context, filter models.LogFilter) ([]*models.Log, error) {
  24. q := psqlcore.New(r.db)
  25. params := psqlcore.SelectLogsParams{
  26. LimitSize: 0,
  27. }
  28. if filter.Search != nil {
  29. ids, err := q.SelectLogIDsFromPostSearch(ctx, *filter.Search)
  30. if err != nil {
  31. return nil, err
  32. }
  33. params.FilterShortID = true
  34. params.ShortIds = ids
  35. }
  36. if filter.Open != nil {
  37. params.FilterOpen = true
  38. params.Open = *filter.Open
  39. }
  40. if filter.Channels != nil {
  41. params.FilterChannelName = true
  42. params.ChannelNames = filter.Channels
  43. }
  44. if filter.Events != nil {
  45. params.FilterEventName = true
  46. params.EventNames = filter.Events
  47. }
  48. if filter.MinDate != nil {
  49. params.FilterEarlistDate = true
  50. params.EarliestDate = *filter.MinDate
  51. }
  52. if filter.MaxDate != nil {
  53. params.FilterLastestDate = true
  54. params.LatestDate = *filter.MaxDate
  55. }
  56. if filter.Limit > 0 {
  57. params.LimitSize = int32(filter.Limit)
  58. }
  59. logs, err := q.SelectLogs(ctx, params)
  60. if err != nil {
  61. return nil, err
  62. }
  63. return r.logs(logs), nil
  64. }
  65. func (r *logRepository) Insert(ctx context.Context, log models.Log) (*models.Log, error) {
  66. tx, err := r.db.BeginTx(ctx, nil)
  67. if err != nil {
  68. return nil, err
  69. }
  70. defer func() { _ = tx.Rollback() }()
  71. q := psqlcore.New(tx)
  72. if !r.insertWithIDs || log.ID == "" {
  73. log.ID = generate.LogID(log)
  74. }
  75. if !r.insertWithIDs || log.ShortID == "" {
  76. next, err := q.IncrementCounter(ctx, "log_short_id")
  77. if err != nil {
  78. return nil, err
  79. }
  80. log.ShortID = fmt.Sprintf("L%d", next)
  81. } else {
  82. n, err := strconv.Atoi(log.ShortID[1:])
  83. if err != nil {
  84. return nil, err
  85. }
  86. err = q.BumpCounter(ctx, psqlcore.BumpCounterParams{
  87. ID: "log_short_id",
  88. Value: int32(n),
  89. })
  90. if err != nil {
  91. return nil, err
  92. }
  93. }
  94. err = q.InsertLog(ctx, psqlcore.InsertLogParams{
  95. ID: log.ID,
  96. ShortID: log.ShortID,
  97. Date: log.Date.UTC(),
  98. ChannelName: log.ChannelName,
  99. EventName: log.EventName,
  100. Title: log.Title,
  101. Description: log.Description,
  102. Open: log.Open,
  103. CharacterIds: log.CharacterIDs,
  104. })
  105. if err != nil {
  106. return nil, err
  107. }
  108. err = tx.Commit()
  109. if err != nil {
  110. return nil, err
  111. }
  112. _ = r.updateTags(log)
  113. return &log, nil
  114. }
  115. func (r *logRepository) Update(ctx context.Context, log models.Log, update models.LogUpdate) (*models.Log, error) {
  116. log.ApplyUpdate(update)
  117. err := psqlcore.New(r.db).UpdateLog(ctx, psqlcore.UpdateLogParams{
  118. Title: log.Title,
  119. EventName: log.EventName,
  120. Description: log.Description,
  121. Open: log.Open,
  122. CharacterIds: log.CharacterIDs,
  123. ID: log.ID,
  124. })
  125. if err != nil {
  126. return nil, err
  127. }
  128. _ = r.updateTags(log)
  129. return &log, nil
  130. }
  131. func (r *logRepository) Delete(ctx context.Context, log models.Log) error {
  132. tx, err := r.db.BeginTx(ctx, nil)
  133. if err != nil {
  134. return err
  135. }
  136. defer func() { _ = tx.Rollback() }()
  137. q := psqlcore.New(tx)
  138. err = q.DeleteLog(ctx, log.ID)
  139. if err != nil {
  140. return err
  141. }
  142. err = q.DeletePostsByLogShortID(ctx, log.ShortID)
  143. if err != nil {
  144. return err
  145. }
  146. return tx.Commit()
  147. }
  148. func (r *logRepository) log(log psqlcore.Log) *models.Log {
  149. return &models.Log{
  150. ID: log.ID,
  151. ShortID: log.ShortID,
  152. Date: log.Date,
  153. ChannelName: log.ChannelName,
  154. EventName: log.EventName,
  155. Title: log.Title,
  156. Description: log.Description,
  157. Open: log.Open,
  158. CharacterIDs: log.CharacterIds,
  159. }
  160. }
  161. func (r *logRepository) logs(logs []psqlcore.Log) []*models.Log {
  162. results := make([]*models.Log, 0, len(logs))
  163. for _, log := range logs {
  164. results = append(results, r.log(log))
  165. }
  166. return results
  167. }
  168. func (r *logRepository) updateTags(log models.Log) error {
  169. ctx, cancel := context.WithTimeout(context.Background(), time.Second)
  170. defer cancel()
  171. tx, err := r.db.BeginTx(ctx, nil)
  172. if err != nil {
  173. return err
  174. }
  175. defer func() { _ = tx.Rollback() }()
  176. q := psqlcore.New(tx)
  177. err = q.ClearTagsByTarget(ctx, psqlcore.ClearTagsByTargetParams{TargetKind: "Log", TargetID: log.ID})
  178. if err != nil {
  179. return err
  180. }
  181. if len(log.CharacterIDs) > 0 {
  182. err := q.SetCharacterTagsFromIDs(ctx, psqlcore.SetCharacterTagsFromIDsParams{
  183. TargetKind: "log",
  184. TargetID: log.ID,
  185. CharacterIds: log.CharacterIDs,
  186. })
  187. if err != nil {
  188. return err
  189. }
  190. }
  191. err = q.SetLocationTagFromChannelName(ctx, psqlcore.SetLocationTagFromChannelNameParams{
  192. TargetKind: "log",
  193. TargetID: log.ID,
  194. ChannelName: log.ChannelName,
  195. })
  196. if err != nil {
  197. return err
  198. }
  199. if log.EventName != "" {
  200. err := q.SetTag(ctx, psqlcore.SetTagParams{
  201. Tag: "Event:" + log.EventName,
  202. TargetKind: "Log",
  203. TargetID: log.ID,
  204. })
  205. if err != nil {
  206. return err
  207. }
  208. }
  209. return tx.Commit()
  210. }