Fix database is locked error 99/188399/13
authorAlexander Mazuruk <a.mazuruk@samsung.com>
Tue, 4 Sep 2018 11:56:26 +0000 (13:56 +0200)
committerPawel Wieczorek <p.wieczorek2@samsung.com>
Mon, 1 Oct 2018 14:34:24 +0000 (16:34 +0200)
Bug:
1. Create quickly around 10-30 job requests (same .yml can be used)
2. List Weles jobs after few seconds.
3. Some of the jobs should have following:
 "info": "Internal Weles error while creating file path in ArtifactDB : database is locked",

When Weles received requests in quick succession it tried to write to
database in more than 1 goroutine. This resulted in "database is locked"
error. This should be resolved by handling this error or customizing
sqlite3 settings.

The issue is described in the following thread:
https://github.com/mattn/go-sqlite3/issues/274

This commit:
- adds logging of artifact insert failure
- sets _BUSY_TIMEOUT of sqlite3 to 5s
- limits max No of open db connections to 1
- fixes tests which failed inconsistently in CI

Verification:
Build Weles with this commit, go through steps below "Bug:". Jobs should
not fail due to "database is locked"

Change-Id: I45dd00e832df0cb234d49b219ad736c37a4be629
Signed-off-by: Alexander Mazuruk <a.mazuruk@samsung.com>
artifacts/database/database.go

index 3b817f7..82a9184 100644 (file)
@@ -37,13 +37,19 @@ type ArtifactDB struct {
        dbmap   *gorp.DbMap
 }
 
+const (
+       sqlite3BusyTimeout = "?_busy_timeout=5000"
+       sqlite3MaxOpenConn = 1
+)
+
 // Open opens database connection.
 func (aDB *ArtifactDB) Open(dbPath string) error {
        var err error
-       aDB.handler, err = sql.Open("sqlite3", dbPath)
+       aDB.handler, err = sql.Open("sqlite3", dbPath+sqlite3BusyTimeout)
        if err != nil {
                return errors.New(dbOpenFail + err.Error())
        }
+       aDB.handler.SetMaxOpenConns(sqlite3MaxOpenConn)
 
        aDB.dbmap = &gorp.DbMap{Db: aDB.handler, Dialect: gorp.SqliteDialect{}}
        return aDB.initDB()
@@ -63,8 +69,12 @@ func (aDB *ArtifactDB) Close() error {
 }
 
 // InsertArtifactInfo inserts information about artifact to database.
-func (aDB *ArtifactDB) InsertArtifactInfo(ai *weles.ArtifactInfo) error {
-       return aDB.dbmap.Insert(ai)
+func (aDB *ArtifactDB) InsertArtifactInfo(ai *weles.ArtifactInfo) (err error) {
+       err = aDB.dbmap.Insert(ai)
+       if err != nil {
+               log.Println("Failed to insert ArtifactInfo: ", err)
+       }
+       return
 }
 
 // SelectPath selects artifact from database based on its path.