123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- package main
- import (
- "fmt"
- "math/rand"
- "net/http"
- "time"
- "github.com/gin-gonic/gin"
- postgres "gorm.io/driver/postgres"
- "gorm.io/gorm"
- )
- // World represents an entry int the World table
- type World struct {
- ID int64 `json:"id"`
- RandomNumber int64 `json:"randomNumber" gorm:"column:randomnumber"`
- }
- // Override GORM convention for table mapping
- // TableName overrides the table name used by User to `profiles`
- func (World) TableName() string {
- return "World"
- }
- // implements the basic logic behind the query tests
- func getWorld(db *gorm.DB) World {
- //we could actually precompute a list of random
- //numbers and slice them but this makes no sense
- //as I expect that this 'random' is just a placeholder
- //for an actual business logic
- randomId := rand.Intn(10000) + 1
- var world World
- db.Take(&world, randomId)
- return world
- }
- // implements the logic behind the updates tests
- func processWorld(tx *gorm.DB) (World, error) {
- //we could actually precompute a list of random
- //numbers and slice them but this makes no sense
- //as I expect that this 'random' is just a placeholder
- //for an actual business logic in a real test
- randomId := rand.Intn(10000) + 1
- randomId2 := int64(rand.Intn(10000) + 1)
- var world World
- tx.Take(&world, randomId)
- world.RandomNumber = randomId2
- err := tx.Save(&world).Error
- return world, err
- }
- func main() {
- /* SETUP DB AND WEB SERVER */
- dsn := "host=tfb-database user=benchmarkdbuser password=benchmarkdbpass dbname=hello_world port=5432 sslmode=disable"
- db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
- PrepareStmt: true, // use prep statements
- })
- if err != nil {
- panic("failed to connect database")
- }
- sqlDB, err := db.DB()
- if err != nil {
- panic("failed to get underlying db conn pooling struct")
- }
- // SetMaxIdleConns sets the maximum number of connections in the idle connection pool.
- sqlDB.SetMaxIdleConns(500)
- r := gin.Default() // use default middleware
- /* START TESTS */
- // JSON TEST
- r.GET("/json", func(c *gin.Context) {
- c.Header("Server", "example")
- c.JSON(200, gin.H{"message": "Hello, World!"})
- })
- // PLAINTEXT TEST
- r.GET("/plaintext", func(c *gin.Context) {
- c.Header("Server", "example")
- c.String(200, "Hello, World!")
- })
- // SINGLE QUERY
- r.GET("/db", func(c *gin.Context) {
- world := getWorld(db)
- c.Header("Server", "example")
- c.JSON(200, world)
- })
- type NumOf struct {
- Queries int `form:"queries"`
- }
- // MULTIPLE QUERIES
- r.GET("/queries", func(c *gin.Context) {
- var numOf NumOf
- if c.ShouldBindQuery(&numOf) != nil { // manage missing query num
- numOf.Queries = 1
- } else if numOf.Queries < 1 { //set at least 1
- numOf.Queries = 1
- } else if numOf.Queries > 500 { //set no more than 500
- numOf.Queries = 500
- }
- worlds := make([]World, numOf.Queries, numOf.Queries) //prealloc
- channel := make(chan World, numOf.Queries)
- for i := 0; i < numOf.Queries; i++ {
- go func() { channel <- getWorld(db) }()
- }
- for i := 0; i < numOf.Queries; i++ {
- worlds[i] = <-channel
- }
- c.Header("Server", "example")
- c.JSON(200, worlds)
- })
- // MULTIPLE UPDATES
- r.GET("/updates", func(c *gin.Context) {
- var numOf NumOf
- if c.ShouldBindQuery(&numOf) != nil { // manage missing query num
- numOf.Queries = 1
- } else if numOf.Queries < 1 { //set at least 1
- numOf.Queries = 1
- } else if numOf.Queries > 500 { //set no more than 500
- numOf.Queries = 500
- }
- worlds := make([]World, numOf.Queries, numOf.Queries) //prealloc
- var err error = nil
- c.Header("Server", "example")
- for i := 0; i < numOf.Queries; i++ {
- worlds[i], err = processWorld(db)
- if err != nil {
- fmt.Println(err)
- c.JSON(500, gin.H{"error": err})
- break
- }
- }
- c.JSON(200, worlds)
- })
- /* START SERVICE */
- s := &http.Server{
- Addr: ":8080",
- Handler: r,
- ReadTimeout: 100000 * time.Second, //increase keepalive
- WriteTimeout: 100000 * time.Second,
- }
- s.ListenAndServe() // listen and serve on 0.0.0.0:8080
- }
|