Skip to content
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

Change ID Database #4247

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

Change ID Database #4247

wants to merge 5 commits into from

Conversation

Caleb-T-Owens
Copy link
Contributor

No description provided.

@github-actions github-actions bot added the rust Pull requests that update Rust code label Jul 5, 2024
Copy link
Collaborator

@Byron Byron left a comment

Choose a reason for hiding this comment

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

It's great to see sqlite happening :)!

I left a few comments which I hope are helpful.

}

#[cfg(test)]
mod tests {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's have integration tests, that is tests for public APIs go into <crate>/tests/ similar to how it's done in core. It's actually a good check to assure public APIs are actually usable from other crates as well.

const DATABASE_NAME: &str = "project.sqlite";

/// ProjectStore provides a light wrapper around a sqlite database
struct ProjectStore {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since Connection is !Sync, i.e. not Sync, the whole ProjectStore will have to be behind a Mutex to compensate for that.

If Clone is implemented such that it connects to the database without rerunning initialization and migration then it concurrency will be possible nonetheless, and it can be as granular as sqlite can make it.

";

/// Migrator is used to perform migrations on a particular database.
pub(crate) struct Migrator<'l> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

When there is no name used for the lifetime then it's traditionally 'a, which is better for readability and sticking to conventions. Then I for one don't have to wonder if l means link, but be upset because I will never know for sure 😁.

let migrator = Migrator::new(&mut connection);

// Try to find unapplied migrations
migrator.find_applied_migrations().unwrap();
Copy link
Collaborator

Choose a reason for hiding this comment

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

There should probably be an assertion here to assure they are empty.

fn find_applied_migrations_lists_all_entries_in_table() {
let mut connection = Connection::open_in_memory().unwrap();

// Call find_applied_migrations in order to create the migrations table
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd move this comment into an assertion as last argument of assert! for example:

assert!(migrator.find_applied_migrations().unwrap().is_empty(), "nothing happened yet, but creates table as side-effect");

#[test]
/// Testing the `migrate` function.
/// When given a list of migrations to run, it will perform the migrations in order
fn migrate_applies_migrations_in_order() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I recommend to not test find_applied_migrations() as it needs to know a lot of details.
Instead, let migrate() return enough information to know which migrations were applied. That way there can be a 'journey' that does what happens typically, empty database, then the first migration, then the second, with idempotency checks sprinkled in.

Tests that are considered good because they don't panic are an indicator that some more useful information could be returned organically to make what happens more observable.

/// If the migration has already been run, it will be skipped.
/// Run migrations get recorded in the `migrations` table.
/// The `migrations` table will be created if it doesn't exist.
pub(crate) fn migrate(&mut self, migrations: Vec<Migration>) -> Result<()> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

migrations doesn't need to be consumed, and when I read it I wonder why that needs to be consumed. Better not 'lie' and do &[Migration] instead.

))?;

let connection = Connection::open(database_path)?;

Copy link
Collaborator

Choose a reason for hiding this comment

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

This whitespace puzzles me, even though I know that I had a phase where I did that too.

@mtsgrd
Copy link
Contributor

mtsgrd commented Jul 29, 2024

@Caleb-T-Owens do you still intend to work on this pr?

@Caleb-T-Owens
Copy link
Contributor Author

@mtsgrd At some point I think it would be good to introduce a SQL database. When I started we had a product-related reason for doing it (we had data we wanted to associate to commits/changes) but we ended up representing the data differently, so its no longer a priority.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
rust Pull requests that update Rust code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants