Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE d14n_migration_cutover;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
CREATE TABLE d14n_migration_cutover (
id INTEGER PRIMARY KEY CHECK (id = 1),
cutover_ns BIGINT NOT NULL DEFAULT 9223372036854775807,
last_checked_ns BIGINT NOT NULL DEFAULT 0,
has_migrated BOOL NOT NULL DEFAULT FALSE
);

INSERT INTO d14n_migration_cutover (id, cutover_ns, last_checked_ns, has_migrated)
VALUES (1, 9223372036854775807, 0, FALSE);
168 changes: 168 additions & 0 deletions crates/xmtp_db/src/encrypted_store/d14n_migration_cutover.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
use super::{
ConnectionExt,
db_connection::DbConnection,
schema::d14n_migration_cutover::{self, dsl},
};
use crate::StorageError;
use diesel::prelude::*;

#[derive(Identifiable, Insertable, Queryable, AsChangeset, Debug, Clone)]
#[diesel(table_name = d14n_migration_cutover)]
#[diesel(primary_key(id))]
pub struct StoredMigrationCutover {
pub id: i32,
pub cutover_ns: i64,
pub last_checked_ns: i64,
pub has_migrated: bool,
}

impl Default for StoredMigrationCutover {
fn default() -> Self {
Self {
id: 1,
cutover_ns: i64::MAX,
last_checked_ns: 0,
has_migrated: false,
}
}
}

pub trait QueryMigrationCutover {
fn get_migration_cutover(&self) -> Result<StoredMigrationCutover, StorageError>;

fn set_cutover_ns(&self, cutover_ns: i64) -> Result<(), StorageError>;

fn get_last_checked_ns(&self) -> Result<i64, StorageError>;

fn set_last_checked_ns(&self, last_checked_ns: i64) -> Result<(), StorageError>;

fn set_has_migrated(&self, has_migrated: bool) -> Result<(), StorageError>;
}

impl<T: QueryMigrationCutover> QueryMigrationCutover for &T {
fn get_migration_cutover(&self) -> Result<StoredMigrationCutover, StorageError> {
(**self).get_migration_cutover()
}

fn set_cutover_ns(&self, cutover_ns: i64) -> Result<(), StorageError> {
(**self).set_cutover_ns(cutover_ns)
}

fn get_last_checked_ns(&self) -> Result<i64, StorageError> {
(**self).get_last_checked_ns()
}

fn set_last_checked_ns(&self, last_checked_ns: i64) -> Result<(), StorageError> {
(**self).set_last_checked_ns(last_checked_ns)
}

fn set_has_migrated(&self, has_migrated: bool) -> Result<(), StorageError> {
(**self).set_has_migrated(has_migrated)
}
}

impl<C: ConnectionExt> QueryMigrationCutover for DbConnection<C> {
fn get_migration_cutover(&self) -> Result<StoredMigrationCutover, StorageError> {
let result =
self.raw_query_read(|conn| dsl::d14n_migration_cutover.first(conn).optional())?;
Ok(result.unwrap_or_default())
}

fn set_cutover_ns(&self, cutover_ns: i64) -> Result<(), StorageError> {
self.raw_query_write(|conn| {
diesel::update(dsl::d14n_migration_cutover.find(1))
.set(d14n_migration_cutover::cutover_ns.eq(cutover_ns))
.execute(conn)
})?;
Ok(())
}

fn get_last_checked_ns(&self) -> Result<i64, StorageError> {
let cutover = self.get_migration_cutover()?;
Ok(cutover.last_checked_ns)
}

fn set_last_checked_ns(&self, last_checked_ns: i64) -> Result<(), StorageError> {
self.raw_query_write(|conn| {
diesel::update(dsl::d14n_migration_cutover.find(1))
.set(d14n_migration_cutover::last_checked_ns.eq(last_checked_ns))
.execute(conn)
})?;
Ok(())
}

fn set_has_migrated(&self, has_migrated: bool) -> Result<(), StorageError> {
self.raw_query_write(|conn| {
diesel::update(dsl::d14n_migration_cutover.find(1))
.set(d14n_migration_cutover::has_migrated.eq(has_migrated))
.execute(conn)
})?;
Ok(())
}
}

#[cfg(test)]
mod tests {
#[cfg(target_arch = "wasm32")]
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_dedicated_worker);

use super::*;
use crate::test_utils::with_connection;

#[xmtp_common::test]
fn test_default_migration_cutover() {
with_connection(|conn| {
let cutover = conn.get_migration_cutover().unwrap();
assert_eq!(cutover.cutover_ns, i64::MAX);
assert_eq!(cutover.last_checked_ns, 0);
assert!(!cutover.has_migrated);
})
}

