Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vweb: implement database pool #18010

Merged
merged 5 commits into from
Apr 23, 2023
Merged

Conversation

Casper64
Copy link
Member

@Casper64 Casper64 commented Apr 21, 2023

At this moment it is only possible to have 1 ongoing datbase connection for an entire vweb application. Problems arise when multiple workers need to access that same database connection over multiple threads, see #18006.

This pullrequest adds the option to have a pool of database connections.

Usage

Example with postgres as database.

module main

import vweb
import db.pg

struct App {
	vweb.Context
	db_handle vweb.DatabasePool[pg.DB]
mut:
	db pg.DB
}

fn get_database_connection() pg.DB {
	return pg.connect(user: 'dev', password: 'password', dbname: 'database') or { panic(err) }
}

fn main() {
	pool := vweb.database_pool(handler: get_database_connection, nr_workers: 20)

	vweb.run_at(&App{
		db_handle: pool
	},
		port: 8080
		nr_workers: 20
	)!
}

In this example there are 20 workers and there must be 1 database connection for each worker (thread).

The default nr of workers is the same as for a default app:

[params]
pub struct PoolParams[T] {
	handler    fn () T [required]
	nr_workers int = runtime.nr_jobs()
}

DIfferent databases

The above example configured for mysql:

module main

import vweb
import db.mysql

struct App {
	vweb.Context
	vweb.Controller
	db_handle vweb.DatabasePool[mysql.Connection]
mut:
	db mysql.Connection
}

fn get_database_connection() mysql.Connection {
	mut connection := mysql.Connection{
		// host: ''
		// port: 3306
		username: 'root'
		// password: ''
		dbname: 'mysql'
	}
	connection.connect() or { panic(err) }
	return connection
}

fn main() {
	pool := vweb.database_pool(handler: get_database_connection, nr_workers: 20)

	vweb.run_at(&App{
		db_handle: pool
	},
		port: 8080
		nr_workers: 20
	)!
}

Only the types in the App struct need to be changed and the implementation of the pool handler.

Compatibility

All older vweb applications with a single db connection will still work so no breaking changes.

Performance

Test script run.sh:

#!/bin/bash

sleep 1
wrk -t 4 -c 20 -d10s http://127.0.0.1:8080/ &
wrk -t 4 -c 20 -d10s http://127.0.0.1:8080/other &

Output:

Running 10s test @ http://127.0.0.1:8080/
Running 10s test @ http://127.0.0.1:8080/other
  4 threads and 20 connections
  4 threads and 20 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     3.15ms  642.50us  16.56ms   80.83%
    Req/Sec     0.91k   413.37     1.64k    68.00%
  36058 requests in 10.01s, 3.61MB read
Requests/sec:   3603.88
Transfer/sec:    369.54KB
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     3.14ms  639.29us  12.51ms   81.35%
    Req/Sec     0.96k    36.87     1.08k    76.50%
  38082 requests in 10.01s, 3.81MB read
Requests/sec:   3804.78
Transfer/sec:    390.14KB

Tested on intel i9 12900K with 24 threads (23 workers).

The test was perfomed with this script.
The load is equally distributed in the app averaging at $3604+ 3805 = 7409$ request per second.

@medvednikov
Copy link
Member

Looks good, but the get_connection field doesn't feel right.

db or db_handle?

@einar-hjortdal
Copy link
Contributor

I would love for a database connection pool for MySQL too. Great work

@Casper64
Copy link
Member Author

Done! Updated the field to db_handle and managed for it to work with all databases. Will add the documentation by tomorrow.

@Casper64 Casper64 marked this pull request as ready for review April 22, 2023 17:00
@medvednikov medvednikov merged commit 5f870f4 into vlang:master Apr 23, 2023
@medvednikov
Copy link
Member

Great work!

@Casper64 Casper64 deleted the database_pool branch May 4, 2023 21:25
l1mey112 pushed a commit to l1mey112/v that referenced this pull request Jun 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

vweb RUNTIME ERROR: invalid memory access using database (postgres) and workers
3 participants