servlet.rkt 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #lang racket/base
  2. (require db
  3. racket/list
  4. racket/string
  5. net/url-structs
  6. web-server/dispatch
  7. web-server/http
  8. web-server/servlet-env
  9. "./helpers/response-json.rkt")
  10. (define (plaintext req)
  11. (response
  12. 200 #"OK" (current-seconds) #"text/plain" empty
  13. (λ (out)
  14. (write-bytes #"Hello, World!" out))))
  15. (define (json req)
  16. (response/json (hash 'message "Hello, World!")))
  17. (define (get-a-random-number)
  18. (+ 1 (random 10000)))
  19. (define pgc
  20. (virtual-connection
  21. (λ ()
  22. (postgresql-connect #:database "hello_world"
  23. #:user "benchmarkdbuser"
  24. #:password "benchmarkdbpass"
  25. #:server "tfb-database"))))
  26. (define (get-a-random-record id)
  27. (hash 'id id 'randomNumber (query-maybe-value pgc "select randomnumber from world where id = $1" id)))
  28. (define (db req)
  29. (response/json (get-a-random-record (get-a-random-number))))
  30. (define (ensure-integer-is-between-one-and-five-hundreds n)
  31. (if (number? n)
  32. (if (< n 1)
  33. 1
  34. (if (> n 500)
  35. 500
  36. n))
  37. 1))
  38. (define (extract-number-of-records-to-fetch req)
  39. (let* ([uri (request-uri req)]
  40. [all-parameters (url-query uri)]
  41. [queries-param (assoc 'queries all-parameters)]
  42. [queries (cdr queries-param)])
  43. (ensure-integer-is-between-one-and-five-hundreds (string->number queries))))
  44. (define (get-some-random-integers-between-one-and-ten-thousand n)
  45. (for/list ((i n))
  46. (add1 (get-a-random-number))))
  47. (define (get-some-random-records n)
  48. (let ([ids (get-some-random-integers-between-one-and-ten-thousand n)])
  49. (map (λ (id) (get-a-random-record id)) ids)))
  50. (define (queries req)
  51. (response/json (get-some-random-records (extract-number-of-records-to-fetch req))))
  52. (define (get-all-fortunes)
  53. (query-rows pgc "select id, message from fortune"))
  54. (define (get-all-fortunes-plus-one)
  55. (let* ([records (get-all-fortunes)]
  56. [records-p-one (append records '(#(0 "Additional fortune added at request time.")))])
  57. (sort records-p-one string<? #:key (λ (e)
  58. (vector-ref e 1)))))
  59. (define (fortunes req)
  60. (response/xexpr
  61. #:preamble #"<!DOCTYPE html>"
  62. `(html
  63. (head
  64. (title "Fortunes"))
  65. (body
  66. (table
  67. (tr
  68. (th "id")
  69. (th "message"))
  70. ,@(for/list ([fortune-row (get-all-fortunes-plus-one)])
  71. `(tr
  72. (td ,(format "~v" (vector-ref fortune-row 0)))
  73. (td ,(vector-ref fortune-row 1))))
  74. )))))
  75. (define (get-and-update-some-random-records n)
  76. (let* ([random-records (get-some-random-records n)]
  77. [random-numbers (get-some-random-integers-between-one-and-ten-thousand n)]
  78. [index -1]
  79. [updated-records (map (λ (row)
  80. (set! index (add1 index))
  81. (hash 'id (hash-ref row 'id)
  82. 'randomNumber (list-ref random-numbers index)))
  83. random-records)]
  84. [record-list (map (λ (row)
  85. (list (hash-ref row 'id)
  86. (hash-ref row 'randomNumber)))
  87. updated-records)]
  88. [sql-values (string-join
  89. (map (λ (rec)
  90. (format "(~a, ~a)" (car rec) (car (cdr rec))))
  91. record-list)
  92. ", ")]
  93. [sql-stmt (string-join
  94. `("UPDATE world AS ori SET randomnumber = new.randomnumber FROM (VALUES "
  95. ,sql-values
  96. ") AS new (id, randomnumber) WHERE ori.id = new.id")
  97. "")])
  98. (query-exec pgc sql-stmt)
  99. updated-records))
  100. (define (updates req)
  101. (response/json (get-and-update-some-random-records (extract-number-of-records-to-fetch req))))
  102. (define-values (tfb-dispatch tfb-url)
  103. (dispatch-rules
  104. [("plaintext") #:method "get" plaintext]
  105. [("json") #:method "get" json]
  106. [("db") #:method "get" db]
  107. [("queries") #:method "get" queries]
  108. [("fortunes") #:method "get" fortunes]
  109. [("updates") #:method "get" updates]
  110. [else plaintext]))
  111. (define (start request)
  112. (tfb-dispatch request))
  113. (serve/servlet start
  114. #:command-line? #t
  115. #:launch-browser? #f
  116. #:listen-ip #f
  117. #:port 8080
  118. #:servlet-path "/"
  119. #:servlet-regexp #rx""
  120. #:stateless? #t)