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.

118 lines
2.2 KiB

  1. package mongodb
  2. import (
  3. "fmt"
  4. "github.com/globalsign/mgo/bson"
  5. "time"
  6. "git.aiterp.net/rpdata/api/internal/config"
  7. "git.aiterp.net/rpdata/api/repositories"
  8. "github.com/globalsign/mgo"
  9. )
  10. // Init initializes the mongodb database
  11. func Init(cfg config.Database) (bundle *repositories.Bundle, closeFn func() error, err error) {
  12. port := cfg.Port
  13. if port <= 0 {
  14. port = 27017
  15. }
  16. session, err := mgo.DialWithInfo(&mgo.DialInfo{
  17. Addrs: []string{fmt.Sprintf("%s:%d", cfg.Host, port)},
  18. Timeout: 30 * time.Second,
  19. Database: cfg.Db,
  20. Username: cfg.Username,
  21. Password: cfg.Password,
  22. Mechanism: cfg.Mechanism,
  23. Source: cfg.Db,
  24. })
  25. if err != nil {
  26. return
  27. }
  28. db := session.DB(cfg.Db)
  29. characters, err := newCharacterRepository(db)
  30. if err != nil {
  31. session.Close()
  32. return nil, nil, err
  33. }
  34. changes, err := newChangeRepository(db)
  35. if err != nil {
  36. session.Close()
  37. return nil, nil, err
  38. }
  39. bundle = &repositories.Bundle{
  40. Characters: characters,
  41. Changes: changes,
  42. Tags: newTagRepository(db),
  43. }
  44. closeFn = func() error {
  45. session.Close()
  46. return nil
  47. }
  48. return
  49. }
  50. type counter struct {
  51. coll *mgo.Collection
  52. category string
  53. name string
  54. }
  55. func newCounter(db *mgo.Database, category, name string) *counter {
  56. return &counter{
  57. coll: db.C("core.counters"),
  58. category: category,
  59. name: name,
  60. }
  61. }
  62. func (c *counter) WithName(name string) *counter {
  63. return &counter{
  64. coll: c.coll,
  65. category: c.category,
  66. name: name,
  67. }
  68. }
  69. func (c *counter) WithCategory(category string) *counter {
  70. return &counter{
  71. coll: c.coll,
  72. category: category,
  73. name: c.name,
  74. }
  75. }
  76. func (c *counter) With(category, name string) *counter {
  77. return &counter{
  78. coll: c.coll,
  79. category: category,
  80. name: name,
  81. }
  82. }
  83. func (c *counter) Increment(amount int) (int, error) {
  84. type counterDoc struct {
  85. ID string `bson:"_id"`
  86. Value int `bson:"value"`
  87. }
  88. id := c.category + "." + c.name
  89. doc := counterDoc{}
  90. _, err := c.coll.Find(bson.M{"_id": id}).Apply(mgo.Change{
  91. Update: bson.M{"$inc": bson.M{"value": amount}},
  92. Upsert: true,
  93. ReturnNew: true,
  94. }, &doc)
  95. if err != nil {
  96. return -1, err
  97. }
  98. return doc.Value, nil
  99. }