Skip to content

Instantly share code, notes, and snippets.

@mashingan
Created March 26, 2019 09:20
Show Gist options
  • Save mashingan/247ac80f163ea10b9ef02319aaa09bd0 to your computer and use it in GitHub Desktop.
Save mashingan/247ac80f163ea10b9ef02319aaa09bd0 to your computer and use it in GitHub Desktop.
package main
import (
"database/sql"
"fmt"
"log"
"math/rand"
"sync"
"sync/atomic"
"time"
_ "github.com/mattn/go-sqlite3"
)
const gorout int = 10000
func sqliteLogger(message string, errcount *uint64, wg *sync.WaitGroup, p conns) {
defer wg.Done()
atomic.AddUint64(errcount, 1)
c := p.Conn()
p.Inc()
c.Mutex.Lock()
_, err := c.DB.Exec(`insert into logging(message) values(?);`, message)
c.Mutex.Unlock()
if err != nil {
log.Println(err)
}
}
func runner(r *rand.Rand, iter int, tehchan chan int, errcount *uint64,
wg *sync.WaitGroup,
p conns,
) {
go func(r *rand.Rand, iter int, tehchan chan int) {
somerand := r.Float64()
if somerand < 0.5 {
wg.Add(1)
go sqliteLogger(
fmt.Sprintf("Some error happened with: %f and iter: %d",
somerand, iter),
errcount, wg, p)
}
tehchan <- iter
}(r, iter, tehchan)
}
type conn struct {
*sql.DB
*sync.Mutex
}
type conns struct {
cs []*conn
count uint64
}
func (cs conns) Inc() {
atomic.AddUint64(&cs.count, 1)
}
func (cs conns) Conn() *conn {
return cs.cs[cs.count%uint64(len(cs.cs))]
}
func (c *conn) Close() error {
return c.DB.Close()
}
func openDb() *sql.DB {
db, err := sql.Open("sqlite3", "./log_with_sqlite.db")
if err != nil {
log.Println("Fatal:", err)
return nil
}
_, err = db.Exec("CREATE TABLE IF NOT EXISTS logging(message text);")
return db
}
func dbPool() conns {
dbsCount := 4
//connection := make(conns, dbsCount)
connection := conns{}
connection.count = 0
connection.cs = make([]*conn, dbsCount)
for i := 0; i < dbsCount; i++ {
connection.cs[i] = &conn{openDb(), &sync.Mutex{}}
}
return connection
}
func poolClose(p conns) {
for _, c := range p.cs {
c.DB.Close()
}
}
func main() {
pool := dbPool()
defer poolClose(pool)
var errcount uint64 = 0
var wg sync.WaitGroup
random := rand.New(rand.NewSource(time.Now().Unix()))
logchan := make(chan int, 100)
fmt.Println("starting goroutine")
start := time.Now()
for i := 0; i < gorout; i++ {
runner(random, i, logchan, &errcount, &wg, pool)
}
fmt.Println("end loop goroutine")
fmt.Println("Waiting sync")
count := 0
theloop:
for {
select {
case _, ok := <-logchan:
if !ok {
break theloop
}
count++
case <-time.Tick(500 * time.Millisecond):
fmt.Println("Ending at count:", count)
break theloop
}
}
fmt.Println("Ended")
wg.Wait()
elapsed := time.Now().Sub(start)
fmt.Printf("Total wait is: %v\n", elapsed)
fmt.Println("Error count is:", errcount)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment