Skip to content

Commit

Permalink
fix: don't regenerate client id if UpdaterState successfully loaded (#76
Browse files Browse the repository at this point in the history
)

* fix: don't regenerate client id if UpdaterState successfully loaded

* tests, cleanup

* comments
  • Loading branch information
bryanoltman authored Sep 7, 2023
1 parent e14f630 commit 292f978
Showing 1 changed file with 56 additions and 24 deletions.
80 changes: 56 additions & 24 deletions library/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,26 @@ pub struct UpdaterState {
// Add file path or FD so modifying functions can save it to disk?
}

fn is_file_not_found(error: &anyhow::Error) -> bool {
for cause in error.chain() {
if let Some(io_error) = cause.downcast_ref::<std::io::Error>() {
return io_error.kind() == std::io::ErrorKind::NotFound;
}
}
false
}

fn generate_client_id() -> String {
uuid::Uuid::new_v4().to_string()
}

impl UpdaterState {
fn new(cache_dir: PathBuf, release_version: String) -> Self {
/// Creates a new UpdaterState. If client_id is None, a new one will be generated.
fn new(cache_dir: PathBuf, release_version: String, client_id: Option<String>) -> Self {
Self {
cache_dir,
release_version,
client_id: Some(generate_client_id()),
client_id: client_id.or(Some(generate_client_id())),
current_boot_slot_index: None,
next_boot_slot_index: None,
failed_patches: Vec::new(),
Expand All @@ -75,22 +89,7 @@ impl UpdaterState {
pub fn client_id_or_default(&self) -> String {
self.client_id.clone().unwrap_or("".to_string())
}
}

fn is_file_not_found(error: &anyhow::Error) -> bool {
for cause in error.chain() {
if let Some(io_error) = cause.downcast_ref::<std::io::Error>() {
return io_error.kind() == std::io::ErrorKind::NotFound;
}
}
false
}

fn generate_client_id() -> String {
uuid::Uuid::new_v4().to_string()
}

impl UpdaterState {
pub fn is_known_good_patch(&self, patch_number: usize) -> bool {
self.successful_patches.iter().any(|v| v == &patch_number)
}
Expand Down Expand Up @@ -139,8 +138,12 @@ impl UpdaterState {
Ok(state)
}

fn create_new_and_save(cache_dir: &Path, release_version: &str) -> Self {
let state = Self::new(cache_dir.to_owned(), release_version.to_owned());
fn create_new_and_save(
cache_dir: &Path,
release_version: &str,
client_id: Option<String>,
) -> Self {
let state = Self::new(cache_dir.to_owned(), release_version.to_owned(), client_id);
let _ = state.save();
state
}
Expand All @@ -149,25 +152,26 @@ impl UpdaterState {
let load_result = Self::load(cache_dir);
match load_result {
Ok(mut loaded) => {
let maybe_client_id = loaded.client_id.clone();
if loaded.release_version != release_version {
info!(
"release_version changed {} -> {}, clearing updater state",
loaded.release_version, release_version
);
return Self::create_new_and_save(cache_dir, release_version);
return Self::create_new_and_save(cache_dir, release_version, maybe_client_id);
}
let validate_result = loaded.validate();
if let Err(e) = validate_result {
warn!("Error while validating state: {:#}, clearing state.", e);
return Self::create_new_and_save(cache_dir, release_version);
return Self::create_new_and_save(cache_dir, release_version, maybe_client_id);
}
loaded
}
Err(e) => {
if !is_file_not_found(&e) {
warn!("Error loading state: {:#}, clearing state.", e);
}
return Self::create_new_and_save(cache_dir, release_version);
return Self::create_new_and_save(cache_dir, release_version, None);
}
}
}
Expand Down Expand Up @@ -434,7 +438,7 @@ mod tests {

fn test_state(tmp_dir: &TempDir) -> UpdaterState {
let cache_dir = tmp_dir.path();
UpdaterState::new(cache_dir.to_owned(), "1.0.0+1".to_string())
UpdaterState::new(cache_dir.to_owned(), "1.0.0+1".to_string(), None)
}

fn fake_patch(tmp_dir: &TempDir, number: usize) -> super::PatchInfo {
Expand Down Expand Up @@ -548,7 +552,7 @@ mod tests {
#[test]
fn adds_client_id_to_saved_state() {
let tmp_dir = TempDir::new("example").unwrap();
let state: UpdaterState = UpdaterState {
let state = UpdaterState {
cache_dir: tmp_dir.path().to_path_buf(),
release_version: "1.0.0+1".to_string(),
client_id: None,
Expand All @@ -565,4 +569,32 @@ mod tests {
UpdaterState::load_or_new_on_error(&state.cache_dir, &state.release_version);
assert!(loaded_state.client_id.is_some());
}

// A new UpdaterState is created when the release version is changed, but
// the client_id should remain the same.
#[test]
fn client_id_does_not_change_if_release_version_changes() {
let tmp_dir = TempDir::new("example").unwrap();

let original_state = UpdaterState {
cache_dir: tmp_dir.path().to_path_buf(),
release_version: "1.0.0+1".to_string(),
client_id: None,
current_boot_slot_index: None,
next_boot_slot_index: None,
failed_patches: Vec::new(),
successful_patches: Vec::new(),
slots: Vec::new(),
};
let original_loaded = UpdaterState::load_or_new_on_error(
&original_state.cache_dir,
&original_state.release_version,
);

let new_loaded = UpdaterState::load_or_new_on_error(&original_state.cache_dir, "1.0.0+2");

assert!(original_loaded.client_id.is_some());
assert!(new_loaded.client_id.is_some());
assert_eq!(original_loaded.client_id, new_loaded.client_id);
}
}

0 comments on commit 292f978

Please sign in to comment.