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

Migrate sequence numbers #309

Merged
merged 14 commits into from
Sep 25, 2019
Merged

Conversation

Dexterp37
Copy link
Contributor

@Dexterp37 Dexterp37 commented Sep 19, 2019

This PR enables the cross-platform Glean SDK to migrate sequence numbers from glean-ac.

This additionally adds initial test coverage for the migration process.

@Dexterp37 Dexterp37 self-assigned this Sep 19, 2019
@Dexterp37
Copy link
Contributor Author

@travis79 @badboy @mdboom thoughts about the overall design of this?

Copy link
Member

@travis79 travis79 left a comment

Choose a reason for hiding this comment

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

Overall the approach seems like a good one!

Copy link
Member

@badboy badboy left a comment

Choose a reason for hiding this comment

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

(not approving/rejecting for now, I'll do that on the final PR).

Overall I think this is a good approach. Migration is encapsulated and mostly self-contained.
I'd like it to be properly and clearly documented why the migration code exist and it'd be good to not affect other platforms (e.g. iOS).

cfg,
newSequenceNums.first,
newSequenceNums.second,
if (newSequenceNums.first != null) newSequenceNums.first!!.size().toInt() else 0
Copy link
Member

Choose a reason for hiding this comment

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

Can we pull this out into a (then self-documenting) variable with a good name?

seq_num_len
);

