Skip to content

Commit

Permalink
feat: extend functionality of CreateDatabaseParams
Browse files Browse the repository at this point in the history
* rename CreateViewParams to CreateDatabaseViewParams
* allow creating more than one database views when using CreateDatabaseParams
* get rid of DatabaseSerde in favor of DatabaseData, and include all the views inside it
  • Loading branch information
richardshiue committed Mar 20, 2024
1 parent 7b587db commit 488cf6d
Show file tree
Hide file tree
Showing 24 changed files with 1,117 additions and 1,187 deletions.
321 changes: 213 additions & 108 deletions collab-database/src/database.rs

Large diffs are not rendered by default.

39 changes: 0 additions & 39 deletions collab-database/src/database_serde.rs

This file was deleted.

1 change: 0 additions & 1 deletion collab-database/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,4 @@ pub mod views;
mod macros;
pub mod blocks;
pub mod database_observer;
mod database_serde;
pub mod error;
4 changes: 2 additions & 2 deletions collab-database/src/meta/meta_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ impl MetaMap {
}

/// Set the inline view id
pub fn set_inline_view_with_txn(&self, txn: &mut TransactionMut, view_id: &str) {
pub fn set_inline_view_id_with_txn(&self, txn: &mut TransactionMut, view_id: &str) {
self
.container
.insert_str_with_txn(txn, DATABASE_INLINE_VIEW, view_id);
}

/// Get the inline view id
pub fn get_inline_view_with_txn<T: ReadTxn>(&self, txn: &T) -> Option<String> {
pub fn get_inline_view_id_with_txn<T: ReadTxn>(&self, txn: &T) -> Option<String> {
self.container.get_str_with_txn(txn, DATABASE_INLINE_VIEW)
}
}
Expand Down
39 changes: 22 additions & 17 deletions collab-database/src/rows/row.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl DatabaseRow {
.set_height(row.height)
.set_visibility(row.visibility)
.set_created_at(row.created_at)
.set_last_modified(row.created_at)
.set_last_modified(row.last_modified)
.set_cells(row.cells);
})
.done();
Expand Down Expand Up @@ -259,7 +259,7 @@ pub struct Row {
pub height: i32,
pub visibility: bool,
pub created_at: i64,
pub modified_at: i64,
pub last_modified: i64,
}

pub enum RowMetaKey {
Expand Down Expand Up @@ -294,7 +294,7 @@ impl Row {
height: DEFAULT_ROW_HEIGHT,
visibility: true,
created_at: timestamp,
modified_at: timestamp,
last_modified: timestamp,
}
}

Expand All @@ -305,7 +305,7 @@ impl Row {
height: DEFAULT_ROW_HEIGHT,
visibility: true,
created_at: 0,
modified_at: 0,
last_modified: 0,
}
}

Expand Down Expand Up @@ -512,7 +512,7 @@ pub fn row_from_map_ref<T: ReadTxn>(map_ref: &MapRef, _meta_ref: &MapRef, txn: &
height: height as i32,
visibility,
created_at,
modified_at,
last_modified: modified_at,
})
}

Expand All @@ -524,7 +524,8 @@ pub struct CreateRowParams {
pub visibility: bool,
#[serde(skip)]
pub row_position: OrderObjectPosition,
pub timestamp: i64,
pub created_at: i64,
pub modified_at: i64,
}

pub(crate) struct CreateRowParamsValidator;
Expand All @@ -535,8 +536,12 @@ impl CreateRowParamsValidator {
return Err(DatabaseError::InvalidRowID("row_id is empty"));
}

