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.

112 lines
3.0 KiB

  1. package main
  2. import (
  3. "context"
  4. "fmt"
  5. "git.aiterp.net/rpdata/api/database"
  6. "git.aiterp.net/rpdata/api/graph2"
  7. "git.aiterp.net/rpdata/api/internal/config"
  8. "git.aiterp.net/rpdata/api/internal/instrumentation"
  9. "git.aiterp.net/rpdata/api/models"
  10. "git.aiterp.net/rpdata/api/services"
  11. "git.aiterp.net/rpdata/api/space"
  12. "github.com/99designs/gqlgen/handler"
  13. "github.com/prometheus/client_golang/prometheus/promhttp"
  14. "log"
  15. "net/http"
  16. "runtime/debug"
  17. )
  18. func main() {
  19. cfg := config.Global()
  20. db, err := database.Init(cfg.Database)
  21. if err != nil {
  22. log.Fatalln("Failed to init db:", err)
  23. }
  24. defer db.Close(context.Background())
  25. var spaceClient *space.Client
  26. if cfg.Space.Enabled {
  27. spaceClient, err = space.Connect(cfg.Space)
  28. if err != nil {
  29. log.Fatalln("Failed to init space:", err)
  30. }
  31. log.Println("Space loaded")
  32. } else {
  33. log.Println("Space is disabled, file upload will not work!")
  34. }
  35. serviceBundle := services.NewBundle(db, spaceClient)
  36. instrumentation.Register()
  37. http.Handle("/", handler.Playground("RPData API", "/graphql"))
  38. http.Handle("/graphql", queryHandler(serviceBundle))
  39. http.Handle("/metrics", promhttp.Handler())
  40. go func() {
  41. err := serviceBundle.Logs.RefreshAllLogCharacters(context.Background())
  42. if err != nil {
  43. log.Println("Refresh Characters:", err)
  44. }
  45. }()
  46. go logListedChanges(serviceBundle.Changes)
  47. log.Fatal(http.ListenAndServe(":8081", nil))
  48. }
  49. func logListedChanges(changes *services.ChangeService) {
  50. sub := changes.Subscribe(context.Background(), models.ChangeFilter{})
  51. for change := range sub {
  52. log.Printf("Change: Author=%#+v Model=%#+v Op=%#+v", change.Author, change.Model, change.Op)
  53. for _, object := range change.Objects() {
  54. switch object := object.(type) {
  55. case models.Log:
  56. log.Printf("\tLog: %s (%s)", object.ID, object.ShortID)
  57. case models.Character:
  58. log.Printf("\tCharacter: %s", object.ID)
  59. case models.Channel:
  60. log.Printf("\tChannel: %s", object.Name)
  61. case models.Post:
  62. log.Printf("\tPost: %s", object.ID)
  63. case models.Story:
  64. log.Printf("\tStory: %s", object.ID)
  65. case models.Tag:
  66. log.Printf("\tTag: (%s,%s)", object.Kind, object.Name)
  67. case models.Chapter:
  68. log.Printf("\tChapter: %s", object.ID)
  69. case models.Comment:
  70. log.Printf("\tComment: %s", object.ID)
  71. }
  72. }
  73. }
  74. log.Println("Change subscription closed.")
  75. }
  76. func queryHandler(services *services.Bundle) http.HandlerFunc {
  77. handler := handler.GraphQL(
  78. graph2.New(services),
  79. handler.UploadMaxSize(10485760),
  80. handler.UploadMaxMemory(1048576),
  81. handler.RecoverFunc(func(ctx context.Context, err interface{}) error {
  82. log.Println(err)
  83. log.Println(string(debug.Stack()))
  84. return fmt.Errorf("The server failed to serve your request due to an internal error, it has been logged")
  85. }),
  86. handler.ComplexityLimit(300),
  87. handler.RequestMiddleware(instrumentation.RequestMiddleware()),
  88. handler.ResolverMiddleware(instrumentation.ResolverMiddleware()),
  89. )
  90. return func(w http.ResponseWriter, r *http.Request) {
  91. r = services.Auth.RequestWithToken(r)
  92. handler.ServeHTTP(w, r)
  93. }
  94. }