let glean = if (&seq_nums).as_ref().ok().is_none() {
Copy link
Member

Choose a reason for hiding this comment

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

That's a mouthful.
Can we swap around the if?

if let Ok(seq_nums) = seq_nums { 
	Glean::with_sequence_numbers(glean_cfg, seq_nums)
} else { 
	Glean::new(...) 
}

glean-core/src/ac_migration/mod.rs Show resolved Hide resolved
) {
let ping_maker = PingMaker::new();

for (store_name_with_suffix, next_seq) in seq_numbers.iter() {
Copy link
Member

Choose a reason for hiding this comment

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

We own seq_numbers, we can iterate and consume it with .into_iter() and save us the &0 below.

// file, You can obtain one at https://mozilla.org/MPL/2.0/.

//! A module containing glean-core code for supporting data migration
//! from glean-ac.
Copy link
Member

Choose a reason for hiding this comment

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

IMO we should document what it migrates and also call out that this is definitely temporary while we transition Glean AC and planned to be removed in 2020

seq.add(glean, next_seq);
}

/// This is pub(super) exclusively for enabling the migration tests.
Copy link
Member

Choose a reason for hiding this comment

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

IMO the first line should still document the method.

I'd also change the string to "This is crate-internal exclusively for enabling the migration tests." or something along the lines.


/**
* A class encapsulating the code used for migrating data from glean-ac
* to glean-core. This class, along all the migration code, should be removed
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* to glean-core. This class, along all the migration code, should be removed
* to glean-core. This class, along with all the migration code, should be removed

@@ -67,7 +67,12 @@ internal interface LibGleanFFI : Library {

// Glean top-level API

fun glean_initialize(cfg: FfiConfiguration): Long
fun glean_initialize(
Copy link
Member

Choose a reason for hiding this comment

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

This will affect iOS. It will need to explicitly pass nil, nil, 0.
Would it make sense to have a duplicate of this method for use by Kotlin instead?

Copy link
Contributor

Choose a reason for hiding this comment

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

Could we have an FFI with this explicitly for migration (e.g. glean_initialize_migration), so it would be clear that we can remove it and revert back to the single argument version for Kotlin once we don't need migration code anymore?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Mh, Good point. Yes, it does.

@@ -67,7 +67,12 @@ internal interface LibGleanFFI : Library {

// Glean top-level API

fun glean_initialize(cfg: FfiConfiguration): Long
fun glean_initialize(
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we have an FFI with this explicitly for migration (e.g. glean_initialize_migration), so it would be clear that we can remove it and revert back to the single argument version for Kotlin once we don't need migration code anymore?

values: RawIntArray,
len: i32,
) -> glean_core::Result<Option<HashMap<String, i32>>> {
unsafe {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we put the unsafe around just the minimal parts that we know require unsafe? For example, I think the first clause here is actually safe, etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think we touched this topic with @badboy a while ago and we agreed on wrapping the whole function there (I've copy pasted it, basically).

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, we opted for wrapping it all.

  • unsafe doesn't disable Rust's safety features, it's just us telling the compiler "trust us, there's some things you can't proof, but devs can"
  • The null check is essential to the safety of what follows.
  • The Result collection is how we guarantee to catch problems that could lead to unsafety.

glean-core/src/ac_migration/mod.rs Show resolved Hide resolved
@@ -298,7 +298,7 @@ mod test {

#[test]
fn test_panicks_if_fails_dir_creation() {
assert!(Database::new("").is_err());
assert!(Database::new("!#\"'@#°ç").is_err());
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we know these characters are invalid on all major platforms? I think ext4 on Linux (Android) probably allows all of these. Maybe include a /? That's sure to fail everywhere, I think.

@@ -142,6 +145,32 @@ impl Glean {
Ok(glean)
}

/// Create and initialize a new Glean object.
///
/// This will create the necessary directories and files in `data_path`.
Copy link
Contributor

Choose a reason for hiding this comment

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

And it clears any existing database, right? That seems potentially surprising and should probably be called out.

This class holds all the functions to perform
data migration from glean-ac to glean-core, on
the Kotlin side.

The initial implementation reads the ac sequence
numbers and allows to mark the client as migrated.

Note: before the migration, glean-ac will need
to land some code to set 'wasMigrated' to false,
always, in case we need to roll back.
rkv currently writes data to `app_dir/glean`. To
make it easier to roll back partial migrations, we
should make it write to `app_dir/glean/db` so that we
can delete that directory before starting a migration
again.
We don't want this function to be used outside of
the Kotlin FFI, as it's only useful in the
glean-ac to glean-core migration.
@Dexterp37 Dexterp37 marked this pull request as ready for review September 24, 2019 09:47
@codecov-io
Copy link

codecov-io commented Sep 24, 2019

Codecov Report

Merging #309 into master will increase coverage by 0.29%.
The diff coverage is 81.25%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master     #309      +/-   ##
============================================
+ Coverage     70.58%   70.87%   +0.29%     
- Complexity      229      244      +15     
============================================
  Files            62       64       +2     
  Lines          3682     3815     +133     
  Branches        559      586      +27     
============================================
+ Hits           2599     2704     +105     
- Misses          667      676       +9     
- Partials        416      435      +19
Impacted Files Coverage Δ Complexity Δ
...n/java/mozilla/telemetry/glean/rust/LibGleanFFI.kt 66.66% <ø> (ø) 0 <0> (ø) ⬇️
glean-core/src/database/mod.rs 78.5% <33.33%> (ø) 0 <0> (ø) ⬇️
glean-core/src/lib.rs 61.45% <44.44%> (-0.84%) 0 <0> (ø)
...oid/src/main/java/mozilla/telemetry/glean/Glean.kt 84.39% <77.77%> (-0.46%) 1 <0> (ø)
glean-core/src/ac_migration/mod.rs 82.22% <82.22%> (ø) 0 <0> (?)
glean-core/src/ping/mod.rs 67.27% <85%> (+0.82%) 0 <0> (ø) ⬇️
...telemetry/glean/acmigration/GleanACDataMigrator.kt 86.95% <86.95%> (ø) 14 <14> (?)
glean-core/src/lib_unit_tests.rs 75.43% <91.66%> (+1.22%) 0 <0> (ø) ⬇️
glean-core/src/error.rs 18.57% <0%> (-5.72%) 0% <0%> (ø)
... and 2 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a39589b...2a73980. Read the comment docs.

Copy link
Member

@badboy badboy left a comment

Choose a reason for hiding this comment

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

Couple of nits left, but I think this is now a solid approach to the migration.

glean-core/ffi/cbindgen.toml Show resolved Hide resolved
values: RawIntArray,
len: i32,
) -> glean_core::Result<Option<HashMap<String, i32>>> {
unsafe {
Copy link
Member

Choose a reason for hiding this comment

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

Yeah, we opted for wrapping it all.

  • unsafe doesn't disable Rust's safety features, it's just us telling the compiler "trust us, there's some things you can't proof, but devs can"
  • The null check is essential to the safety of what follows.
  • The Result collection is how we guarantee to catch problems that could lead to unsafety.

glean-core/src/ac_migration/mod.rs Outdated Show resolved Hide resolved
glean-core/src/database/mod.rs Show resolved Hide resolved
@Dexterp37 Dexterp37 merged commit c43de1b into mozilla:master Sep 25, 2019
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.

5 participants