mirror of
https://github.com/waku-org/nwaku.git
synced 2025-02-21 03:18:32 +00:00
deploy: 14abdef79677ddc828ff396ece321e05cedfca17
This commit is contained in:
parent
871c7a169d
commit
2c82480d83
@ -246,24 +246,6 @@ suite "Message Store":
|
|||||||
## Cleanup
|
## Cleanup
|
||||||
store.close()
|
store.close()
|
||||||
|
|
||||||
test "migration":
|
|
||||||
let
|
|
||||||
database = SqliteDatabase.init("", inMemory = true)[]
|
|
||||||
store = SqliteStore.init(database)[]
|
|
||||||
defer: store.close()
|
|
||||||
|
|
||||||
template sourceDir: string = currentSourcePath.rsplit(DirSep, 1)[0]
|
|
||||||
let migrationPath = sourceDir
|
|
||||||
|
|
||||||
let res = database.migrate(migrationPath, 10)
|
|
||||||
check:
|
|
||||||
res.isErr == false
|
|
||||||
|
|
||||||
let ver = database.getUserVersion()
|
|
||||||
check:
|
|
||||||
ver.isErr == false
|
|
||||||
ver.value == 10
|
|
||||||
|
|
||||||
# TODO: Move this test case to retention policy test suite
|
# TODO: Move this test case to retention policy test suite
|
||||||
test "number of messages retrieved by getAll is bounded by storeCapacity":
|
test "number of messages retrieved by getAll is bounded by storeCapacity":
|
||||||
let capacity = 10
|
let capacity = 10
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# libtool - Provide generalized library-building support services.
|
# libtool - Provide generalized library-building support services.
|
||||||
# Generated automatically by config.status (libbacktrace) version-unused
|
# Generated automatically by config.status (libbacktrace) version-unused
|
||||||
# Libtool was configured on host fv-az246-52:
|
# Libtool was configured on host fv-az180-768:
|
||||||
# NOTE: Changes made to this file will be lost: look at ltmain.sh.
|
# NOTE: Changes made to this file will be lost: look at ltmain.sh.
|
||||||
#
|
#
|
||||||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
|
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
|
||||||
|
81
waku/v2/node/storage/migration.nim
Normal file
81
waku/v2/node/storage/migration.nim
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
|
||||||
|
import
|
||||||
|
stew/results,
|
||||||
|
chronicles
|
||||||
|
import
|
||||||
|
./sqlite,
|
||||||
|
./migration/migration_types,
|
||||||
|
./migration/migration_utils
|
||||||
|
|
||||||
|
export
|
||||||
|
migration_types,
|
||||||
|
migration_utils
|
||||||
|
|
||||||
|
|
||||||
|
logScope:
|
||||||
|
topics = "storage.migration"
|
||||||
|
|
||||||
|
|
||||||
|
const USER_VERSION* = 7 # increase this when there is an update in the database schema
|
||||||
|
|
||||||
|
|
||||||
|
proc migrate*(db: SqliteDatabase, path: string, targetVersion: int64 = USER_VERSION): DatabaseResult[void] =
|
||||||
|
## Compares the user_version of the db with the targetVersion
|
||||||
|
## runs migration scripts if the user_version is outdated (does not support down migration)
|
||||||
|
## path points to the directory holding the migrations scripts
|
||||||
|
## once the db is updated, it sets the user_version to the tragetVersion
|
||||||
|
|
||||||
|
# read database version
|
||||||
|
let userVersionRes = db.getUserVersion()
|
||||||
|
if userVersionRes.isErr():
|
||||||
|
debug "failed to get user_version", error=userVersionRes.error
|
||||||
|
|
||||||
|
let userVersion = userVersionRes.value
|
||||||
|
|
||||||
|
debug "current database user_version", userVersion=userVersion, targetVersion=targetVersion
|
||||||
|
|
||||||
|
if userVersion == targetVersion:
|
||||||
|
info "database is up to date"
|
||||||
|
return ok()
|
||||||
|
|
||||||
|
info "database user_version outdated. migrating.", userVersion=userVersion, targetVersion=targetVersion
|
||||||
|
|
||||||
|
# fetch migration scripts
|
||||||
|
let migrationScriptsRes = getScripts(path)
|
||||||
|
if migrationScriptsRes.isErr():
|
||||||
|
return err("failed to load migration scripts")
|
||||||
|
|
||||||
|
let migrationScripts = migrationScriptsRes.value
|
||||||
|
|
||||||
|
# filter scripts based on their versions
|
||||||
|
let scriptsRes = migrationScripts.filterScripts(userVersion, targetVersion)
|
||||||
|
if scriptsRes.isErr():
|
||||||
|
return err("failed to filter migration scripts")
|
||||||
|
|
||||||
|
let scripts = scriptsRes.value
|
||||||
|
if scripts.len == 0:
|
||||||
|
return err("no suitable migration scripts")
|
||||||
|
|
||||||
|
trace "migration scripts", scripts=scripts
|
||||||
|
|
||||||
|
|
||||||
|
# Run the migration scripts
|
||||||
|
for script in scripts:
|
||||||
|
|
||||||
|
for query in script.splitScript():
|
||||||
|
debug "executing migration statement", statement=query
|
||||||
|
|
||||||
|
let execRes = db.query(query, NoopRowHandler)
|
||||||
|
if execRes.isErr():
|
||||||
|
error "failed to execute migration statement", statement=query, error=execRes.error
|
||||||
|
return err("failed to execute migration statement")
|
||||||
|
|
||||||
|
debug "migration statement executed succesfully", statement=query
|
||||||
|
|
||||||
|
# Update user_version
|
||||||
|
let res = db.setUserVersion(targetVersion)
|
||||||
|
if res.isErr():
|
||||||
|
return err("failed to set the new user_version")
|
||||||
|
|
||||||
|
debug "database user_version updated", userVersion=targetVersion
|
||||||
|
ok()
|
@ -7,8 +7,6 @@ const MESSAGE_STORE_MIGRATION_PATH* = sourceDir / "migrations_scripts/message"
|
|||||||
const PEER_STORE_MIGRATION_PATH* = sourceDir / "migrations_scripts/peer"
|
const PEER_STORE_MIGRATION_PATH* = sourceDir / "migrations_scripts/peer"
|
||||||
const ALL_STORE_MIGRATION_PATH* = sourceDir / "migrations_scripts"
|
const ALL_STORE_MIGRATION_PATH* = sourceDir / "migrations_scripts"
|
||||||
|
|
||||||
const USER_VERSION* = 7 # increase this when there is an update in the database schema
|
|
||||||
|
|
||||||
type MigrationScriptsResult*[T] = Result[T, string]
|
type MigrationScriptsResult*[T] = Result[T, string]
|
||||||
type
|
type
|
||||||
MigrationScripts* = ref object of RootObj
|
MigrationScripts* = ref object of RootObj
|
||||||
|
@ -9,7 +9,8 @@ import
|
|||||||
export migration_types
|
export migration_types
|
||||||
|
|
||||||
logScope:
|
logScope:
|
||||||
topics = "migration_utils"
|
topics = "storage.migration"
|
||||||
|
|
||||||
|
|
||||||
proc getScripts*(migrationPath: string): MigrationScriptsResult[MigrationScripts] =
|
proc getScripts*(migrationPath: string): MigrationScriptsResult[MigrationScripts] =
|
||||||
## the code in this procedure is an adaptation of https://github.com/status-im/nim-status/blob/21aebe41be03cb6450ea261793b800ed7d3e6cda/nim_status/migrations/sql_generate.nim#L4
|
## the code in this procedure is an adaptation of https://github.com/status-im/nim-status/blob/21aebe41be03cb6450ea261793b800ed7d3e6cda/nim_status/migrations/sql_generate.nim#L4
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
{.push raises: [Defect].}
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
import
|
import
|
||||||
os,
|
std/os,
|
||||||
sqlite3_abi,
|
|
||||||
chronicles,
|
|
||||||
stew/results,
|
stew/results,
|
||||||
migration/migration_utils
|
chronicles,
|
||||||
|
sqlite3_abi
|
||||||
|
|
||||||
# The code in this file is an adaptation of the Sqlite KV Store found in nim-eth.
|
# The code in this file is an adaptation of the Sqlite KV Store found in nim-eth.
|
||||||
# https://github.com/status-im/nim-eth/blob/master/eth/db/kvstore_sqlite3.nim
|
# https://github.com/status-im/nim-eth/blob/master/eth/db/kvstore_sqlite3.nim
|
||||||
#
|
#
|
||||||
@ -323,9 +323,11 @@ proc getUserVersion*(database: SqliteDatabase): DatabaseResult[int64] =
|
|||||||
var version: int64
|
var version: int64
|
||||||
proc handler(s: ptr sqlite3_stmt) =
|
proc handler(s: ptr sqlite3_stmt) =
|
||||||
version = sqlite3_column_int64(s, 0)
|
version = sqlite3_column_int64(s, 0)
|
||||||
|
|
||||||
let res = database.query("PRAGMA user_version;", handler)
|
let res = database.query("PRAGMA user_version;", handler)
|
||||||
if res.isErr:
|
if res.isErr():
|
||||||
return err("failed to get user_version")
|
return err("failed to get user_version")
|
||||||
|
|
||||||
ok(version)
|
ok(version)
|
||||||
|
|
||||||
|
|
||||||
@ -334,73 +336,10 @@ proc setUserVersion*(database: SqliteDatabase, version: int64): DatabaseResult[v
|
|||||||
## some context borrowed from https://www.sqlite.org/pragma.html#pragma_user_version
|
## some context borrowed from https://www.sqlite.org/pragma.html#pragma_user_version
|
||||||
## The user-version is an integer that is available to applications to use however they want.
|
## The user-version is an integer that is available to applications to use however they want.
|
||||||
## SQLite makes no use of the user-version itself
|
## SQLite makes no use of the user-version itself
|
||||||
proc handler(s: ptr sqlite3_stmt) = discard
|
|
||||||
|
|
||||||
let query = "PRAGMA user_version=" & $version & ";"
|
let query = "PRAGMA user_version=" & $version & ";"
|
||||||
let res = database.query(query, handler)
|
let res = database.query(query, NoopRowHandler)
|
||||||
if res.isErr():
|
if res.isErr():
|
||||||
return err("failed to set user_version")
|
return err("failed to set user_version")
|
||||||
|
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
|
|
||||||
proc migrate*(db: SqliteDatabase, path: string, targetVersion: int64 = migration_utils.USER_VERSION): DatabaseResult[bool] =
|
|
||||||
## compares the user_version of the db with the targetVersion
|
|
||||||
## runs migration scripts if the user_version is outdated (does not support down migration)
|
|
||||||
## path points to the directory holding the migrations scripts
|
|
||||||
## once the db is updated, it sets the user_version to the tragetVersion
|
|
||||||
|
|
||||||
# read database version
|
|
||||||
let userVersion = db.getUserVersion()
|
|
||||||
debug "current db user_version", userVersion=userVersion
|
|
||||||
if userVersion.value == targetVersion:
|
|
||||||
# already up to date
|
|
||||||
info "database is up to date"
|
|
||||||
ok(true)
|
|
||||||
|
|
||||||
else:
|
|
||||||
info "database user_version outdated. migrating.", userVersion=userVersion, targetVersion=targetVersion
|
|
||||||
# TODO check for the down migrations i.e., userVersion.value > tragetVersion
|
|
||||||
# fetch migration scripts
|
|
||||||
let migrationScriptsRes = getScripts(path)
|
|
||||||
if migrationScriptsRes.isErr:
|
|
||||||
return err("failed to load migration scripts")
|
|
||||||
let migrationScripts = migrationScriptsRes.value
|
|
||||||
|
|
||||||
# filter scripts based on their versions
|
|
||||||
let scriptsRes = migrationScripts.filterScripts(userVersion.value, targetVersion)
|
|
||||||
if scriptsRes.isErr:
|
|
||||||
return err("failed to filter migration scripts")
|
|
||||||
|
|
||||||
let scripts = scriptsRes.value
|
|
||||||
if (scripts.len == 0):
|
|
||||||
return err("no suitable migration scripts")
|
|
||||||
|
|
||||||
debug "scripts to be run", scripts=scripts
|
|
||||||
|
|
||||||
|
|
||||||
proc handler(s: ptr sqlite3_stmt) =
|
|
||||||
discard
|
|
||||||
|
|
||||||
# run the scripts
|
|
||||||
for script in scripts:
|
|
||||||
debug "script", script=script
|
|
||||||
# a script may contain multiple queries
|
|
||||||
let queries = script.splitScript()
|
|
||||||
# TODO queries of the same script should be executed in an atomic manner
|
|
||||||
for query in queries:
|
|
||||||
let res = db.query(query, handler)
|
|
||||||
if res.isErr:
|
|
||||||
debug "failed to run the query", query=query
|
|
||||||
return err("failed to run the script")
|
|
||||||
else:
|
|
||||||
debug "query is executed", query=query
|
|
||||||
|
|
||||||
|
|
||||||
# bump the user version
|
|
||||||
let res = db.setUserVersion(targetVersion)
|
|
||||||
if res.isErr:
|
|
||||||
return err("failed to set the new user_version")
|
|
||||||
|
|
||||||
debug "user_version is set to", targetVersion=targetVersion
|
|
||||||
ok(true)
|
|
@ -4,7 +4,7 @@ import
|
|||||||
stew/results,
|
stew/results,
|
||||||
chronicles,
|
chronicles,
|
||||||
./storage/sqlite,
|
./storage/sqlite,
|
||||||
./storage/migration/migration_types,
|
./storage/migration,
|
||||||
./config
|
./config
|
||||||
|
|
||||||
logScope:
|
logScope:
|
||||||
@ -15,15 +15,14 @@ proc runMigrations*(sqliteDatabase: SqliteDatabase, conf: WakuNodeConf) =
|
|||||||
# Run migration scripts on persistent storage
|
# Run migration scripts on persistent storage
|
||||||
var migrationPath: string
|
var migrationPath: string
|
||||||
if conf.persistPeers and conf.persistMessages:
|
if conf.persistPeers and conf.persistMessages:
|
||||||
migrationPath = migration_types.ALL_STORE_MIGRATION_PATH
|
migrationPath = ALL_STORE_MIGRATION_PATH
|
||||||
elif conf.persistPeers:
|
elif conf.persistPeers:
|
||||||
migrationPath = migration_types.PEER_STORE_MIGRATION_PATH
|
migrationPath = PEER_STORE_MIGRATION_PATH
|
||||||
elif conf.persistMessages:
|
elif conf.persistMessages:
|
||||||
migrationPath = migration_types.MESSAGE_STORE_MIGRATION_PATH
|
migrationPath = MESSAGE_STORE_MIGRATION_PATH
|
||||||
|
|
||||||
info "running migration ...", migrationPath=migrationPath
|
|
||||||
let migrationResult = sqliteDatabase.migrate(migrationPath)
|
let migrationResult = sqliteDatabase.migrate(migrationPath)
|
||||||
if migrationResult.isErr():
|
if migrationResult.isErr():
|
||||||
warn "migration failed", error=migrationResult.error()
|
warn "migration failed", error=migrationResult.error
|
||||||
else:
|
else:
|
||||||
info "migration is done"
|
info "migration is done"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user