main.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. package main
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "net/http"
  6. "time"
  7. "github.com/gin-gonic/gin"
  8. postgres "gorm.io/driver/postgres"
  9. "gorm.io/gorm"
  10. )
  11. // World represents an entry int the World table
  12. type World struct {
  13. ID int64 `json:"id"`
  14. RandomNumber int64 `json:"randomNumber" gorm:"column:randomnumber"`
  15. }
  16. // Override GORM convention for table mapping
  17. // TableName overrides the table name used by User to `profiles`
  18. func (World) TableName() string {
  19. return "World"
  20. }
  21. // implements the basic logic behind the query tests
  22. func getWorld(db *gorm.DB) World {
  23. //we could actually precompute a list of random
  24. //numbers and slice them but this makes no sense
  25. //as I expect that this 'random' is just a placeholder
  26. //for an actual business logic
  27. randomId := rand.Intn(10000) + 1
  28. var world World
  29. db.Take(&world, randomId)
  30. return world
  31. }
  32. // implements the logic behind the updates tests
  33. func processWorld(tx *gorm.DB) (World, error) {
  34. //we could actually precompute a list of random
  35. //numbers and slice them but this makes no sense
  36. //as I expect that this 'random' is just a placeholder
  37. //for an actual business logic in a real test
  38. randomId := rand.Intn(10000) + 1
  39. randomId2 := int64(rand.Intn(10000) + 1)
  40. var world World
  41. tx.Take(&world, randomId)
  42. world.RandomNumber = randomId2
  43. err := tx.Save(&world).Error
  44. return world, err
  45. }
  46. func main() {
  47. /* SETUP DB AND WEB SERVER */
  48. dsn := "host=tfb-database user=benchmarkdbuser password=benchmarkdbpass dbname=hello_world port=5432 sslmode=disable"
  49. db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
  50. PrepareStmt: true, // use prep statements
  51. })
  52. if err != nil {
  53. panic("failed to connect database")
  54. }
  55. sqlDB, err := db.DB()
  56. if err != nil {
  57. panic("failed to get underlying db conn pooling struct")
  58. }
  59. // SetMaxIdleConns sets the maximum number of connections in the idle connection pool.
  60. sqlDB.SetMaxIdleConns(500)
  61. r := gin.Default() // use default middleware
  62. /* START TESTS */
  63. // JSON TEST
  64. r.GET("/json", func(c *gin.Context) {
  65. c.Header("Server", "example")
  66. c.JSON(200, gin.H{"message": "Hello, World!"})
  67. })
  68. // PLAINTEXT TEST
  69. r.GET("/plaintext", func(c *gin.Context) {
  70. c.Header("Server", "example")
  71. c.String(200, "Hello, World!")
  72. })
  73. // SINGLE QUERY
  74. r.GET("/db", func(c *gin.Context) {
  75. world := getWorld(db)
  76. c.Header("Server", "example")
  77. c.JSON(200, world)
  78. })
  79. type NumOf struct {
  80. Queries int `form:"queries"`
  81. }
  82. // MULTIPLE QUERIES
  83. r.GET("/queries", func(c *gin.Context) {
  84. var numOf NumOf
  85. if c.ShouldBindQuery(&numOf) != nil { // manage missing query num
  86. numOf.Queries = 1
  87. } else if numOf.Queries < 1 { //set at least 1
  88. numOf.Queries = 1
  89. } else if numOf.Queries > 500 { //set no more than 500
  90. numOf.Queries = 500
  91. }
  92. worlds := make([]World, numOf.Queries, numOf.Queries) //prealloc
  93. channel := make(chan World, numOf.Queries)
  94. for i := 0; i < numOf.Queries; i++ {
  95. go func() { channel <- getWorld(db) }()
  96. }
  97. for i := 0; i < numOf.Queries; i++ {
  98. worlds[i] = <-channel
  99. }
  100. c.Header("Server", "example")
  101. c.JSON(200, worlds)
  102. })
  103. // MULTIPLE UPDATES
  104. r.GET("/updates", func(c *gin.Context) {
  105. var numOf NumOf
  106. if c.ShouldBindQuery(&numOf) != nil { // manage missing query num
  107. numOf.Queries = 1
  108. } else if numOf.Queries < 1 { //set at least 1
  109. numOf.Queries = 1
  110. } else if numOf.Queries > 500 { //set no more than 500
  111. numOf.Queries = 500
  112. }
  113. worlds := make([]World, numOf.Queries, numOf.Queries) //prealloc
  114. var err error = nil
  115. c.Header("Server", "example")
  116. for i := 0; i < numOf.Queries; i++ {
  117. worlds[i], err = processWorld(db)
  118. if err != nil {
  119. fmt.Println(err)
  120. c.JSON(500, gin.H{"error": err})
  121. break
  122. }
  123. }
  124. c.JSON(200, worlds)
  125. })
  126. /* START SERVICE */
  127. s := &http.Server{
  128. Addr: ":8080",
  129. Handler: r,
  130. ReadTimeout: 100000 * time.Second, //increase keepalive
  131. WriteTimeout: 100000 * time.Second,
  132. }
  133. s.ListenAndServe() // listen and serve on 0.0.0.0:8080
  134. }