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

feat: add eventmessage for emitting models & start refactoring emit macro #1656

Merged
merged 38 commits into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
1fab000
feat: add eventmessage for emitting models & start refactoring emit m…
Larkooo Mar 12, 2024
92fc0ba
refactor: emit multiple models event
Larkooo Mar 12, 2024
3942b34
feat: event message processor
Larkooo Mar 13, 2024
bfec3ab
feat: emit_message world func emit event mssage
Larkooo Mar 13, 2024
9c590a0
refactor: catch all event processor
Larkooo Mar 13, 2024
3efd17f
refactor: check model key as name
Larkooo Mar 13, 2024
b947f26
feat: model name keccak as id & rework model events
Larkooo Mar 13, 2024
5b1e8f2
fix: storing entities with model hash
Larkooo Mar 13, 2024
e53e046
refactor: catch all event message and store
Larkooo Mar 14, 2024
d98f49e
feat: emit model evrnt from spawn and move spawn
Larkooo Mar 14, 2024
c9c3255
fix: pass keys as array
Larkooo Mar 14, 2024
655fb9f
feat: fix emit macro and correctly index model events
Larkooo Mar 14, 2024
b2f3bee
feat: event messages migrations & set
Larkooo Mar 14, 2024
61e0ca3
feat: store events messages and new id system
Larkooo Mar 14, 2024
201e019
chore: fmt
Larkooo Mar 14, 2024
82dc81f
fix: keys array
Larkooo Mar 14, 2024
40dddbc
feat: add grpc endpoint for event messages
Larkooo Mar 15, 2024
b048831
feat: graphql schema for event messages
Larkooo Mar 15, 2024
fa51fd2
cadd comments for moel name hash
Larkooo Mar 15, 2024
15f3031
revert world.cario changes
Larkooo Mar 15, 2024
aeaaa81
fix: graphql entity and model connection
Larkooo Mar 19, 2024
ba793f4
refactor: only test models name ordering
Larkooo Mar 20, 2024
10ff64b
fix: entity/modeldata relation
Larkooo Mar 20, 2024
9720ab3
refactor: remove event testing
Larkooo Mar 20, 2024
048bfa4
fix: cairo code
Larkooo Mar 20, 2024
80bc512
refactor: add back event rxample
Larkooo Mar 20, 2024
8b10b9a
Merge branch 'main' into emit-model
Larkooo Mar 20, 2024
f461512
fix: merge
Larkooo Mar 20, 2024
611f846
chore: migration
Larkooo Mar 20, 2024
9c8e37a
fix: subscription test
Larkooo Mar 20, 2024
56836dc
fix: tests
Larkooo Mar 20, 2024
423b1cb
fix: subscription test
Larkooo Mar 20, 2024
91e50ae
fix: sql test
Larkooo Mar 20, 2024
220d36c
chore: format model id correctly in test
Larkooo Mar 20, 2024
6f19ebd
fix: model subscription with id
Larkooo Mar 20, 2024
c6d33b7
fix: schema for model
Larkooo Mar 21, 2024
9ae11f4
chore: revert modelmmeber type
Larkooo Mar 21, 2024
ba880af
fix: event message query
Larkooo Mar 21, 2024
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
2 changes: 2 additions & 0 deletions bin/torii/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
use tokio::sync::broadcast::Sender;
use tokio_stream::StreamExt;
use torii_core::engine::{Engine, EngineConfig, Processors};
use torii_core::processors::event_message::EventMessageProcessor;
use torii_core::processors::metadata_update::MetadataUpdateProcessor;
use torii_core::processors::register_model::RegisterModelProcessor;
use torii_core::processors::store_del_record::StoreDelRecordProcessor;
Expand Down Expand Up @@ -160,6 +161,7 @@
Box::new(StoreSetRecordProcessor),
Box::new(MetadataUpdateProcessor),
Box::new(StoreDelRecordProcessor),
Box::new(EventMessageProcessor),

Check warning on line 164 in bin/torii/src/main.rs

View check run for this annotation

Codecov / codecov/patch

bin/torii/src/main.rs#L164

Added line #L164 was not covered by tests
],
transaction: vec![Box::new(StoreTransactionProcessor)],
..Processors::default()
Expand Down
94 changes: 76 additions & 18 deletions crates/dojo-lang/src/inline_macros/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
use cairo_lang_semantic::inline_macros::unsupported_bracket_diagnostic;
use cairo_lang_syntax::node::{ast, TypedSyntaxNode};

use super::unsupported_arg_diagnostic;

#[derive(Debug, Default)]
pub struct EmitMacro;

Expand All @@ -23,11 +25,7 @@
return unsupported_bracket_diagnostic(db, syntax);
};
let mut builder = PatchBuilder::new(db);
builder.add_str(
"{
let mut keys = Default::<core::array::Array>::default();
let mut data = Default::<core::array::Array>::default();",
);
builder.add_str("{");

