Skip to content

[sql-46] trigger kvdb to sql migration using sqldb/v2 #1114

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

Draft
wants to merge 25 commits into
base: master
Choose a base branch
from

Conversation

ViktorTigerstrom
Copy link
Contributor

Based on and blocked by #1113

Implements step 3. of "Phase 3" in #917.

This PR implements the functionality to use sqldb/v2 to trigger the kvdb to sql migration under the dev build-tagged litd builds, using code migrations which sqldb/v2 adds support for. This PR also adds support for having separate dev sql migrations, which are only run under build-tagged litd builds.

Note that this is only a draft PR for now, as the sqldb/v2 is not released, and we therefore need to add forked+local dependencies in order to run this. Once we have an official release of the sqldb/v2 package, I'll update this PR to use that dependency.

We add a helper function to the functions that creates the test SQL
stores, in order to ensure that the store is properly closed when the
test is cleaned up.
In the upcoming migration of the firewall database to SQL, the helper
functions that creates the test databases of different types, need to
return a unified interface in order to not have to control the
migration tests file by build tags. Therefore, we export the unified
interface FirewallDBs, so that it can be returned public test DB
creation functions
In the upcoming migration of the firewall database to SQL, the helper
functions that creates the test databases of different types, need to
return a unified interface in order to not have to control the
migration tests file by build tags. Therefore, we update the
`NewTestDB` functions to return the `FirewallDBs` interface instead of
the specific store implementation type.
During the upcoming upcoming migration of the firewall database to SQL,
we need to be able to check all kvstores records in the SQL database,
to validate that the migration is successful in tests.

This commits adds a query to list all kvstores records, which enables
that functionality.
Rename the session_id to group_id in kvstores table in the SQL store, to
better represent how the field is actually used.

Note that this is a breaking change, and would normally require a new
migration. But as the SQL store is not used in production, and only
enabled under the dev build flag, we can rename it without a new
migration, as there's no users of the SQL store in production.
During the migration of the kvstores to SQL, we'll iterate over the
buckets in the bbolt database, which holds all kvstores records.

In order to understand why the migration iterates over the buckets in
the specific order, we need to clarify the bbolt kvstores illustration
docs, so that it correctly reflects how the records are actually stored
in the bbolt database.
This commit introduces the migration logic for transitioning the
kvstores store from kvdb to SQL.

Note that as of this commit, the migration is not yet triggered by any
production code, i.e. only tests execute the migration logic.
This commit updates litd to use the new sqldb v2 package. Note that this
with just this commit, litd will not utilize the capabilities of sqldb
v2 to run specific post migrations steps (such as migrating the kvdb to
SQL). That functionality will be added in later commits.

Instead, this commit just focuses on adding support for the new
sqldb v2 package, and the functionality of the SQL stores are expected
to remain the same as prior to this commit.
rename `sqlStore` to `store` in the firewalldb sql migration test file,
to make the name shorted. This is done in preparation for future commits
which will lengthen the lines where `sqlStore` is used, which otherwise
would make the lines exceed the 80 character limit.
This commit introduces the `sqlcmig6` package, which at the time of this
commit contains the same queries and models as `sqlc` package.
Importantly though, once the kvdb to sql migration is made available in
production, the `sqlcmig6` package will not change, as it is intended
to represent the sql db as it was at the time of the migration.

The sqlcmig6 package is therefore intended to be used in the kvdb to sql
migration code, as it is will always be compatible with the sql database
when all sql migrations prior to the kvdb to sql migration are applied.

When additional sql migrations are added in the future, they may effect
the `sqlc` package in such a way that the standard `sqlc` queries and
models aren't compatible with kvdb to sql migration code any longer.

By preserving the `sqlcmig6` package, we ensure that the kvdb to sql
migration code can always use the same queries and models that were
available at the time of the migration, even if the `sqlc` package
changes in the future.

Note that the `sqlcmig6` package have not been generated by `sqlc` (the
queries and models are copied from the `sqlc` package), as it is not
intended to be changed in the future.
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary of Changes

Hello @ViktorTigerstrom, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request represents a significant architectural shift, laying the groundwork for litd to transition its data persistence from BoltDB to a SQL backend. By integrating sqldb/v2 and implementing code migrations, it enables the seamless transfer of existing data for key components like accounts, sessions, and firewall rules within dev environments. This change facilitates future development on a more scalable and flexible data layer, while ensuring data integrity during the transition.

Highlights

  • KVDB to SQL Migration: I've implemented the core logic to migrate existing BoltDB (KVDB) data for accounts, sessions, and firewalldb stores to a SQL database. This is a 'code migration' that runs as a post-migration step, ensuring existing data is transferred to the new schema.
  • sqldb/v2 Integration: This PR integrates the new sqldb/v2 library for database management. This includes adopting its robust transaction execution pattern and migration framework across the accounts, session, and firewalldb modules.
  • Separate Dev Migrations: I've introduced a mechanism for dev builds to have their own SQL migration streams. This allows for experimental or in-progress migrations, such as the KVDB to SQL data migration, to be tested and developed without affecting production builds.
  • Database Schema Adaptation: Various database interaction layers, including SQLC generated code, store interfaces, and test helpers, have been updated. This aligns them with the new sqldb/v2 patterns and introduces sqlcmig6 types specifically for handling the migration's intermediate schema.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This is a substantial pull request that migrates the database backend from kvdb to sqldb/v2 and introduces the necessary migration logic. The changes are well-structured, particularly the use of a separate sqlcmig6 package for migration-specific queries and the centralized migration stream handling. I've identified one critical issue that will prevent compilation, and a couple of medium-severity issues related to error message formatting. After addressing these points, the code should be in good shape.

Comment on lines +198 to +207
for i := range len(query) {
if query[i] != '?' {
sb.WriteByte(query[i])
continue
}

sb.WriteString("$")
sb.WriteString(strconv.Itoa(argNum))
argNum++
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The loop for i := range len(query) is not valid Go syntax and will cause a compilation error. range cannot be used on an integer value.

A direct fix is to use a standard C-style for loop: for i := 0; i < len(query); i++.

However, a more idiomatic way to iterate over a string in Go is for _, r := range query, which correctly handles Unicode characters. Since you are using WriteByte, the C-style loop is a safe and direct replacement.

Suggested change
for i := range len(query) {
if query[i] != '?' {
sb.WriteByte(query[i])
continue
}
sb.WriteString("$")
sb.WriteString(strconv.Itoa(argNum))
argNum++
}
for i := 0; i < len(query); i++ {
if query[i] != '?' {
sb.WriteByte(query[i])
continue
}
sb.WriteString("$")
sb.WriteString(strconv.Itoa(argNum))
argNum++
}

Comment on lines +126 to +128
return stores, fmt.Errorf("error applying "+
"migrations to SQLlite store: %w", err,
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This error message contains a typo ("SQLlite" instead of "SQLite") and uses unnecessary string concatenation. It's good practice to keep error messages clear and free of typos for better debuggability.

return stores, fmt.Errorf("error applying migrations to SQLite store: %w", err)

Comment on lines +171 to +173
return stores, fmt.Errorf("error applying "+
"migrations to Postgres store: %w", err,
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This error message uses unnecessary string concatenation. Simplifying it will improve readability.

return stores, fmt.Errorf("error applying migrations to Postgres store: %w", err)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant