Просмотр исходного кода

Add veb, the new V lang framework (#9717)

* Add veb. V lang default framework

* Update Readme, config and so

* set headers with a middleware to reduce code repetition

---------

Co-authored-by: c-cesar <[email protected]>
ccesar 5 месяцев назад
Родитель
Сommit
3c4d632f6e

+ 35 - 0
frameworks/V/veb/README.md

@@ -0,0 +1,35 @@
+# [veb](https://modules.vlang.io/veb.html) Benchmarking Test
+
+Veb is the default V language web framework. This test uses veb and V native ORM.
+
+### Test Type Implementation Source Code
+
+All tests in a 95 lines [main.v] and a html [template](fortunes.html)
+### Database
+
+PostgresQL
+
+## Test URLs
+### JSON
+
+http://localhost:8080/json
+
+### PLAINTEXT
+
+http://localhost:8080/plaintext
+
+### DB
+
+http://localhost:8080/db
+
+### QUERY
+
+http://localhost:8080/query?q=
+
+### UPDATE
+
+http://localhost:8080/update?queries=
+
+### FORTUNES
+
+http://localhost:8080/fortunes

+ 30 - 0
frameworks/V/veb/benchmark_config.json

@@ -0,0 +1,30 @@
+{
+  "framework": "veb",
+  "tests": [
+    {
+      "default": {
+        "json_url": "/json",
+        "plaintext_url": "/plaintext",
+        "db_url": "/db",
+        "query_url": "/queries?q=",
+        "fortune_url": "/fortunes",
+        "update_url": "/update?q=",
+        "port": 8080,
+        "approach": "Realistic",
+        "classification": "Fullstack",
+        "database": "Postgres",
+        "framework": "veb",
+        "language": "V",
+        "flavor": "None",
+        "orm": "Micro",
+        "platform": "None",
+        "webserver": "None",
+        "os": "Linux",
+        "database_os": "Linux",
+        "display_name": "veb",
+        "notes": "",
+        "versus": "None"
+      }
+    }
+  ]
+}

+ 19 - 0
frameworks/V/veb/config.toml

@@ -0,0 +1,19 @@
+[framework]
+name = "veb"
+
+[main]
+urls.plaintext = "/plaintext"
+urls.json = "/json"
+urls.db = "/db"
+urls.query = "/queries?q="
+urls.update = "/update?q="
+urls.fortune = "/fortunes"
+approach = "Realistic"
+classification = "Fullstack"
+database = "Postgres"
+database_os = "Linux"
+os = "Linux"
+orm = "Micro"
+platform = "None"
+webserver = "None"
+versus = "None"

+ 12 - 0
frameworks/V/veb/fortunes.html

@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head><title>Fortunes</title></head>
+<body>
+<table>
+<tr><th>id</th><th>message</th></tr>
+@for m in fortunes
+<tr><td>@m.id</td><td>@m.message</td></tr>
+@end
+</table>
+</body>
+</html>

+ 103 - 0
frameworks/V/veb/main.v

@@ -0,0 +1,103 @@
+import veb
+import time
+import rand
+import db.pg
+
+pub fn (app &App) plaintext(mut ctx Context) veb.Result {
+	s := 'Hello, World!'
+	return ctx.text(s)
+}
+
+pub fn (app &App) json(mut ctx Context) veb.Result {
+	obj := {'message': 'Hello, World!'}
+	return ctx.json(obj)
+}
+
+struct World {
+	id           int @[primary; sql: serial]
+mut:
+	randomnumber int
+}
+
+pub fn (app &App) db(mut ctx Context) veb.Result {
+	r := rand.int_in_range(1, 10000) or { return ctx.text('rand error') }
+	mut world := sql app.db {
+		select from World where id == r
+	} or { return ctx.text('db error') }
+	return ctx.json(world.first())
+}
+
+pub fn (app &App) queries(mut ctx Context) veb.Result {
+	mut q := ctx.query['q'].int()
+	if q < 1 { q = 1 } else if q > 500 { q = 500 }
+	mut world := []World{}
+	for _ in 0..q {
+		r := rand.int_in_range(1, 10000) or { return ctx.text('rand error') }
+		world << sql app.db {
+			select from World where id == r
+		} or { return ctx.text('db error') }
+	}
+	return ctx.json(world)
+}
+
+pub fn (app &App) update(mut ctx Context) veb.Result {
+	mut q := ctx.query['q'].int()
+	if q < 1 { q = 1 } else if q > 500 { q = 500 }
+	mut world := []World{}
+	for _ in 0..q {
+		r := rand.int_in_range(1, 10000) or { return ctx.text('rand error') }
+		world << sql app.db {
+			select from World where id == r
+		} or { return ctx.text('db error') }
+		world.last().randomnumber = rand.int_in_range(1, 10000) or { return ctx.text('rand error') }
+		sql app.db {
+			update World set randomnumber = world.last().randomnumber where id == world.last().id
+		} or { return ctx.text('db error') }
+	}
+	return ctx.json(world)
+}
+
+struct Fortune {
+	id      int @[primary; sql: serial]
+	message string
+}
+
+pub fn (app &App) fortunes(mut ctx Context) veb.Result {
+	mut fortunes := sql app.db {
+		select from Fortune
+	} or { return ctx.text('db error') }
+	fortunes.insert(0, Fortune{id: 0, message: 'Additional fortune added at request time.'})
+	fortunes.sort(a.message < b.message)
+	ctx.content_type = 'text/html; charset=utf-8'
+	return $veb.html()
+}
+
+pub struct Context {
+    veb.Context
+}
+
+pub struct App {
+	veb.Middleware[Context]
+pub mut:
+	db pg.DB
+}
+
+pub fn header(mut ctx Context)  bool {
+	ctx.set_header(.date, time.now().as_utc().custom_format('ddd, DD MMM YYYY HH:MM:ss') + ' GMT')
+	ctx.set_header(.server, 'veb')
+	return true
+}
+
+fn main() {
+	mut app := &App{
+		db: pg.connect(pg.Config{
+			host:     'tfb-database'
+			port:      5432
+			user:     'benchmarkdbuser'
+			password: 'benchmarkdbpass'
+			dbname:   'hello_world'
+		}) !
+	}
+	app.use(handler: header)
+	veb.run[App, Context](mut app,  8080)
+}

+ 7 - 0
frameworks/V/veb/run.sh

@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in $(seq 0 $(nproc)); do
+  taskset -c $i ./main &
+done
+
+wait

+ 9 - 0
frameworks/V/veb/veb.dockerfile

@@ -0,0 +1,9 @@
+FROM thevlang/vlang:debian-dev
+RUN apt update && apt install -y libpq-dev
+
+WORKDIR /app
+COPY ./main.v run.sh fortunes.html ./
+RUN v -prod -cflags '-std=gnu11 -Wall -O3 -march=native -mtune=native -flto' main.v
+
+EXPOSE 8080
+CMD sh run.sh