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.

147 lines
3.2 KiB

  1. package loader
  2. import (
  3. "context"
  4. "errors"
  5. "strings"
  6. "git.aiterp.net/rpdata/api/model/character"
  7. "git.aiterp.net/rpdata/api/models"
  8. "git.aiterp.net/rpdata/api/models/characters"
  9. "github.com/graph-gophers/dataloader"
  10. )
  11. // Character gets a character by key
  12. func (loader *Loader) Character(key, value string) (models.Character, error) {
  13. if !strings.HasPrefix(key, "Character.") {
  14. key = "Character." + key
  15. }
  16. loader.loadPrimed(key)
  17. if loader.loaders[key] == nil {
  18. return models.Character{}, errors.New("unsupported key")
  19. }
  20. thunk := loader.loaders[key].Load(loader.ctx, dataloader.StringKey(value))
  21. res, err := thunk()
  22. if err != nil {
  23. return models.Character{}, err
  24. }
  25. char, ok := res.(models.Character)
  26. if !ok {
  27. return models.Character{}, errors.New("incorrect type")
  28. }
  29. return char, nil
  30. }
  31. // Characters gets characters by key
  32. func (loader *Loader) Characters(key string, values ...string) ([]models.Character, error) {
  33. if !strings.HasPrefix(key, "Character.") {
  34. key = "Character." + key
  35. }
  36. if loader.loaders[key] == nil {
  37. return nil, errors.New("unsupported key")
  38. }
  39. loader.loadPrimed(key)
  40. thunk := loader.loaders[key].LoadMany(loader.ctx, dataloader.NewKeysFromStrings(values))
  41. res, errs := thunk()
  42. for _, err := range errs {
  43. if err != nil && err != ErrNotFound {
  44. return nil, err
  45. }
  46. }
  47. chars := make([]models.Character, len(res))
  48. for i := range res {
  49. char, ok := res[i].(models.Character)
  50. if !ok {
  51. return nil, errors.New("incorrect type")
  52. }
  53. chars[i] = char
  54. }
  55. return chars, nil
  56. }
  57. // PrimeCharacters adds a set of characters to be loaded if, and only if, characters
  58. // are going to be loaded. This will fill up the cache and speed up subsequent dataloader
  59. // runs.
  60. func (loader *Loader) PrimeCharacters(key string, values ...string) {
  61. if !strings.HasPrefix(key, "Character.") {
  62. key = "Character." + key
  63. }
  64. loader.prime(key, values)
  65. }
  66. func characterIDBatch(ctx context.Context, keys dataloader.Keys) []*dataloader.Result {
  67. results := make([]*dataloader.Result, 0, len(keys))
  68. ids := keys.Keys()
  69. characters, err := characters.List(&characters.Filter{IDs: ids})
  70. if err != nil {
  71. for range ids {
  72. results = append(results, &dataloader.Result{Error: err})
  73. }
  74. return results
  75. }
  76. for _, id := range ids {
  77. found := false
  78. for _, character := range characters {
  79. if character.ID == id {
  80. results = append(results, &dataloader.Result{Data: character})
  81. found = true
  82. break
  83. }
  84. }
  85. if !found {
  86. results = append(results, &dataloader.Result{Data: models.Character{}, Error: ErrNotFound})
  87. }
  88. }
  89. return results
  90. }
  91. func characterNickBatch(ctx context.Context, keys dataloader.Keys) []*dataloader.Result {
  92. var results []*dataloader.Result
  93. nicks := keys.Keys()
  94. characters, err := character.ListNicks(nicks...)
  95. if err != nil {
  96. for range nicks {
  97. results = append(results, &dataloader.Result{Error: err})
  98. }
  99. return results
  100. }
  101. for _, nick := range nicks {
  102. found := false
  103. for i := range characters {
  104. if characters[i].HasNick(nick) {
  105. results = append(results, &dataloader.Result{Data: characters[i]})
  106. found = true
  107. break
  108. }
  109. }
  110. if !found {
  111. results = append(results, &dataloader.Result{Data: models.Character{}, Error: err})
  112. }
  113. }
  114. return results
  115. }