let args = arg_list.arguments(db).elements(db);

Expand All @@ -36,25 +34,85 @@
code: None,
diagnostics: vec![PluginDiagnostic {
stable_ptr: arg_list.arguments(db).stable_ptr().untyped(),
message: "Invalid arguments. Expected \"emit!(world, event)\"".to_string(),
message: "Invalid arguments. Expected \"emit!(world, models,)\"".to_string(),

Check warning on line 37 in crates/dojo-lang/src/inline_macros/emit.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo-lang/src/inline_macros/emit.rs#L37

Added line #L37 was not covered by tests
severity: Severity::Error,
}],
};
}

let world = &args[0];
let event = &args[1];

builder.add_str(
"\n starknet::Event::append_keys_and_data(@core::traits::Into::<_, \
Event>::into(",
);
builder.add_node(event.as_syntax_node());
builder.add_str("), ref keys, ref data);");

builder.add_str("\n ");
builder.add_node(world.as_syntax_node());
builder.add_str(".emit(keys, data.span());");

let ast::ArgClause::Unnamed(models) = args[1].arg_clause(db) else {
return unsupported_arg_diagnostic(db, syntax);

Check warning on line 46 in crates/dojo-lang/src/inline_macros/emit.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo-lang/src/inline_macros/emit.rs#L46

Added line #L46 was not covered by tests
};

let mut bundle = vec![];

match models.value(db) {
ast::Expr::Parenthesized(parens) => {
let syntax_node = parens.expr(db).as_syntax_node();
bundle.push((syntax_node.get_text(db), syntax_node));
}
ast::Expr::Tuple(list) => {
list.expressions(db).elements(db).into_iter().for_each(|expr| {
let syntax_node = expr.as_syntax_node();
bundle.push((syntax_node.get_text(db), syntax_node));
})

Check warning on line 60 in crates/dojo-lang/src/inline_macros/emit.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo-lang/src/inline_macros/emit.rs#L56-L60

Added lines #L56 - L60 were not covered by tests
}
ast::Expr::StructCtorCall(ctor) => {
let syntax_node = ctor.as_syntax_node();
bundle.push((syntax_node.get_text(db), syntax_node));
}

Check warning on line 65 in crates/dojo-lang/src/inline_macros/emit.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo-lang/src/inline_macros/emit.rs#L62-L65

Added lines #L62 - L65 were not covered by tests
_ => {
return InlinePluginResult {
code: None,
diagnostics: vec![PluginDiagnostic {
message: "Invalid arguments. Expected \"(world, (models,))\"".to_string(),
stable_ptr: arg_list.arguments(db).stable_ptr().untyped(),
severity: Severity::Error,
}],
};

Check warning on line 74 in crates/dojo-lang/src/inline_macros/emit.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo-lang/src/inline_macros/emit.rs#L67-L74

Added lines #L67 - L74 were not covered by tests
}
}

if bundle.is_empty() {
return InlinePluginResult {
code: None,
diagnostics: vec![PluginDiagnostic {
message: "Invalid arguments: No models provided.".to_string(),
stable_ptr: arg_list.arguments(db).stable_ptr().untyped(),
severity: Severity::Error,
}],
};

Check warning on line 86 in crates/dojo-lang/src/inline_macros/emit.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo-lang/src/inline_macros/emit.rs#L79-L86

Added lines #L79 - L86 were not covered by tests
}

for (event, _) in bundle {
builder.add_str("{");

builder.add_str(
"
let mut keys = Default::<core::array::Array>::default();
let mut data = Default::<core::array::Array>::default();",
);

builder.add_str(&format!(
"keys.append(selector!(\"{}\"));",
Larkooo marked this conversation as resolved.
Show resolved Hide resolved
event.split_whitespace().next().unwrap()
));

builder.add_str(&format!(
"
starknet::Event::append_keys_and_data(@{event}, ref keys, ref data);",
event = event
));

builder.add_str("\n ");
builder.add_node(world.as_syntax_node());
builder.add_str(".emit(keys, data.span());");

builder.add_str("}");
}

builder.add_str("}");