if params.timestamp == 0 {
params.timestamp = timestamp();
let timestamp = timestamp();
if params.created_at == 0 {
params.created_at = timestamp;
}
if params.modified_at == 0 {
params.modified_at = timestamp;
}

Ok(params)
Expand All @@ -547,24 +552,24 @@ impl Default for CreateRowParams {
fn default() -> Self {
Self {
id: gen_row_id(),
cells: Default::default(),
cells: Cells::default(),
height: 60,
visibility: true,
row_position: OrderObjectPosition::default(),
timestamp: 0,
created_at: 0,
modified_at: 0,
}
}
}

impl CreateRowParams {
pub fn new(id: RowId) -> Self {
let timestamp = timestamp();
Self {
id,
cells: Cells::default(),
height: 60,
visibility: true,
row_position: OrderObjectPosition::default(),
timestamp: timestamp(),
created_at: timestamp,
modified_at: timestamp,
..Default::default()
}
}
}
Expand All @@ -576,8 +581,8 @@ impl From<CreateRowParams> for Row {
cells: params.cells,
height: params.height,
visibility: params.visibility,
created_at: params.timestamp,
modified_at: params.timestamp,
created_at: params.created_at,
last_modified: params.modified_at,
}
}
}
Expand Down
15 changes: 12 additions & 3 deletions collab-database/src/user/db_meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use collab::preclude::{
use std::collections::HashSet;

use crate::database::timestamp;
use crate::views::CreateDatabaseParams;

const DATABASES: &str = "databases";

Expand Down Expand Up @@ -38,12 +39,20 @@ impl DatabaseMetaList {
/// Create a new [DatabaseMeta] for the given database id and view id
/// use [Self::update_database] to attach more views to the existing database.
///
pub fn add_database(&self, database_id: &str, view_ids: Vec<String>) {
pub fn add_database(&self, params: &CreateDatabaseParams) {
self.array_ref.with_transact_mut(|txn| {
// Use HashSet to remove duplicates
let linked_views: HashSet<String> = view_ids.into_iter().collect();
let mut linked_views = HashSet::new();
linked_views.insert(params.inline_view_id.to_string());
linked_views.extend(
params
.views
.iter()
.filter(|view| view.view_id != params.inline_view_id)
.map(|view| view.view_id.clone()),
);
let record = DatabaseMeta {
database_id: database_id.to_string(),
database_id: params.database_id.clone(),
created_at: timestamp(),
linked_views: linked_views.into_iter().collect(),
};
Expand Down
48 changes: 13 additions & 35 deletions collab-database/src/user/user_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ use crate::database_observer::DatabaseNotify;
use crate::error::DatabaseError;

use crate::user::db_meta::{DatabaseMeta, DatabaseMetaList};
use crate::views::{CreateDatabaseParams, CreateViewParams, CreateViewParamsValidator};
use crate::views::{CreateDatabaseParams, CreateDatabaseViewParams, CreateViewParamsValidator};

pub type CollabDocStateByOid = HashMap<String, CollabDocState>;
pub type CollabFuture<T> = Pin<Box<dyn Future<Output = T> + Send + Sync + 'static>>;

/// Use this trait to build a [MutexCollab] for a database object including [Database],
/// [DatabaseView], and [DatabaseRow]. When building a [MutexCollab], the caller can add
/// different [CollabPlugin]s to the [MutexCollab] to support different features.
Expand Down Expand Up @@ -183,6 +184,7 @@ impl WorkspaceDatabase {
Some(database) => Some(database),
}
}

/// Return the database id with the given view id.
/// Multiple views can share the same database.
pub async fn get_database_with_view_id(&self, view_id: &str) -> Option<Arc<MutexDatabase>> {
Expand All @@ -207,7 +209,6 @@ impl WorkspaceDatabase {
params: CreateDatabaseParams,
) -> Result<Arc<MutexDatabase>, DatabaseError> {
debug_assert!(!params.database_id.is_empty());
debug_assert!(!params.view_id.is_empty());

// Create a [Collab] for the given database id.
let collab = self.collab_for_database(&params.database_id, CollabDocState::default());
Expand All @@ -221,41 +222,19 @@ impl WorkspaceDatabase {
};

// Add a new database record.
self
.database_meta_list()
.add_database(&params.database_id, vec![params.view_id.clone()]);
self.database_meta_list().add_database(&params);
let database_id = params.database_id.clone();
// TODO(RS): insert the first view of the database.
let mutex_database = MutexDatabase::new(Database::create_with_inline_view(params, context)?);
let database = Arc::new(mutex_database);
self.databases.lock().put(database_id, database.clone());
Ok(database)
}

pub fn track_database(&self, database_id: &str, database_view_ids: Vec<String>) {
self
.database_meta_list()
.add_database(database_id, database_view_ids);
}

/// Create database with the data duplicated from the given database.
/// The [DatabaseData] contains all the database data. It can be
/// used to restore the database from the backup.
pub fn create_database_with_data(
&self,
data: DatabaseData,
) -> Result<Arc<MutexDatabase>, DatabaseError> {
let DatabaseData { view, fields, rows } = data;
let params = CreateDatabaseParams::from_view(view, fields, rows);
let database = self.create_database(params)?;
Ok(database)
}

/// Create linked view that shares the same data with the inline view's database
/// If the inline view is deleted, the reference view will be deleted too.
pub async fn create_database_linked_view(
&self,
params: CreateViewParams,
params: CreateDatabaseViewParams,
) -> Result<(), DatabaseError> {
let params = CreateViewParamsValidator::validate(params)?;
if let Some(database) = self.get_database(&params.database_id).await {
Expand Down Expand Up @@ -353,19 +332,18 @@ impl WorkspaceDatabase {
&self,
view_id: &str,
) -> Result<Arc<MutexDatabase>, DatabaseError> {
let DatabaseData { view, fields, rows } = self.get_database_duplicated_data(view_id).await?;
let params = CreateDatabaseParams::from_view(view, fields, rows);
let database = self.create_database(params)?;
let database_data = self.get_all_database_data(view_id).await?;

let create_database_params = database_data.to_create_database_params(true);
let database = self.create_database(create_database_params)?;

Ok(database)
}

/// Duplicate the database with the given view id.
pub async fn get_database_duplicated_data(
&self,
view_id: &str,
) -> Result<DatabaseData, DatabaseError> {
/// Duplicate the database with the view_id of any view in the database
pub async fn get_all_database_data(&self, view_id: &str) -> Result<DatabaseData, DatabaseError> {
if let Some(database) = self.get_database_with_view_id(view_id).await {
let data = database.lock().duplicate_database();
let data = database.lock().get_all_database_data();
Ok(data)
} else {
Err(DatabaseError::DatabaseNotExist)
Expand Down
Loading

0 comments on commit 488cf6d

Please sign in to comment.