/persistence/sql_init.go

https://github.com/fnproject/flow · Go · 120 lines · 96 code · 20 blank · 4 comment · 14 complexity · e3e33d989534f49cc4d9583427cc548c MD5 · raw file

  1. package persistence
  2. import (
  3. "database/sql"
  4. "fmt"
  5. "net/url"
  6. "os"
  7. "path/filepath"
  8. "strings"
  9. "github.com/jmoiron/sqlx"
  10. "github.com/sirupsen/logrus"
  11. // this is pulled in to ensure we have mysql Drivers for DB/DBX
  12. _ "github.com/go-sql-driver/mysql"
  13. )
  14. var tables = map[string][]string{
  15. "sqlite3": {
  16. `CREATE TABLE IF NOT EXISTS events (
  17. actor_name varchar(255) NOT NULL,
  18. event_type varchar(255) NOT NULL,
  19. event_index int NOT NULL,
  20. event BLOB NOT NULL);`,
  21. `CREATE INDEX IF NOT EXISTS actors ON events (actor_name);`,
  22. `CREATE TABLE IF NOT EXISTS snapshots (
  23. actor_name varchar(255) NOT NULL PRIMARY KEY ,
  24. snapshot_type varchar(255) NOT NULL,
  25. event_index int NOT NULL,
  26. snapshot BLOB NOT NULL);`,
  27. `CREATE TABLE IF NOT EXISTS blobs (
  28. prefix varchar(255) NOT NULL,
  29. blob_id varchar(255) NOT NULL PRIMARY KEY ,
  30. blob_data BLOB);`,
  31. },
  32. "mysql": {
  33. `CREATE TABLE IF NOT EXISTS events (
  34. actor_name varchar(255) NOT NULL,
  35. event_type varchar(255) NOT NULL,
  36. event_index int NOT NULL,
  37. event BLOB NOT NULL,
  38. INDEX actors (actor_name));`,
  39. `CREATE TABLE IF NOT EXISTS snapshots (
  40. actor_name varchar(255) NOT NULL PRIMARY KEY ,
  41. snapshot_type varchar(255) NOT NULL,
  42. event_index int NOT NULL,
  43. snapshot BLOB NOT NULL);`,
  44. `CREATE TABLE IF NOT EXISTS blobs (
  45. prefix varchar(255) NOT NULL,
  46. blob_id varchar(255) NOT NULL PRIMARY KEY ,
  47. blob_data BLOB);`,
  48. },
  49. }
  50. // CreateDBConnection sets up a DB connection and ensures required tables exist
  51. func CreateDBConnection(url *url.URL) (*sqlx.DB, error) {
  52. driver := url.Scheme
  53. switch driver {
  54. case "mysql", "sqlite3":
  55. default:
  56. return nil, fmt.Errorf("Invalid db driver %s", driver)
  57. }
  58. if driver == "sqlite3" {
  59. dir := filepath.Dir(url.Path)
  60. err := os.MkdirAll(dir, 0755)
  61. if err != nil {
  62. return nil, err
  63. }
  64. }
  65. var uri = url.String()
  66. uri = strings.TrimPrefix(url.String(), url.Scheme+"://")
  67. sqldb, err := sql.Open(driver, uri)
  68. if err != nil {
  69. logrus.WithFields(logrus.Fields{"url": uri}).WithError(err).Error("couldn't open db")
  70. return nil, err
  71. }
  72. sqlxDb := sqlx.NewDb(sqldb, driver)
  73. err = sqlxDb.Ping()
  74. if err != nil {
  75. logrus.WithFields(logrus.Fields{"url": uri}).WithError(err).Error("couldn't ping db")
  76. return nil, err
  77. }
  78. maxIdleConns := 10 // TODO we need to strip this out of the URL probably
  79. switch driver {
  80. case "sqlite3":
  81. sqlxDb.SetMaxIdleConns(1)
  82. sqlxDb.SetMaxOpenConns(1)
  83. case "mysql":
  84. sqlxDb.SetMaxIdleConns(maxIdleConns)
  85. sqlxDb.SetMaxOpenConns(5 * maxIdleConns)
  86. // setting the lifetime seems to result in driver bad connection errors
  87. // sqlxDb.SetConnMaxLifetime(1 * time.Minute)
  88. }
  89. statements, ok := tables[driver]
  90. if !ok {
  91. return nil, fmt.Errorf("No initialisation sequence known for %s", driver)
  92. }
  93. for _, v := range statements {
  94. _, err = sqlxDb.Exec(v)
  95. if err != nil {
  96. return nil, fmt.Errorf("Failed to create database table %s: %v", v, err)
  97. }
  98. }
  99. return sqlxDb, nil
  100. }