InlinePluginResult {
Expand Down
5 changes: 5 additions & 0 deletions crates/dojo-world/src/contracts/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
pub trait ModelReader<E> {
fn name(&self) -> String;
fn class_hash(&self) -> FieldElement;
fn contract_address(&self) -> FieldElement;
async fn schema(&self) -> Result<Ty, E>;
Expand Down Expand Up @@ -147,6 +148,10 @@
where
P: Provider + Sync + Send,
{
fn name(&self) -> String {
self.name.to_string()
}

Check warning on line 153 in crates/dojo-world/src/contracts/model.rs

View check run for this annotation

Codecov / codecov/patch

crates/dojo-world/src/contracts/model.rs#L151-L153

Added lines #L151 - L153 were not covered by tests
Larkooo marked this conversation as resolved.
Show resolved Hide resolved

fn class_hash(&self) -> FieldElement {
self.class_hash
}
Expand Down
4 changes: 2 additions & 2 deletions crates/dojo-world/src/manifest_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,10 +380,10 @@ async fn fetch_remote_manifest() {
let remote_manifest =
DeploymentManifest::load_from_remote(provider, world_address).await.unwrap();

assert_eq!(local_manifest.models.len(), 2);
assert_eq!(local_manifest.models.len(), 3);
assert_eq!(local_manifest.contracts.len(), 1);

assert_eq!(remote_manifest.models.len(), 2);
assert_eq!(remote_manifest.models.len(), 3);
assert_eq!(remote_manifest.contracts.len(), 1);

// compute diff from local and remote manifest
Expand Down
5 changes: 4 additions & 1 deletion crates/torii/core/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,10 @@ impl<P: Provider + Sync> Engine<P> {
};
self.db.store_event(event_id, event, transaction_hash);
for processor in &self.processors.event {
if get_selector_from_name(&processor.event_key())? == event.keys[0]
// If the processor has no event_key, means it's a catch-all processor.
// We also validate the event
if (processor.event_key().is_empty()
|| get_selector_from_name(&processor.event_key())? == event.keys[0])
&& processor.validate(event)
{
processor
Expand Down
4 changes: 3 additions & 1 deletion crates/torii/core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::num::ParseIntError;
use dojo_types::primitive::PrimitiveError;
use dojo_types::schema::EnumError;
use starknet::core::types::{FromByteSliceError, FromStrError};
use starknet::core::utils::CairoShortStringToFeltError;
use starknet::core::utils::{CairoShortStringToFeltError, NonAsciiNameError};

#[derive(Debug, thiserror::Error)]
pub enum Error {
Expand All @@ -21,6 +21,8 @@ pub enum Error {

#[derive(Debug, thiserror::Error)]
pub enum ParseError {
#[error(transparent)]
NonAsciiName(#[from] NonAsciiNameError),
#[error(transparent)]
FromStr(#[from] FromStrError),
#[error(transparent)]
Expand Down
11 changes: 10 additions & 1 deletion crates/torii/core/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use sqlx::sqlite::SqliteRow;
use sqlx::{Pool, Row, Sqlite};
use starknet::core::types::FieldElement;
use starknet::core::utils::get_selector_from_name;

use super::error::{self, Error};
use crate::error::{ParseError, QueryError};
Expand Down Expand Up @@ -59,6 +60,10 @@
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
impl ModelReader<Error> for ModelSQLReader {
fn name(&self) -> String {
self.name.to_string()
}

Check warning on line 65 in crates/torii/core/src/model.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/core/src/model.rs#L63-L65

Added lines #L63 - L65 were not covered by tests

fn class_hash(&self) -> FieldElement {
self.class_hash
}
Expand All @@ -68,11 +73,15 @@
}

async fn schema(&self) -> Result<Ty, Error> {
// this is temporary until the hash for the model name is precomputed
let model_selector =
get_selector_from_name(&self.name).map_err(error::ParseError::NonAsciiName)?;
Larkooo marked this conversation as resolved.
Show resolved Hide resolved

let model_members: Vec<SqlModelMember> = sqlx::query_as(
"SELECT id, model_idx, member_idx, name, type, type_enum, enum_options, key FROM \
model_members WHERE model_id = ? ORDER BY model_idx ASC, member_idx ASC",
)
.bind(self.name.clone())
.bind(format!("{:#x}", model_selector))
.fetch_all(&self.pool)
.await?;

Expand Down
65 changes: 65 additions & 0 deletions crates/torii/core/src/processors/event_message.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use anyhow::{Error, Result};
use async_trait::async_trait;
use dojo_world::contracts::model::ModelReader;
use dojo_world::contracts::world::WorldContractReader;
use starknet::core::types::{Event, TransactionReceipt};
use starknet::providers::Provider;
use tracing::info;

use super::EventProcessor;
use crate::processors::MODEL_INDEX;
use crate::sql::Sql;

#[derive(Default)]

Check warning on line 13 in crates/torii/core/src/processors/event_message.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/core/src/processors/event_message.rs#L13

Added line #L13 was not covered by tests
pub struct EventMessageProcessor;

#[async_trait]
impl<P> EventProcessor<P> for EventMessageProcessor
where
P: Provider + Send + Sync,
{
fn event_key(&self) -> String {
"".to_string()
}

Check warning on line 23 in crates/torii/core/src/processors/event_message.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/core/src/processors/event_message.rs#L21-L23

Added lines #L21 - L23 were not covered by tests

fn validate(&self, event: &Event) -> bool {
// we expect at least 3 keys
// 1: event selector
// 2: model keys, arbitrary length
// last key: system key
if event.keys.len() < 3 {
return false;
}

true
Larkooo marked this conversation as resolved.
Show resolved Hide resolved
}

Check warning on line 35 in crates/torii/core/src/processors/event_message.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/core/src/processors/event_message.rs#L25-L35

Added lines #L25 - L35 were not covered by tests

async fn process(
&self,
_world: &WorldContractReader<P>,
db: &mut Sql,
_block_number: u64,
_transaction_receipt: &TransactionReceipt,
event_id: &str,
event: &Event,
) -> Result<(), Error> {

Check warning on line 45 in crates/torii/core/src/processors/event_message.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/core/src/processors/event_message.rs#L37-L45

Added lines #L37 - L45 were not covered by tests
// silently ignore if the model is not found
let model = match db.model(&format!("{:#x}", event.keys[MODEL_INDEX])).await {
Ok(model) => model,
Err(_) => return Ok(()),

Check warning on line 49 in crates/torii/core/src/processors/event_message.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/core/src/processors/event_message.rs#L47-L49

Added lines #L47 - L49 were not covered by tests
};

info!("store event message: {}", model.name());

Check warning on line 52 in crates/torii/core/src/processors/event_message.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/core/src/processors/event_message.rs#L52

Added line #L52 was not covered by tests

// skip the first key, as its the event selector
// and dont include last key as its the system key
let mut keys_and_unpacked =
[event.keys[1..event.keys.len() - 1].to_vec(), event.data.clone()].concat();

Check warning on line 57 in crates/torii/core/src/processors/event_message.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/core/src/processors/event_message.rs#L56-L57

Added lines #L56 - L57 were not covered by tests

let mut entity = model.schema().await?;
entity.deserialize(&mut keys_and_unpacked)?;

Check warning on line 60 in crates/torii/core/src/processors/event_message.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/core/src/processors/event_message.rs#L59-L60

Added lines #L59 - L60 were not covered by tests

db.set_event_message(entity, event_id).await?;
Ok(())
}

Check warning on line 64 in crates/torii/core/src/processors/event_message.rs

View check run for this annotation

Codecov / codecov/patch

crates/torii/core/src/processors/event_message.rs#L62-L64

Added lines #L62 - L64 were not covered by tests
}
1 change: 1 addition & 0 deletions crates/torii/core/src/processors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use starknet_crypto::FieldElement;

use crate::sql::Sql;

pub mod event_message;
pub mod metadata_update;
pub mod register_model;
pub mod store_del_record;
Expand Down
5 changes: 3 additions & 2 deletions crates/torii/core/src/processors/store_del_record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use async_trait::async_trait;
use dojo_world::contracts::model::ModelReader;
use dojo_world::contracts::world::WorldContractReader;
use starknet::core::types::{Event, TransactionReceipt};
use starknet::core::utils::parse_cairo_short_string;
use starknet::core::utils::{get_selector_from_name, parse_cairo_short_string};
use starknet::providers::Provider;
use tracing::info;

Expand Down Expand Up @@ -47,7 +47,8 @@ where
let name = parse_cairo_short_string(&event.data[MODEL_INDEX])?;
info!("store delete record: {}", name);

let model = db.model(&name).await?;
// this is temporary until the model name hash is precomputed
let model = db.model(&format!("{:#x}", get_selector_from_name(&name)?)).await?;

let keys_start = NUM_KEYS_INDEX + 1;
let keys = event.data[keys_start..].to_vec();
Expand Down
5 changes: 3 additions & 2 deletions crates/torii/core/src/processors/store_set_record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use async_trait::async_trait;
use dojo_world::contracts::model::ModelReader;
use dojo_world::contracts::world::WorldContractReader;
use starknet::core::types::{Event, TransactionReceipt};
use starknet::core::utils::parse_cairo_short_string;
use starknet::core::utils::{get_selector_from_name, parse_cairo_short_string};
use starknet::providers::Provider;
use tracing::info;

Expand Down Expand Up @@ -47,7 +47,8 @@ where
let name = parse_cairo_short_string(&event.data[MODEL_INDEX])?;
info!("store set record: {}", name);

let model = db.model(&name).await?;
// this is temporary until the model name hash is precomputed
let model = db.model(&format!("{:#x}", get_selector_from_name(&name)?)).await?;

let keys_start = NUM_KEYS_INDEX + 1;
let keys_end: usize = keys_start + usize::from(u8::try_from(event.data[NUM_KEYS_INDEX])?);
Expand Down
Loading
Loading