Skip to content

Commit

Permalink
refactor: use array of models for keysclause
Browse files Browse the repository at this point in the history
  • Loading branch information
Larkooo committed Jun 27, 2024
1 parent fc9de16 commit 48c9c2e
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 90 deletions.
2 changes: 1 addition & 1 deletion crates/torii/grpc/proto/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ message EntityKeysClause {
message KeysClause {
repeated bytes keys = 1;
PatternMatching pattern_matching = 2;
optional string model = 3;
repeated string models = 3;
}

message HashedKeysClause {
Expand Down
93 changes: 53 additions & 40 deletions crates/torii/grpc/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ impl DojoWorld {
arrays_rows.insert(name, rows);
}

entities.push(Self::map_row_to_entity(&row, &arrays_rows, &schemas)?);
entities.push(map_row_to_entity(&row, &arrays_rows, &schemas)?);

Check warning on line 289 in crates/torii/grpc/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/grpc/src/server/mod.rs#L289

Added line #L289 was not covered by tests
}

Ok((entities, total_count))
Expand Down Expand Up @@ -327,19 +327,27 @@ impl DojoWorld {
FROM {table}
{}
"#,
if let Some(model) = &keys_clause.model {
if !keys_clause.models.is_empty() {
let model_ids = keys_clause
.models
.iter()
.map(|model| get_selector_from_name(model).map_err(ParseError::NonAsciiName))
.collect::<Result<Vec<_>, _>>()?;
let model_ids_str =
model_ids.iter().map(|id| format!("'{:#x}'", id)).collect::<Vec<_>>().join(",");
format!(
r#"
JOIN {model_relation_table} ON {table}.id = {model_relation_table}.entity_id
WHERE {model_relation_table}.model_id = '{:#x}' AND {table}.keys REGEXP ?
"#,
get_selector_from_name(model).map_err(ParseError::NonAsciiName)?
JOIN {model_relation_table} ON {table}.id = {model_relation_table}.entity_id
WHERE {model_relation_table}.model_id IN ({})
AND {table}.keys REGEXP ?
"#,
model_ids_str
)

Check warning on line 345 in crates/torii/grpc/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/grpc/src/server/mod.rs#L331-L345

Added lines #L331 - L345 were not covered by tests
} else {
format!(
r#"
WHERE {table}.keys REGEXP ?
"#
WHERE {table}.keys REGEXP ?
"#
)
}
);
Expand All @@ -358,19 +366,29 @@ impl DojoWorld {
JOIN {model_relation_table} ON {table}.id = {model_relation_table}.entity_id
WHERE {table}.keys REGEXP ?
GROUP BY {table}.id
ORDER BY {table}.event_id DESC
"#
);

if let Some(model) = &keys_clause.model {
if !keys_clause.models.is_empty() {
// filter by models
models_query += &format!(
r#"
HAVING INSTR(model_ids, '{:#x}') > 0
"#,
get_selector_from_name(model).map_err(ParseError::NonAsciiName)?
"HAVING {}",
keys_clause
.models
.iter()
.map(|model| {
let model_id =
get_selector_from_name(model).map_err(ParseError::NonAsciiName)?;
Ok(format!("INSTR(model_ids, '{:#x}') > 0", model_id))
})
.collect::<Result<Vec<_>, Error>>()?
.join(" OR ")
.as_str()

Check warning on line 386 in crates/torii/grpc/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/grpc/src/server/mod.rs#L374-L386

Added lines #L374 - L386 were not covered by tests
);
}

models_query += &format!(" ORDER BY {table}.event_id DESC");

if limit.is_some() {
models_query += " LIMIT ?";
}
Expand Down Expand Up @@ -405,7 +423,7 @@ impl DojoWorld {
arrays_rows.insert(name, rows);

Check warning on line 423 in crates/torii/grpc/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/grpc/src/server/mod.rs#L422-L423

Added lines #L422 - L423 were not covered by tests
}

entities.push(Self::map_row_to_entity(&row, &arrays_rows, &schemas)?);
entities.push(map_row_to_entity(&row, &arrays_rows, &schemas)?);
}

Ok((entities, total_count))
Expand Down Expand Up @@ -531,7 +549,7 @@ impl DojoWorld {

let entities_collection = db_entities
.iter()
.map(|row| Self::map_row_to_entity(row, &arrays_rows, &schemas))
.map(|row| map_row_to_entity(row, &arrays_rows, &schemas))

Check warning on line 552 in crates/torii/grpc/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/grpc/src/server/mod.rs#L552

Added line #L552 was not covered by tests
.collect::<Result<Vec<_>, Error>>()?;
// Since there is not limit and offset, total_count is same as number of entities
let total_count = entities_collection.len() as u32;
Expand Down Expand Up @@ -780,30 +798,6 @@ impl DojoWorld {
) -> Result<Receiver<Result<proto::world::SubscribeEventsResponse, tonic::Status>>, Error> {
self.event_manager.add_subscriber(clause.try_into().unwrap()).await

Check warning on line 799 in crates/torii/grpc/src/server/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/grpc/src/server/mod.rs#L799

Added line #L799 was not covered by tests
}

fn map_row_to_entity(
row: &SqliteRow,
arrays_rows: &HashMap<String, Vec<SqliteRow>>,
schemas: &[Ty],
) -> Result<proto::types::Entity, Error> {
let hashed_keys =
FieldElement::from_str(&row.get::<String, _>("id")).map_err(ParseError::FromStr)?;
let models = schemas
.iter()
.map(|schema| {
let mut schema = schema.to_owned();
map_row_to_ty("", &schema.name(), &mut schema, row, arrays_rows)?;
Ok(schema
.as_struct()
.expect("schema should be struct")
.to_owned()
.try_into()
.unwrap())
})
.collect::<Result<Vec<_>, Error>>()?;

Ok(proto::types::Entity { hashed_keys: hashed_keys.to_bytes_be().to_vec(), models })
}
}

fn process_event_field(data: &str) -> Result<Vec<Vec<u8>>, Error> {
Expand All @@ -825,6 +819,25 @@ fn map_row_to_event(row: &(String, String, String)) -> Result<proto::types::Even
Ok(proto::types::Event { keys, data, transaction_hash })
}

fn map_row_to_entity(
row: &SqliteRow,
arrays_rows: &HashMap<String, Vec<SqliteRow>>,
schemas: &[Ty],
) -> Result<proto::types::Entity, Error> {
let hashed_keys =
FieldElement::from_str(&row.get::<String, _>("id")).map_err(ParseError::FromStr)?;
let models = schemas
.iter()
.map(|schema| {
let mut schema = schema.to_owned();
map_row_to_ty("", &schema.name(), &mut schema, row, arrays_rows)?;
Ok(schema.as_struct().expect("schema should be struct").to_owned().try_into().unwrap())
})
.collect::<Result<Vec<_>, Error>>()?;

Ok(proto::types::Entity { hashed_keys: hashed_keys.to_bytes_be().to_vec(), models })
}

type ServiceResult<T> = Result<Response<T>, Status>;
type SubscribeModelsResponseStream =
Pin<Box<dyn Stream<Item = Result<SubscribeModelsResponse, Status>> + Send>>;
Expand Down
31 changes: 8 additions & 23 deletions crates/torii/grpc/src/server/subscriptions/entity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ use tokio::sync::mpsc::{channel, Receiver, Sender};
use tokio::sync::RwLock;
use torii_core::cache::ModelCache;
use torii_core::error::{Error, ParseError};
use torii_core::model::{build_sql_query, map_row_to_ty};
use torii_core::model::build_sql_query;
use torii_core::simple_broker::SimpleBroker;
use torii_core::sql::FELT_DELIMITER;
use torii_core::types::Entity;
use tracing::{error, trace};

use crate::proto;
use crate::proto::world::SubscribeEntityResponse;
use crate::server::map_row_to_entity;
use crate::types::{EntityKeysClause, PatternMatching};

pub(crate) const LOG_TARGET: &str = "torii::grpc::server::subscriptions::entity";
Expand Down Expand Up @@ -115,11 +116,11 @@ impl Service {
Some(EntityKeysClause::Keys(clause)) => {

Check warning on line 116 in crates/torii/grpc/src/server/subscriptions/entity.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/grpc/src/server/subscriptions/entity.rs#L116

Added line #L116 was not covered by tests
// if we have a model clause, then we need to check that the entity
// has an updated model and that the model name matches the clause
if let Some(model) = &clause.model {
if let Some(updated_model) = &entity.updated_model {
if updated_model.name() != model.clone() {
continue;
}
if let Some(updated_model) = &entity.updated_model {
if !clause.models.is_empty()
&& !clause.models.contains(&updated_model.name())

Check warning on line 121 in crates/torii/grpc/src/server/subscriptions/entity.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/grpc/src/server/subscriptions/entity.rs#L119-L121

Added lines #L119 - L121 were not covered by tests
{
continue;
}
}

Check warning on line 125 in crates/torii/grpc/src/server/subscriptions/entity.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/grpc/src/server/subscriptions/entity.rs#L123-L125

Added lines #L123 - L125 were not covered by tests

Expand Down Expand Up @@ -199,24 +200,8 @@ impl Service {
arrays_rows.insert(name, row);

Check warning on line 200 in crates/torii/grpc/src/server/subscriptions/entity.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/grpc/src/server/subscriptions/entity.rs#L196-L200

Added lines #L196 - L200 were not covered by tests
}

let models = schemas
.into_iter()
.map(|mut s| {
map_row_to_ty("", &s.name(), &mut s, &row, &arrays_rows)?;

Ok(s.as_struct()
.expect("schema should be a struct")
.to_owned()
.try_into()
.unwrap())
})
.collect::<Result<Vec<_>, Error>>()?;

let resp = proto::world::SubscribeEntityResponse {
entity: Some(proto::types::Entity {
hashed_keys: hashed.to_bytes_be().to_vec(),
models,
}),
entity: Some(map_row_to_entity(&row, &arrays_rows, &schemas)?),

Check warning on line 204 in crates/torii/grpc/src/server/subscriptions/entity.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/grpc/src/server/subscriptions/entity.rs#L203-L204

Added lines #L203 - L204 were not covered by tests
};

if sub.sender.send(Ok(resp)).await.is_err() {
Expand Down
30 changes: 8 additions & 22 deletions crates/torii/grpc/src/server/subscriptions/event_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ use tokio::sync::mpsc::{channel, Receiver, Sender};
use tokio::sync::RwLock;
use torii_core::cache::ModelCache;
use torii_core::error::{Error, ParseError};
use torii_core::model::{build_sql_query, map_row_to_ty};
use torii_core::model::build_sql_query;
use torii_core::simple_broker::SimpleBroker;
use torii_core::sql::FELT_DELIMITER;
use torii_core::types::EventMessage;
use tracing::{error, trace};

use crate::proto;
use crate::proto::world::SubscribeEntityResponse;
use crate::server::map_row_to_entity;
use crate::types::{EntityKeysClause, PatternMatching};

pub(crate) const LOG_TARGET: &str = "torii::grpc::server::subscriptions::event_message";
Expand Down Expand Up @@ -114,11 +115,11 @@ impl Service {
Some(EntityKeysClause::Keys(clause)) => {

Check warning on line 115 in crates/torii/grpc/src/server/subscriptions/event_message.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/grpc/src/server/subscriptions/event_message.rs#L115

Added line #L115 was not covered by tests
// if we have a model clause, then we need to check that the entity
// has an updated model and that the model name matches the clause
if let Some(model) = &clause.model {
if let Some(updated_model) = &entity.updated_model {
if updated_model.name() != model.clone() {
continue;
}
if let Some(updated_model) = &entity.updated_model {
if !clause.models.is_empty()
&& !clause.models.contains(&updated_model.name())

Check warning on line 120 in crates/torii/grpc/src/server/subscriptions/event_message.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/grpc/src/server/subscriptions/event_message.rs#L118-L120

Added lines #L118 - L120 were not covered by tests
{
continue;
}
}

Check warning on line 124 in crates/torii/grpc/src/server/subscriptions/event_message.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/grpc/src/server/subscriptions/event_message.rs#L122-L124

Added lines #L122 - L124 were not covered by tests

Expand Down Expand Up @@ -184,23 +185,8 @@ impl Service {
arrays_rows.insert(name, rows);

Check warning on line 185 in crates/torii/grpc/src/server/subscriptions/event_message.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/grpc/src/server/subscriptions/event_message.rs#L181-L185

Added lines #L181 - L185 were not covered by tests
}

let models = schemas
.into_iter()
.map(|mut s| {
map_row_to_ty("", &s.name(), &mut s, &row, &arrays_rows)?;
Ok(s.as_struct()
.expect("schema should be a struct")
.to_owned()
.try_into()
.unwrap())
})
.collect::<Result<Vec<_>, Error>>()?;

let resp = proto::world::SubscribeEntityResponse {
entity: Some(proto::types::Entity {
hashed_keys: hashed.to_bytes_be().to_vec(),
models,
}),
entity: Some(map_row_to_entity(&row, &arrays_rows, &schemas)?),

Check warning on line 189 in crates/torii/grpc/src/server/subscriptions/event_message.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/grpc/src/server/subscriptions/event_message.rs#L188-L189

Added lines #L188 - L189 were not covered by tests
};

if sub.sender.send(Ok(resp)).await.is_err() {
Expand Down
2 changes: 1 addition & 1 deletion crates/torii/grpc/src/server/tests/entities_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ async fn test_entities_queries() {
KeysClause {
keys: vec![account.address().to_bytes_be().to_vec()],
pattern_matching: 0,
model: None,
models: vec![],
},
Some(1),
None,
Expand Down
6 changes: 3 additions & 3 deletions crates/torii/grpc/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub struct ModelKeysClause {
pub struct KeysClause {
pub keys: Vec<FieldElement>,
pub pattern_matching: PatternMatching,
pub model: Option<String>,
pub models: Vec<String>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Hash, Eq, Clone)]

Check warning on line 51 in crates/torii/grpc/src/types/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/grpc/src/types/mod.rs#L51

Added line #L51 was not covered by tests
Expand Down Expand Up @@ -186,7 +186,7 @@ impl From<KeysClause> for proto::types::KeysClause {
Self {
keys: value.keys.iter().map(|k| k.to_bytes_be().into()).collect(),
pattern_matching: value.pattern_matching as i32,
model: value.model,
models: value.models,
}
}

Check warning on line 191 in crates/torii/grpc/src/types/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/grpc/src/types/mod.rs#L185-L191

Added lines #L185 - L191 were not covered by tests
}
Expand All @@ -201,7 +201,7 @@ impl TryFrom<proto::types::KeysClause> for KeysClause {
.map(|k| FieldElement::from_byte_slice_be(k))
.collect::<Result<Vec<_>, _>>()?;

Check warning on line 202 in crates/torii/grpc/src/types/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/grpc/src/types/mod.rs#L197-L202

Added lines #L197 - L202 were not covered by tests

Ok(Self { keys, pattern_matching: value.pattern_matching().into(), model: value.model })
Ok(Self { keys, pattern_matching: value.pattern_matching().into(), models: value.models })
}

Check warning on line 205 in crates/torii/grpc/src/types/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/grpc/src/types/mod.rs#L204-L205

Added lines #L204 - L205 were not covered by tests
}

Expand Down

0 comments on commit 48c9c2e

Please sign in to comment.