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

websocket: send/receive reducer & table ids instead of names (take 2) #1940

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

64 changes: 29 additions & 35 deletions crates/cli/src/subcommands/generate/csharp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::fmt::{self, Write};
use std::ops::Deref;

use convert_case::{Case, Casing};
use itertools::Itertools;
use spacetimedb_lib::sats::{AlgebraicType, AlgebraicTypeRef, ArrayType, ProductType, SumType};
use spacetimedb_lib::ReducerDef;
use spacetimedb_primitives::ColList;
Expand Down Expand Up @@ -554,13 +555,17 @@ pub fn autogen_csharp_reducer(ctx: &GenCtx, reducer: &ReducerDef, namespace: &st
pub fn autogen_csharp_globals(ctx: &GenCtx, items: &[GenItem], namespace: &str) -> Vec<(String, String)> {
let mut results = Vec::new();

let tables = items.iter().filter_map(|i| {
if let GenItem::Table(table) = i {
Some(table)
} else {
None
}
});
let tables: Vec<_> = items
.iter()
.filter_map(|i| {
if let GenItem::Table(table) = i {
Some(table)
} else {
None
}
})
.sorted_by_key(|t| &t.schema.table_name)
.collect();

let reducers: Vec<&ReducerDef> = items
.iter()
Expand All @@ -571,6 +576,7 @@ pub fn autogen_csharp_globals(ctx: &GenCtx, items: &[GenItem], namespace: &str)
None
}
})
.sorted_by_key(|i| &i.name)
.collect();
let reducer_names: Vec<String> = reducers
.iter()
Expand All @@ -581,7 +587,7 @@ pub fn autogen_csharp_globals(ctx: &GenCtx, items: &[GenItem], namespace: &str)