#[xmtp_common::test]
fn test_set_cutover_ns() {
with_connection(|conn| {
let timestamp = 1_700_000_000_000_000_000i64;
conn.set_cutover_ns(timestamp).unwrap();

let cutover = conn.get_migration_cutover().unwrap();
assert_eq!(cutover.cutover_ns, timestamp);
assert_eq!(cutover.last_checked_ns, 0);
assert!(!cutover.has_migrated);
})
}

#[xmtp_common::test]
fn test_set_last_checked_ns() {
with_connection(|conn| {
let timestamp = 1_700_000_000_000_000_000i64;
conn.set_last_checked_ns(timestamp).unwrap();

let cutover = conn.get_migration_cutover().unwrap();
assert_eq!(cutover.cutover_ns, i64::MAX);
assert_eq!(cutover.last_checked_ns, timestamp);
assert!(!cutover.has_migrated);
})
}

#[xmtp_common::test]
fn test_get_last_checked_ns() {
with_connection(|conn| {
let timestamp = 1_700_000_000_000_000_000i64;
conn.set_last_checked_ns(timestamp).unwrap();

let last_checked = conn.get_last_checked_ns().unwrap();
assert_eq!(last_checked, timestamp);
})
}

#[xmtp_common::test]
fn test_set_has_migrated() {
with_connection(|conn| {
conn.set_has_migrated(true).unwrap();

let cutover = conn.get_migration_cutover().unwrap();
assert!(cutover.has_migrated);
})
}
}
1 change: 1 addition & 0 deletions crates/xmtp_db/src/encrypted_store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
pub mod association_state;
pub mod consent_record;
pub mod conversation_list;
pub mod d14n_migration_cutover;
pub mod database;
pub mod db_connection;
pub mod group;
Expand Down
10 changes: 10 additions & 0 deletions crates/xmtp_db/src/encrypted_store/schema_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ diesel::table! {
}
}

diesel::table! {
d14n_migration_cutover (id) {
id -> Integer,
cutover_ns -> BigInt,
last_checked_ns -> BigInt,
has_migrated -> Bool,
}
}

diesel::table! {
group_intents (id) {
id -> Integer,
Expand Down Expand Up @@ -263,6 +272,7 @@ diesel::joinable!(message_deletions -> group_messages (id));
diesel::allow_tables_to_appear_in_same_query!(
association_state,
consent_records,
d14n_migration_cutover,
group_intents,
group_messages,
groups,
Expand Down
1 change: 1 addition & 0 deletions crates/xmtp_db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub mod prelude {
pub use super::association_state::QueryAssociationStateCache;
pub use super::consent_record::QueryConsentRecord;
pub use super::conversation_list::QueryConversationList;
pub use super::d14n_migration_cutover::QueryMigrationCutover;
pub use super::group::QueryDms;
pub use super::group::QueryGroup;
pub use super::group::QueryGroupVersion;
Expand Down
12 changes: 12 additions & 0 deletions crates/xmtp_db/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,18 @@ mock! {

fn run_pending_migrations(&self) -> Result<Vec<String>, crate::ConnectionError>;
}
impl crate::d14n_migration_cutover::QueryMigrationCutover for DbQuery {
fn get_migration_cutover(&self) -> Result<crate::d14n_migration_cutover::StoredMigrationCutover, StorageError>;

fn set_cutover_ns(&self, cutover_ns: i64) -> Result<(), StorageError>;

fn get_last_checked_ns(&self) -> Result<i64, StorageError>;

fn set_last_checked_ns(&self, last_checked_ns: i64) -> Result<(), StorageError>;

fn set_has_migrated(&self, has_migrated: bool) -> Result<(), StorageError>;
}

impl crate::message_deletion::QueryMessageDeletion for DbQuery {
fn get_message_deletion(
&self,
Expand Down
3 changes: 3 additions & 0 deletions crates/xmtp_db/src/traits.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::ConnectionExt;
use crate::StorageError;
use crate::association_state::QueryAssociationStateCache;
use crate::d14n_migration_cutover::QueryMigrationCutover;
use crate::icebox::QueryIcebox;
use crate::message_deletion::QueryMessageDeletion;
use crate::pending_remove::QueryPendingRemove;
Expand Down Expand Up @@ -90,6 +91,7 @@ pub trait DbQuery:
+ QueryPendingRemove
+ QueryIcebox
+ QueryMessageDeletion
+ QueryMigrationCutover
+ Pragmas
+ crate::ConnectionExt
{
Expand Down Expand Up @@ -121,6 +123,7 @@ impl<T: ?Sized> DbQuery for T where
+ QueryPendingRemove
+ QueryIcebox
+ QueryMessageDeletion
+ QueryMigrationCutover
+ Pragmas
+ crate::ConnectionExt
{
Expand Down
Loading