-
Notifications
You must be signed in to change notification settings - Fork 0
feat(migrations): Adding a support of Flyway #214
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
Changes from all commits
d58d450
93a331e
8fdcb4c
0f428bb
8b73226
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| # EventGate Database | ||
|
|
||
| All database code lives here and is deployed with [Flyway](https://documentation.red-gate.com/flyway). | ||
| The migrations are the single source of truth for the schema, roles, and grants — the | ||
| same migrations build local, CI (integration tests), and real environments. | ||
|
|
||
| ## Layout | ||
|
|
||
| ```text | ||
| flyway.toml # Flyway configuration (locations, baseline, placeholders) — repo root | ||
| database/ | ||
| ├── README.md | ||
| └── migrations/ | ||
| ├── 00_databases.ddl # One-off DB bootstrap (NOT a Flyway migration; no `V` prefix) | ||
| ├── V1.4.0.1__create_roles.ddl # owner / writer / reader roles | ||
| ├── V1.4.0.2__initial_schema.ddl # tables | ||
| └── V1.4.0.3__grants.ddl # ownership + least-privilege grants | ||
| ... | ||
| ``` | ||
|
|
||
| ## Conventions | ||
|
|
||
| - Versioned migrations follow Flyway's `V<major>.<minor>.<patch>.<step>__description.ext` format, | ||
| where `<major>.<minor>.<patch>` tracks the EventGate release the migration ships in and `<step>` | ||
| increments per migration within that release. | ||
| - Extensions carry intent: `.ddl` for structural changes (tables, roles, constraints, indexes), | ||
| `.sql` for DML / data. | ||
|
|
||
| ## Roles | ||
|
|
||
| | Role | Purpose | Used by | | ||
| |--------------------|-----------------------------------------------------|---------------------| | ||
| | master (superuser) | Runs the migrations | Flyway (deployment) | | ||
| | `eventgate_owner` | Owns the schema objects, may run DDL | Migrations | | ||
|
lsulak marked this conversation as resolved.
|
||
| | `eventgate_writer` | `SELECT` / `INSERT` / `UPDATE` on data tables | EventGate Lambda | | ||
| | `eventgate_reader` | `SELECT` only | EventStats Lambda | | ||
|
|
||
| Role passwords are required Flyway placeholders (`eventgate_owner_password`, | ||
| `eventgate_writer_password`, `eventgate_reader_password`). Supply them from secrets in real | ||
| environments. | ||
|
|
||
| ## Local setup | ||
|
|
||
| Requires the Flyway CLI (needs a JDK 17+) and Docker. | ||
|
|
||
| ```zsh | ||
| # 1. Start a local Postgres docker container | ||
| docker run --name=eventgate_db -e POSTGRES_PASSWORD=changeme -e POSTGRES_DB=eventgate_db -p 5432:5432 -d postgres:16 | ||
|
|
||
| # 2. Apply the migrations (run from the repo root, where flyway.toml lives) | ||
| export FLYWAY_PLACEHOLDERS_EVENTGATE_OWNER_PASSWORD=changeme | ||
|
oto-macenauer-absa marked this conversation as resolved.
|
||
| export FLYWAY_PLACEHOLDERS_EVENTGATE_WRITER_PASSWORD=changeme | ||
| export FLYWAY_PLACEHOLDERS_EVENTGATE_READER_PASSWORD=changeme | ||
| flyway migrate | ||
|
|
||
| # Inspect state / clean up | ||
| flyway info | ||
| docker kill eventgate_db && docker rm eventgate_db | ||
| ``` | ||
|
|
||
| ## Adopting an existing database | ||
|
|
||
| On a database that already contains the tables but has no Flyway history (i.e. production), a | ||
| plain `flyway migrate` fails because Flyway sees existing objects it didn't create. The first | ||
| migration against such a database must instead pass baseline flags explicitly, one time only: | ||
|
|
||
| ```zsh | ||
| flyway -baselineOnMigrate=true -baselineVersion=1.4.0.0 migrate | ||
| ``` | ||
|
|
||
| This records a baseline at `1.4.0.0` in `flyway_schema_history` and then applies `V1.4.0.1+` on | ||
| top. | ||
|
|
||
| Before the first production migration: | ||
|
|
||
| 1. Compare the deployed schema with `V1.4.0.2__initial_schema.ddl`. | ||
| 2. Back up the database and cluster roles. | ||
| 3. Confirm the migration account can create roles and change ownership of every EventGate table. | ||
| 4. Run `flyway info`, then the baseline command above with all role-password placeholders supplied from secrets. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| /* | ||
| * Copyright 2026 ABSA Group Limited | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| -- Database bootstrap (NOT a Flyway migration). | ||
| -- | ||
| -- Flyway connects to an existing database, so it cannot create the database it migrates. | ||
| -- This script is intentionally NOT prefixed with `V`, so Flyway ignores it. | ||
|
|
||
| CREATE DATABASE eventgate_db | ||
| WITH | ||
| ENCODING = 'UTF8' | ||
| CONNECTION LIMIT = -1; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| /* | ||
| * Copyright 2026 ABSA Group Limited | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| -- Application database roles. | ||
| -- | ||
| -- eventgate_owner - owns the schema objects and may run DDL. | ||
| -- eventgate_writer - inserts/updates event data (main EventGate Lambda). | ||
| -- eventgate_reader - read-only access (EventStats Lambda). | ||
|
|
||
| DO | ||
| $do$ | ||
| BEGIN | ||
| IF EXISTS ( | ||
| SELECT FROM pg_catalog.pg_roles | ||
| WHERE rolname = 'eventgate_owner') THEN | ||
|
|
||
| RAISE NOTICE 'Role "eventgate_owner" already exists. Skipping.'; | ||
| ELSE | ||
| CREATE ROLE eventgate_owner WITH | ||
| LOGIN | ||
| NOSUPERUSER | ||
| INHERIT | ||
| NOCREATEDB | ||
| NOCREATEROLE | ||
| NOREPLICATION | ||
| PASSWORD '${eventgate_owner_password}'; | ||
| END IF; | ||
| END | ||
| $do$; | ||
|
|
||
| DO | ||
| $do$ | ||
| BEGIN | ||
| IF EXISTS ( | ||
| SELECT FROM pg_catalog.pg_roles | ||
| WHERE rolname = 'eventgate_writer') THEN | ||
| RAISE NOTICE 'Role "eventgate_writer" already exists. Skipping.'; | ||
| ELSE | ||
| CREATE ROLE eventgate_writer WITH | ||
| LOGIN | ||
| NOSUPERUSER | ||
| INHERIT | ||
| NOCREATEDB | ||
| NOCREATEROLE | ||
| NOREPLICATION | ||
| PASSWORD '${eventgate_writer_password}'; | ||
| END IF; | ||
| END | ||
| $do$; | ||
|
|
||
| DO | ||
| $do$ | ||
| BEGIN | ||
| IF EXISTS ( | ||
| SELECT FROM pg_catalog.pg_roles | ||
| WHERE rolname = 'eventgate_reader') THEN | ||
| RAISE NOTICE 'Role "eventgate_reader" already exists. Skipping.'; | ||
| ELSE | ||
| CREATE ROLE eventgate_reader WITH | ||
| LOGIN | ||
| NOSUPERUSER | ||
| INHERIT | ||
| NOCREATEDB | ||
| NOCREATEROLE | ||
| NOREPLICATION | ||
| PASSWORD '${eventgate_reader_password}'; | ||
| END IF; | ||
|
tmikula-dev marked this conversation as resolved.
|
||
| END | ||
| $do$; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,23 +1,21 @@ | ||
| # | ||
| # Copyright 2026 ABSA Group Limited | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
| # | ||
| /* | ||
| * Copyright 2026 ABSA Group Limited | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| """PostgreSQL schema for integration tests.""" | ||
| -- Initial EventGate schema. | ||
|
|
||
| SCHEMA_SQL = """ | ||
| -- Table matching WriterPostgres._postgres_run_write columns | ||
| -- Run header rows for the runs topic. | ||
| CREATE TABLE IF NOT EXISTS public_cps_za_runs ( | ||
| event_id VARCHAR(255) NOT NULL, | ||
| job_ref VARCHAR(255) NOT NULL, | ||
|
|
@@ -29,7 +27,7 @@ | |
| timestamp_end BIGINT | ||
| ); | ||
|
|
||
| -- Table matching WriterPostgres._postgres_run_write job rows | ||
| -- Per-job rows belonging to a run. | ||
| CREATE TABLE IF NOT EXISTS public_cps_za_runs_jobs ( | ||
| internal_id SERIAL PRIMARY KEY, | ||
| event_id VARCHAR(255) NOT NULL, | ||
|
|
@@ -42,7 +40,7 @@ | |
| additional_info JSONB | ||
| ); | ||
|
|
||
| -- Table matching WriterPostgres._postgres_edla_write columns | ||
| -- Data lake change events. | ||
| CREATE TABLE IF NOT EXISTS public_cps_za_dlchange ( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that this topic and thus this table is not really used. I don't even know what its responsibility should be :D I checked DEV and PROD content of these table - empty! If yes, should we clean it here? @oto-macenauer I would appreciate your opinion also, because you might know more than I
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's not used, but as for removing, it's a bit of refactoring, I'd leave it for later (another issue) and maybe discussed it with @yruslan it's part of his ADR
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, that works for me |
||
| event_id VARCHAR(255) NOT NULL, | ||
| tenant_id VARCHAR(255) NOT NULL, | ||
|
|
@@ -59,7 +57,7 @@ | |
| additional_info JSONB | ||
| ); | ||
|
|
||
| -- Table matching WriterPostgres._postgres_test_write columns | ||
| -- Test topic events. | ||
| CREATE TABLE IF NOT EXISTS public_cps_za_test ( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we will have this on UAT and PROD. I think that it was part of PoC but we don't really need it anymore. If we wanna test, we have DEV env. What do you think @oto-macenauer, any idea where/how we could use it and thus keep it here?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The test topic is meant for smoke tests, so whenever deployment happens it should try to put data here in this topic and read it using SQS, that should do for some basic functionality test. I didn't want to pollute PROD tables and queues so that's why I've added these test topics.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Performing smoke tests against PROD in isolated topic can be a good idea, but then part of real, live, production thing, is for tests purposes only. I am not really sure what is the best practice, there are trade-offs involved. What do you think, @miroslavpojer ?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Running Smoke test on PROD is RISKY.
Again:
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree. Let's create a ticket and continue the conversation against such ticket, with this discussion as a reference point to that ticket @tmikula-dev please if you can create it |
||
| event_id VARCHAR(255) NOT NULL, | ||
| tenant_id VARCHAR(255) NOT NULL, | ||
|
|
@@ -69,7 +67,7 @@ | |
| additional_info JSONB | ||
| ); | ||
|
|
||
| -- Table for test_status_change_writer | ||
| -- Aggregated latest status per job (see ADR 001). | ||
| CREATE TABLE IF NOT EXISTS public_cps_za_status_change_aggregated_job ( | ||
| job_id UUID PRIMARY KEY, | ||
| job_group_id UUID, | ||
|
|
@@ -97,4 +95,3 @@ | |
| finished_at TIMESTAMPTZ, | ||
| last_updated_at TIMESTAMPTZ NOT NULL | ||
| ); | ||
| """ | ||
Uh oh!
There was an error while loading. Please reload this page.