writeln!(output, "public sealed class RemoteTables");
indented_block(&mut output, |output| {
for table in tables {
for &table in &tables {
let schema = &table.schema;
let name = &schema.table_name;
let csharp_name = name.as_ref().to_case(Case::Pascal);
Expand Down Expand Up @@ -772,9 +778,7 @@ pub fn autogen_csharp_globals(ctx: &GenCtx, items: &[GenItem], namespace: &str)
for reducer_name in &reducer_names {
writeln!(output, "{reducer_name} {reducer_name},");
}
writeln!(output, "Unit StdbNone,");
writeln!(output, "Unit StdbIdentityConnected,");
writeln!(output, "Unit StdbIdentityDisconnected");
writeln!(output, "Unit StdbNone");
}
writeln!(output, ")>;");

Expand All @@ -794,24 +798,25 @@ pub fn autogen_csharp_globals(ctx: &GenCtx, items: &[GenItem], namespace: &str)
writeln!(output, "Reducers = new(this, this.SetReducerFlags);");
writeln!(output);

for item in items {
if let GenItem::Table(table) = item {
writeln!(
output,
"clientDB.AddTable<{table_type}>(\"{table_name}\", Db.{csharp_table_name});",
table_type = csharp_typename(ctx, table.data),
table_name = table.schema.table_name,
csharp_table_name = table.schema.table_name.as_ref().to_case(Case::Pascal)
);
}
for &table in tables.iter() {
writeln!(
output,
"clientDB.AddTable<{table_type}>(\"{table_name}\", Db.{csharp_table_name});",
table_type = csharp_typename(ctx, table.data),
table_name = table.schema.table_name,
csharp_table_name = table.schema.table_name.as_ref().to_case(Case::Pascal)
);
}
});
writeln!(output);

writeln!(output, "protected override Reducer ToReducer(TransactionUpdate update)");
writeln!(
output,
"protected override Reducer ToReducer(string reducerName, TransactionUpdate update)"
);
indented_block(output, |output| {
writeln!(output, "var encodedArgs = update.ReducerCall.Args;");
writeln!(output, "return update.ReducerCall.ReducerName switch {{");
writeln!(output, "return reducerName switch {{");
{
indent_scope!(output);
for (reducer, reducer_name) in std::iter::zip(&reducers, &reducer_names) {
Expand All @@ -822,15 +827,6 @@ pub fn autogen_csharp_globals(ctx: &GenCtx, items: &[GenItem], namespace: &str)
);
}
writeln!(output, "\"<none>\" => new Reducer.StdbNone(default),");
writeln!(
output,
"\"__identity_connected__\" => new Reducer.StdbIdentityConnected(default),"
);
writeln!(
output,
"\"__identity_disconnected__\" => new Reducer.StdbIdentityDisconnected(default),"
);
writeln!(output, "\"\" => new Reducer.StdbNone(default),"); //Transaction from CLI command
writeln!(
output,
r#"var reducer => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {{reducer}}")"#
Expand Down Expand Up @@ -862,9 +858,7 @@ pub fn autogen_csharp_globals(ctx: &GenCtx, items: &[GenItem], namespace: &str)
"Reducer.{reducer_name}(var args) => Reducers.Invoke{reducer_name}(eventContext, args),"
);
}
writeln!(output, "Reducer.StdbNone or");
writeln!(output, "Reducer.StdbIdentityConnected or");
writeln!(output, "Reducer.StdbIdentityDisconnected => true,");
writeln!(output, "Reducer.StdbNone => true,");
writeln!(
output,
r#"_ => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {{reducer}}")"#
Expand Down
9 changes: 4 additions & 5 deletions crates/cli/src/subcommands/generate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use spacetimedb_schema::schema::{Schema, TableSchema};
use std::fs;
use std::ops::Deref;
use std::path::{Path, PathBuf};
use util::{iter_reducers, iter_tables};
use wasmtime::{Caller, StoreContextMut};

use crate::util::y_or_n;
Expand Down Expand Up @@ -266,9 +267,7 @@ pub fn generate(module: RawModuleDef, lang: Language, namespace: &str) -> anyhow
let items = itertools::chain!(
types,
tables.into_iter().map(GenItem::Table),
reducers
.filter(|r| !(r.name.starts_with("__") && r.name.ends_with("__")))
.map(GenItem::Reducer),
reducers.map(GenItem::Reducer),
);

let items: Vec<GenItem> = items.collect();
Expand All @@ -284,7 +283,7 @@ pub fn generate(module: RawModuleDef, lang: Language, namespace: &str) -> anyhow

fn generate_lang(module: &ModuleDef, lang: impl Lang, namespace: &str) -> Vec<(String, String)> {
itertools::chain!(
module.tables().map(|tbl| {
iter_tables(module).map(|tbl| {
(
lang.table_filename(module, tbl),
lang.generate_table(module, namespace, tbl),
Expand All @@ -296,7 +295,7 @@ fn generate_lang(module: &ModuleDef, lang: impl Lang, namespace: &str) -> Vec<(S
lang.generate_type(module, namespace, typ),
)
}),
module.reducers().map(|reducer| {
iter_reducers(module).map(|reducer| {
(
lang.reducer_filename(&reducer.name),
lang.generate_reducer(module, namespace, reducer),
Expand Down
143 changes: 69 additions & 74 deletions crates/cli/src/subcommands/generate/rust.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::code_indenter::{CodeIndenter, Indenter};
use super::util::{collect_case, print_lines, type_ref_name};
use super::util::{collect_case, iter_reducers, iter_tables, print_lines, type_ref_name};
use super::Lang;
use crate::generate::util::{namespace_is_empty_or_default, print_auto_generated_file_comment};
use convert_case::{Case, Casing};
Expand Down Expand Up @@ -763,20 +763,6 @@ fn print_module_reexports(module: &ModuleDef, out: &mut Indenter) {
}
}

/// Iterate over all the [`ReducerDef`]s defined by the module, in alphabetical order by name.
///
/// Sorting is necessary to have deterministic reproducable codegen.
fn iter_reducers(module: &ModuleDef) -> impl Iterator<Item = &ReducerDef> {
module.reducers().sorted_by_key(|reducer| &reducer.name)
}

/// Iterate over all the [`TableDef`]s defined by the module, in alphabetical order by name.
///
/// Sorting is necessary to have deterministic reproducable codegen.
fn iter_tables(module: &ModuleDef) -> impl Iterator<Item = &TableDef> {
module.tables().sorted_by_key(|table| &table.name)
}

fn print_reducer_enum_defn(module: &ModuleDef, out: &mut Indenter) {
print_enum_derives(out);
writeln!(
Expand Down Expand Up @@ -851,42 +837,45 @@ impl __sdk::spacetime_module::InModule for Reducer {{
},
"}\n",
);
},
"}\n",
);

out.delimited_block(
"impl TryFrom<__ws::ReducerCallInfo<__ws::BsatnFormat>> for Reducer {",
|out| {
writeln!(out, "type Error = __anyhow::Error;");
out.delimited_block(
"fn try_from(value: __ws::ReducerCallInfo<__ws::BsatnFormat>) -> __anyhow::Result<Self> {",
|out| {
out.delimited_block(
"match &value.reducer_name[..] {",
|out| {
for reducer in iter_reducers(module) {
writeln!(
out,
"{:?} => Ok(Reducer::{}(__sdk::spacetime_module::parse_reducer_args({:?}, &value.args)?)),",
reducer.name.deref(),
reducer_variant_name(&reducer.name),
reducer.name.deref(),
);
}
"fn parse_call_info(
reducer_id_to_name: &impl Fn(__ws::ReducerId) -> __anyhow::Result<&'static str>,
raw: __ws::ReducerCallInfo<__ws::BsatnFormat>,
) -> __anyhow::Result<Self> {",
|out| {
out.delimited_block(
"use __sdk::spacetime_module::parse_reducer_args;
let name = reducer_id_to_name(raw.reducer_id)?;
match name {",
|out| {
for reducer in iter_reducers(module) {
writeln!(
out,
"_ => Err(__anyhow::anyhow!(\"Unknown reducer {{:?}}\", value.reducer_name)),",
"{:?} => Ok(Reducer::{}(parse_reducer_args(name, &raw.args)?)),",
reducer.name.deref(),
reducer_variant_name(&reducer.name),
);
},
"}\n",
)
},
}
writeln!(out, "_ => unreachable!(),");
},
"
}\n",
)
},
"}\n",
);
out.delimited_block(
"fn reducer_names() -> &'static [&'static str] {&[",
|out| {
for reducer in iter_reducers(module) {
writeln!(out, "{:?},", &reducer.name);
}
},
"]}\n",
);
},
"}\n",
)
);
}

fn print_db_update_defn(module: &ModuleDef, out: &mut Indenter) {
Expand All @@ -910,37 +899,6 @@ fn print_db_update_defn(module: &ModuleDef, out: &mut Indenter) {

out.newline();

out.delimited_block(
"
impl TryFrom<__ws::DatabaseUpdate<__ws::BsatnFormat>> for DbUpdate {
type Error = __anyhow::Error;
fn try_from(raw: __ws::DatabaseUpdate<__ws::BsatnFormat>) -> Result<Self, Self::Error> {
let mut db_update = DbUpdate::default();
for table_update in raw.tables {
match &table_update.table_name[..] {
",
|out| {
for table in iter_tables(module) {
writeln!(
out,
"{:?} => db_update.{} = {}::parse_table_update(table_update)?,",
table.name.deref(),
table_method_name(&table.name),
table_module_name(&table.name),
);
}
},
"
unknown => __anyhow::bail!(\"Unknown table {unknown:?} in DatabaseUpdate\"),
}
}
Ok(db_update)
}
}",
);

out.newline();

writeln!(
out,
"
Expand Down Expand Up @@ -984,6 +942,43 @@ impl __sdk::spacetime_module::InModule for DbUpdate {{
},
"}\n",
);

out.delimited_block(
"fn parse_update(
table_id_to_name: &impl Fn(__ws::TableId) -> __anyhow::Result<&'static str>,
raw: __ws::DatabaseUpdate<__ws::BsatnFormat>,
) -> __anyhow::Result<Self> {
let mut db_update = DbUpdate::default();
for table_update in raw.tables {
match table_id_to_name(table_update.table_id)? {",
|out| {
for table in iter_tables(module) {
writeln!(
out,
"{:?} => db_update.{} = {}::parse_table_update(table_update)?,",
table.name.deref(),
table_method_name(&table.name),
table_module_name(&table.name),
);
}
},
"
_ => unreachable!(),
}
}
Ok(db_update)
}\n",
);

out.delimited_block(
"fn table_names() -> &'static [&'static str] {&[",
|out| {
for table in iter_tables(module) {
writeln!(out, "{:?},", &table.name);
}
},
"]}\n"
);
},
"}\n",
);
Expand Down
19 changes: 18 additions & 1 deletion crates/cli/src/subcommands/generate/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ use std::{
use convert_case::{Case, Casing};
use itertools::Itertools;
use spacetimedb_lib::sats::AlgebraicTypeRef;
use spacetimedb_schema::{def::ModuleDef, identifier::Identifier};
use spacetimedb_schema::{
def::{ModuleDef, ReducerDef, TableDef},
identifier::Identifier,
};

use super::code_indenter::Indenter;

Expand Down Expand Up @@ -57,3 +60,17 @@ pub(super) fn type_ref_name(module: &ModuleDef, typeref: AlgebraicTypeRef) -> St
let (name, _def) = module.type_def_from_ref(typeref).unwrap();
collect_case(Case::Pascal, name.name_segments())
}

/// Iterate over all the [`TableDef`]s defined by the module, in alphabetical order by name.
///
/// Sorting is necessary to have deterministic reproducable codegen.
pub(super) fn iter_tables(module: &ModuleDef) -> impl Iterator<Item = &TableDef> {
module.tables().sorted_by_key(|table| &table.name)
}

/// Iterate over all the [`ReducerDef`]s defined by the module, in alphabetical order by name.
///
/// Sorting is necessary to have deterministic reproducable codegen.
pub(super) fn iter_reducers(module: &ModuleDef) -> impl Iterator<Item = &ReducerDef> {
module.reducers().sorted_by_key(|reducer| &reducer.name)
}
2 changes: 1 addition & 1 deletion crates/cli/src/subcommands/subscribe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ fn reformat_update<'a>(
let table_schema = schema
.tables
.iter()
.find(|tbl| tbl.name == upd.table_name)
.find(|tbl| *tbl.name == *upd.table_name)
.context("table not found in schema")?;
let table_ty = schema.typespace.resolve(table_schema.product_type_ref);

Expand Down
Loading
Loading