-
Notifications
You must be signed in to change notification settings - Fork 4.6k
use postgres / jooq (without code generation) / test containers #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
Conversation
@@ -2,3 +2,4 @@ | |||
.idea | |||
build | |||
.DS_Store | |||
dataline-db/pg_data/* |
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.
what generates that directory?
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.
It's what I'm using as the default mount for the dev docker db. I'm just setting it to an explicit location so it's easy to delete if we want to iterate on db schemas or start from scratch.
.env
Outdated
@@ -1,2 +1,7 @@ | |||
VERSION=0.1.0 | |||
ENV=docker | |||
POSTGRES_VERSION=13-alpine |
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.
we should hardcode this one in compose. We should keep the env for the env varialbes that are read by the code
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.
This should be read by test containers to pull the correct version of the image, so it's consistent with docker compose. I'll add that.
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.
Actually it's hard to set variables used for test in intellij, github, and gradle versions of tests. Maybe that should just be hardcoded in both places.
return connectionPool; | ||
public static BasicDataSource getConnectionPoolFromEnv() { | ||
return getConnectionPool( | ||
System.getenv("POSTGRES_USER"), |
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.
Can we create a class in commons
that serves as a repository for these env variable and provides accessors?
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'll do this separately since I already have some ENV helpers in the scheduling PR.
CREATE TABLE DATALINE_METADATA (id varchar(255), value varchar(255), PRIMARY KEY (id)); | ||
INSERT INTO DATALINE_METADATA VALUES ('server-uuid', ((lower(hex(randomblob(4))) || '-' || lower(hex(randomblob(2))) || '-4' || substr(lower(hex(randomblob(2))),2) || '-' || substr('89ab',abs(random()) % 4 + 1, 1) || substr(lower(hex(randomblob(2))),2) || '-' || lower(hex(randomblob(6)))))); | ||
CREATE TABLE JOBS (id INTEGER PRIMARY KEY AUTOINCREMENT, scope varchar(255), created_at INTEGER, started_at INTEGER, updated_at INTEGER, status INTEGER, config BLOB, output, BLOB, stdout_path varchar(255), stderr_path varchar(255)); | ||
-- extensions |
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.
Clean :D
private static final JdbcDatabaseContainer POSTGRES_CONTAINER; | ||
private static final BasicDataSource CONNECTION_POOL; | ||
|
||
static { |
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.
NIT: can you use @BeforeAll
instead?
|
||
static { | ||
// todo: load image from env and don't hardcode absolute path | ||
POSTGRES_CONTAINER = new PostgreSQLContainer("postgres:13-alpine").withInitScript("schema.sql"); |
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.
really nice!
Are there good practices to ensure that tests run in isolation? It seems that since you instantiate the db once, that content in tables will be shared accross the tests.
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.
What we did in the past was create a single db container and then run tests one at a time, clearing the db in between runs. I'll make a better db test class after merging this PR.
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD} | ||
- POSTGRES_DB=${POSTGRES_DB} | ||
- POSTGRES_CONNECT_STR=${POSTGRES_CONNECT_STR} | ||
- WAIT_HOSTS=db:5432 |
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 assume the depends_on isn't enough? Maybe we can make it work with some sort of a tcp healthcheck defined in the db.
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.
This is basically just a tcp healtcheck. Searching around, it seems like doing something like using one of the wait/wait-for/wait-for-it scripts is the "accepted" method of doing the check. You can do things like setting the value of WAIT_HOSTS
to db:5432,db2:5433
if you have multiple TCP dependencies, for example.
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.
And to answer the other question, yes, depends_on isn't enough. It only waits for the container to start, but the PG server doesn't run until the init script finishes.
You should look at
ServerUuid
for an example of how to use JOOQ for querying. I didn't do codegen so it isn't using the ORM functionality, butResult<Record>
provides a much nicer interface than something likeResultSet
.