Skip to content

Commit

Permalink
Update quickstart chat server for 0.12 host
Browse files Browse the repository at this point in the history
  • Loading branch information
lcodes committed Oct 31, 2024
1 parent bc4c5d9 commit c1cfca3
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 73 deletions.
6 changes: 5 additions & 1 deletion examples~/quickstart/server/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@
debug/
target/

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock

# These are backup files generated by rustfmt
**/*.rs.bk

# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb

# Spacetime ignore
/.spacetime
/.spacetime
95 changes: 71 additions & 24 deletions examples~/quickstart/server/Cargo.lock

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

5 changes: 2 additions & 3 deletions examples~/quickstart/server/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "spacetime-module"
name = "quickstart-chat-module"
version = "0.1.0"
edition = "2021"

Expand All @@ -9,6 +9,5 @@ edition = "2021"
crate-type = ["cdylib"]

[dependencies]
spacetimedb = "0.10"
spacetimedb = "0.12.0"
log = "0.4"
anyhow = "1.0"
91 changes: 46 additions & 45 deletions examples~/quickstart/server/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use spacetimedb::{ReducerContext, Identity, Table, Timestamp};
use anyhow::{Result, anyhow};
use spacetimedb::{Identity, ReducerContext, Table, Timestamp};

#[spacetimedb::table(name = user, public)]
pub struct User {
Expand All @@ -16,71 +15,41 @@ pub struct Message {
text: String,
}

#[spacetimedb::reducer(init)]
pub fn init(_ctx: &ReducerContext) {

}

#[spacetimedb::reducer(client_connected)]
pub fn identity_connected(ctx: &ReducerContext) {
if let Some(user) = ctx.db.user().identity().find(&ctx.sender) {
// If this is a returning user, i.e. we already have a `User` with this `Identity`,
// set `online: true`, but leave `name` and `identity` unchanged.
ctx.db.user().identity().update(User { online: true, ..user });
} else {
// If this is a new user, create a `User` row for the `Identity`,
// which is online, but hasn't set a name.
ctx.db.user().try_insert(User {
name: None,
identity: ctx.sender,
online: true,
}).unwrap();
}
}

#[spacetimedb::reducer(client_disconnected)]
pub fn identity_disconnected(ctx: &ReducerContext) {
if let Some(user) = ctx.db.user().identity().find(&ctx.sender) {
ctx.db.user().identity().update(User { online: false, ..user });
} else {
// This branch should be unreachable,
// as it doesn't make sense for a client to disconnect without connecting first.
log::warn!("Disconnect event for unknown user with identity {:?}", ctx.sender);
}
}

fn validate_name(name: String) -> Result<String> {
fn validate_name(name: String) -> Result<String, String> {
if name.is_empty() {
Err(anyhow!("Names must not be empty"))
Err("Names must not be empty".to_string())
} else {
Ok(name)
}
}

#[spacetimedb::reducer]
pub fn set_name(ctx: &ReducerContext, name: String) -> Result<()> {
pub fn set_name(ctx: &ReducerContext, name: String) -> Result<(), String> {
let name = validate_name(name)?;
if let Some(user) = ctx.db.user().identity().find(&ctx.sender) {
ctx.db.user().identity().update(User { name: Some(name), ..user });
if let Some(user) = ctx.db.user().identity().find(ctx.sender) {
ctx.db.user().identity().update(User {
name: Some(name),
..user
});
Ok(())
} else {
Err(anyhow!("Cannot set name for unknown user"))
Err("Cannot set name for unknown user".to_string())
}
}

fn validate_message(text: String) -> Result<String> {
fn validate_message(text: String) -> Result<String, String> {
if text.is_empty() {
Err(anyhow!("Messages must not be empty"))
Err("Messages must not be empty".to_string())
} else {
Ok(text)
}
}

#[spacetimedb::reducer]
pub fn send_message(ctx: &ReducerContext, text: String) -> Result<()> {
pub fn send_message(ctx: &ReducerContext, text: String) -> Result<(), String> {
// Things to consider:
// - Rate-limit messages per-user.
// - Reject messages from unnamed users.
// - Reject messages from unnamed user.
let text = validate_message(text)?;
ctx.db.message().insert(Message {
sender: ctx.sender,
Expand All @@ -89,3 +58,35 @@ pub fn send_message(ctx: &ReducerContext, text: String) -> Result<()> {
});
Ok(())
}

#[spacetimedb::reducer(init)]
// Called when the module is initially published
pub fn init(_ctx: &ReducerContext) {}

#[spacetimedb::reducer(client_connected)]
pub fn identity_connected(ctx: &ReducerContext) {
if let Some(user) = ctx.db.user().identity().find(ctx.sender) {
// If this is a returning user, i.e. we already have a `User` with this `Identity`,
// set `online: true`, but leave `name` and `identity` unchanged.
ctx.db.user().identity().update(User { online: true, ..user });
} else {
// If this is a new user, create a `User` row for the `Identity`,
// which is online, but hasn't set a name.
ctx.db.user().insert(User {
name: None,
identity: ctx.sender,
online: true,
});
}
}

#[spacetimedb::reducer(client_disconnected)]
pub fn identity_disconnected(ctx: &ReducerContext) {
if let Some(user) = ctx.db.user().identity().find(ctx.sender) {
ctx.db.user().identity().update(User { online: false, ..user });
} else {
// This branch should be unreachable,
// as it doesn't make sense for a client to disconnect without connecting first.
log::warn!("Disconnect event for unknown user with identity {:?}", ctx.sender);
}
}

0 comments on commit c1cfca3

Please sign in to comment.