-
Notifications
You must be signed in to change notification settings - Fork 57
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
chore: Postgres migrations #2477
Conversation
This PR may contain changes to database schema of one of the drivers. If you are introducing any changes to the schema, make sure the upgrade from the latest release to this change passes without any errors/issues. Please make sure the label |
You can find the image built from this PR at
Built from e9e35bb |
f230cc4
to
cc6e377
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not familiar with migrations but LGTM.
@@ -498,7 +498,7 @@ proc setupProtocols(node: WakuNode, | |||
|
|||
if conf.store: | |||
# Archive setup | |||
let archiveDriverRes = ArchiveDriver.new(conf.storeMessageDbUrl, | |||
let archiveDriverRes = waitFor ArchiveDriver.new(conf.storeMessageDbUrl, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you can waitFor
in a async proc. That would prevent the runtime from progressing no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can, it just means you are intended to wait till future become avail...
although I'm not pretty sure if it would not be better to wait with timeout?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the comments!
@SionoiS - yes this is feasible. In this case we are blocking because this is a needed condition to be satisfied.
@NagyZoltanPeter - I will submit a separate PR where we apply that great proposal of using withTimeout
@@ -63,17 +64,25 @@ proc new*(T: type ArchiveDriver, | |||
let db = dbRes.get() | |||
|
|||
# SQLite vacuum | |||
let (pageSize, pageCount, freelistCount) = ? db.gatherSqlitePageStats() | |||
let sqliteStatsRes = db.gatherSqlitePageStats() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe .valueOr:
or.isOkOr:
? Same elsewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very good point. I'll submit a separate PR later on
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any need to rollback if a migration step fail?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, very good point! I'd add this in the future as an enhancement
let createMsgRes = await s.createMessageTable() | ||
if createMsgRes.isErr(): | ||
return err("createMsgRes.isErr in init: " & createMsgRes.error) | ||
let execRes = await s.writeConnPool.pgQuery(dropVersionTableQuery()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.isOkOr:
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amaaaazing PR! Thanks so much for it!
Adding some small questions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Without going into the details of the migration, approach generally LGTM. As mentioned elsewhere, I don't think we want to support endless migrations in the compiled code. At some point, migration scripts can be removed from the binary and provided as a standalone, consolidated script for older versions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approve it within mind it will be followed by next step. Left some questions though.
@@ -498,7 +498,7 @@ proc setupProtocols(node: WakuNode, | |||
|
|||
if conf.store: | |||
# Archive setup | |||
let archiveDriverRes = ArchiveDriver.new(conf.storeMessageDbUrl, | |||
let archiveDriverRes = waitFor ArchiveDriver.new(conf.storeMessageDbUrl, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can, it just means you are intended to wait till future become avail...
although I'm not pretty sure if it would not be better to wait with timeout?
id VARCHAR NOT NULL, | ||
messageHash VARCHAR NOT NULL, | ||
storedAt BIGINT NOT NULL, | ||
CONSTRAINT messageIndex PRIMARY KEY (messageHash, storedAt) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this migration I think it is better to add this index later after data inserted its time saving as more efficient to do it once for the db engine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok good point , I will cover that in a separate PR.
b0e3c38
to
4b8d76e
Compare
Description
Adding the needed logic so that we can safely change the Postgres database schema.
The approach is different from the current migration logic in SQLite. In this case, we avoid the use of external resources and instead, use a compiled
consts
that contains the migration scripts.Now I'm setting the current schema version to 1. Notice that this PR includes a migration script aimed at converting the current table into a partitioned table, and this will happen in the upcoming PR, where the partition logic is implemented. Therefore, even though we have the migration script for version 2, we are still at version 1.
Changes
breakIntoStatements
proc inpostgres_driver/migrations.nim
to support handling PL/SQL scripts.How to test
Start node A with
./build/wakunode2 --config-file=cfg_node_a.txt
cfg_node_a.txt
In a separate terminal, start a Postgres database locally, with
docker compose -f postgres-docker-compose.yml up
:Content of postgres-docker-compose.yml:
Notice that the following lines might not be needed. I cannot push the files. You can use the default settings:
- ./postgres_cfg/postgresql.conf:/etc/postgresql/postgresql.conf
- ./postgres_cfg/db.sql:/docker-entrypoint-initdb.d/db.sql
Start node B with
./build/wakunode2 --config-file=cfg_node_b.txt
cfg_node_b.txt
Publish a few messages during some time with
bash msg_publisher.sh
Being
msg_publisher.sh
:waku/waku_archive/driver/postgres_driver/migrations.nim
wakunode2
and run B again.messages
table is a partitioned table and it exists a partition that contains all the messages stored in the previous rawmessages
table.Issue
closes #2249