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.

177 lines
3.2 KiB

  1. package mongodb
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/globalsign/mgo/bson"
  6. "time"
  7. "git.aiterp.net/rpdata/api/internal/config"
  8. "git.aiterp.net/rpdata/api/repositories"
  9. "github.com/globalsign/mgo"
  10. )
  11. type MongoDB struct {
  12. session *mgo.Session
  13. changes repositories.ChangeRepository
  14. channels *channelRepository
  15. characters repositories.CharacterRepository
  16. tags repositories.TagRepository
  17. logs *logRepository
  18. posts *postRepository
  19. }
  20. func (m *MongoDB) Changes() repositories.ChangeRepository {
  21. return m.changes
  22. }
  23. func (m *MongoDB) Characters() repositories.CharacterRepository {
  24. return m.characters
  25. }
  26. func (m *MongoDB) Tags() repositories.TagRepository {
  27. return m.tags
  28. }
  29. func (m *MongoDB) Logs() repositories.LogRepository {
  30. return m.logs
  31. }
  32. func (m *MongoDB) Posts() repositories.PostRepository {
  33. return m.posts
  34. }
  35. func (m *MongoDB) Channels() repositories.ChannelRepository {
  36. return m.channels
  37. }
  38. func (m *MongoDB) Close(ctx context.Context) error {
  39. m.session.Close()
  40. return nil
  41. }
  42. // Init initializes the mongodb database
  43. func Init(cfg config.Database) (*MongoDB, error) {
  44. port := cfg.Port
  45. if port <= 0 {
  46. port = 27017
  47. }
  48. session, err := mgo.DialWithInfo(&mgo.DialInfo{
  49. Addrs: []string{fmt.Sprintf("%s:%d", cfg.Host, port)},
  50. Timeout: 30 * time.Second,
  51. Database: cfg.Db,
  52. Username: cfg.Username,
  53. Password: cfg.Password,
  54. Mechanism: cfg.Mechanism,
  55. Source: cfg.Db,
  56. })
  57. if err != nil {
  58. return nil, err
  59. }
  60. db := session.DB(cfg.Db)
  61. characters, err := newCharacterRepository(db)
  62. if err != nil {
  63. session.Close()
  64. return nil, err
  65. }
  66. channels, err := newChannelRepository(db)
  67. if err != nil {
  68. session.Close()
  69. return nil, err
  70. }
  71. changes, err := newChangeRepository(db)
  72. if err != nil {
  73. session.Close()
  74. return nil, err
  75. }
  76. logs, err := newLogRepository(db)
  77. if err != nil {
  78. session.Close()
  79. return nil, err
  80. }
  81. posts, err := newPostRepository(db)
  82. if err != nil {
  83. session.Close()
  84. return nil, err
  85. }
  86. go posts.fixPositions(logs)
  87. return &MongoDB{
  88. session: session,
  89. changes: changes,
  90. characters: characters,
  91. channels: channels,
  92. tags: newTagRepository(db),
  93. logs: logs,
  94. posts: posts,
  95. }, nil
  96. }
  97. type counter struct {
  98. coll *mgo.Collection
  99. category string
  100. name string
  101. }
  102. func newCounter(db *mgo.Database, category, name string) *counter {
  103. return &counter{
  104. coll: db.C("core.counters"),
  105. category: category,
  106. name: name,
  107. }
  108. }
  109. func (c *counter) WithName(name string) *counter {
  110. return &counter{
  111. coll: c.coll,
  112. category: c.category,
  113. name: name,
  114. }
  115. }
  116. func (c *counter) WithCategory(category string) *counter {
  117. return &counter{
  118. coll: c.coll,
  119. category: category,
  120. name: c.name,
  121. }
  122. }
  123. func (c *counter) With(category, name string) *counter {
  124. return &counter{
  125. coll: c.coll,
  126. category: category,
  127. name: name,
  128. }
  129. }
  130. func (c *counter) Increment(amount int) (int, error) {
  131. type counterDoc struct {
  132. ID string `bson:"_id"`
  133. Value int `bson:"value"`
  134. }
  135. id := c.category + "." + c.name
  136. doc := counterDoc{}
  137. _, err := c.coll.Find(bson.M{"_id": id}).Apply(mgo.Change{
  138. Update: bson.M{"$inc": bson.M{"value": amount}},
  139. Upsert: true,
  140. ReturnNew: true,
  141. }, &doc)
  142. if err != nil {
  143. return -1, err
  144. }
  145. return doc.Value, nil
  146. }