Skip to content

Commit

Permalink
c# client SDK
Browse files Browse the repository at this point in the history
  • Loading branch information
lcodes committed Sep 12, 2024
1 parent 4cf062b commit 8bd8055
Show file tree
Hide file tree
Showing 13 changed files with 280 additions and 277 deletions.
2 changes: 1 addition & 1 deletion SpacetimeDB.ClientSDK.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
Expand Down
100 changes: 55 additions & 45 deletions examples~/quickstart/client/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net.WebSockets;
using System.Threading;
using SpacetimeDB;
using SpacetimeDB.ClientApi;
using SpacetimeDB.Types;

const string HOST = "http://localhost:3000";
const string DBNAME = "chatqs";

DbConnection? conn = null;

// our local client SpacetimeDB identity
Identity? local_identity = null;
// declare a thread safe queue to store commands
Expand All @@ -18,7 +24,25 @@ void Main()
{
AuthToken.Init(".spacetime_csharp_quickstart");

RegisterCallbacks();
conn = DbConnection.Builder()
.WithUri(HOST)
.WithModuleName(DBNAME)
//.WithCredentials((null, AuthToken.Token))
.OnConnect(OnConnect)
.OnConnectError(OnConnectError)
.OnDisconnect(OnDisconnect)
.Build();

conn.RemoteTables.User.OnInsert += User_OnInsert;
conn.RemoteTables.User.OnUpdate += User_OnUpdate;

conn.RemoteTables.Message.OnInsert += Message_OnInsert;

conn.RemoteReducers.OnSetName += Reducer_OnSetNameEvent;
conn.RemoteReducers.OnSendMessage += Reducer_OnSendMessageEvent;

conn.onSubscriptionApplied += OnSubscriptionApplied;
conn.onUnhandledReducerError += onUnhandledReducerError;

// spawn a thread to call process updates and process commands
var thread = new Thread(ProcessThread);
Expand All @@ -31,33 +55,17 @@ void Main()
thread.Join();
}

void RegisterCallbacks()
{
SpacetimeDBClient.instance.onConnect += OnConnect;
SpacetimeDBClient.instance.onIdentityReceived += OnIdentityReceived;
SpacetimeDBClient.instance.onSubscriptionApplied += OnSubscriptionApplied;
SpacetimeDBClient.instance.onUnhandledReducerError += onUnhandledReducerError;

User.OnInsert += User_OnInsert;
User.OnUpdate += User_OnUpdate;

Message.OnInsert += Message_OnInsert;

Reducer.OnSetNameEvent += Reducer_OnSetNameEvent;
Reducer.OnSendMessageEvent += Reducer_OnSendMessageEvent;
}

string UserNameOrIdentity(User user) => user.Name ?? user.Identity.ToString()[..8];

void User_OnInsert(User insertedValue, ReducerEvent? dbEvent)
void User_OnInsert(EventContext ctx, User insertedValue)
{
if (insertedValue.Online)
{
Console.WriteLine($"{UserNameOrIdentity(insertedValue)} is online");
}
}

void User_OnUpdate(User oldValue, User newValue, ReducerEvent? dbEvent)
void User_OnUpdate(EventContext ctx, User oldValue, User newValue)
{
if (oldValue.Name != newValue.Name)
{
Expand Down Expand Up @@ -88,39 +96,44 @@ void PrintMessage(Message message)
Console.WriteLine($"{senderName}: {message.Text}");
}

void Message_OnInsert(Message insertedValue, ReducerEvent? dbEvent)
void Message_OnInsert(EventContext ctx, Message insertedValue)
{
if (dbEvent != null)
if (ctx != null)
{
PrintMessage(insertedValue);
}
}

void Reducer_OnSetNameEvent(ReducerEvent reducerEvent, string name)
void Reducer_OnSetNameEvent(EventContext reducerEvent, string name)
{
if (reducerEvent.Identity == local_identity && reducerEvent.Status is UpdateStatus.Failed)
{
Console.Write($"Failed to change name to {name}");
}
}

void Reducer_OnSendMessageEvent(ReducerEvent reducerEvent, string text)
void Reducer_OnSendMessageEvent(EventContext reducerEvent, string text)
{
if (reducerEvent.Identity == local_identity && reducerEvent.Status is UpdateStatus.Failed)
{
Console.Write($"Failed to send message {text}");
}
}

void OnConnect()
{
SpacetimeDBClient.instance.Subscribe(new List<string> { "SELECT * FROM User", "SELECT * FROM Message" });
}

void OnIdentityReceived(string authToken, Identity identity, Address _address)
void OnConnect(Identity identity, string authToken)
{
local_identity = identity;
AuthToken.SaveToken(authToken);

conn!.Subscribe(new List<string> { "SELECT * FROM User", "SELECT * FROM Message" });
}

void OnConnectError(WebSocketError? error, string message) {

}

void OnDisconnect(DbConnection conn, WebSocketCloseStatus? status, WebSocketError? error) {

}

void PrintMessagesInOrder()
Expand All @@ -137,29 +150,26 @@ void OnSubscriptionApplied()
PrintMessagesInOrder();
}

void onUnhandledReducerError(ReducerEvent reducerEvent)
void onUnhandledReducerError(EventContext reducerEvent)
{
Console.WriteLine($"Unhandled reducer error in {reducerEvent.ReducerName}: {reducerEvent.ErrMessage}");
}

const string HOST = "http://localhost:3000";
const string DBNAME = "chatqs";

void ProcessThread()
{
SpacetimeDBClient.instance.Connect(AuthToken.Token, HOST, DBNAME);

// loop until cancellation token
while (!cancel_token.IsCancellationRequested)
{
SpacetimeDBClient.instance.Update();
try {
// loop until cancellation token
while (!cancel_token.IsCancellationRequested) {
conn.Update();

ProcessCommands();
ProcessCommands();

Thread.Sleep(100);
Thread.Sleep(100);
}
}
finally {
conn.Close();
}

SpacetimeDBClient.instance.Close();
}

void InputLoop()
Expand Down Expand Up @@ -192,10 +202,10 @@ void ProcessCommands()
switch (command.Command)
{
case "message":
Reducer.SendMessage(command.Args);
conn.RemoteReducers.SendMessage(command.Args);
break;
case "name":
Reducer.SetName(command.Args);
conn.RemoteReducers.SetName(command.Args);
break;
}
}
Expand Down
23 changes: 20 additions & 3 deletions examples~/quickstart/client/module_bindings/Message.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,31 @@ namespace SpacetimeDB.Types
{
[SpacetimeDB.Type]
[DataContract]
public partial class Message : SpacetimeDB.DatabaseTable<Message, SpacetimeDB.Types.ReducerEvent>
public partial class Message : SpacetimeDB.DatabaseTable<Message, SpacetimeDB.Types.EventContext>
{
[DataMember(Name = "sender")]
public SpacetimeDB.Identity Sender = new();
public SpacetimeDB.Identity Sender;
[DataMember(Name = "sent")]
public ulong Sent;
[DataMember(Name = "text")]
public string Text = "";
public string Text;

public Message(
SpacetimeDB.Identity Sender,
ulong Sent,
string Text
)
{
this.Sender = Sender;
this.Sent = Sent;
this.Text = Text;
}

public Message()
{
this.Sender = new();
this.Text = "";
}

public static IEnumerable<Message> FilterBySender(SpacetimeDB.Identity value)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,9 @@ namespace SpacetimeDB.Types
[SpacetimeDB.Type]
public partial class SendMessageArgsStruct : IReducerArgs
{
ReducerType IReducerArgs.ReducerType => ReducerType.SendMessage;
string IReducerArgsBase.ReducerName => "send_message";
bool IReducerArgs.InvokeHandler(ReducerEvent reducerEvent) => Reducer.OnSendMessage(reducerEvent, this);
bool IReducerArgs.InvokeHandler(EventContext ctx) => ctx.Reducers.InvokeSendMessage(ctx, this);

public string Text = "";
}

public static partial class Reducer
{
public delegate void SendMessageHandler(ReducerEvent reducerEvent, string text);
public static event SendMessageHandler? OnSendMessageEvent;

public static void SendMessage(string text)
{
SpacetimeDBClient.instance.InternalCallReducer(new SendMessageArgsStruct { Text = text });
}

public static bool OnSendMessage(ReducerEvent reducerEvent, SendMessageArgsStruct args)
{
if (OnSendMessageEvent == null) return false;
OnSendMessageEvent(
reducerEvent,
args.Text
);
return true;
}
}

}
25 changes: 1 addition & 24 deletions examples~/quickstart/client/module_bindings/SetNameReducer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,9 @@ namespace SpacetimeDB.Types
[SpacetimeDB.Type]
public partial class SetNameArgsStruct : IReducerArgs
{
ReducerType IReducerArgs.ReducerType => ReducerType.SetName;
string IReducerArgsBase.ReducerName => "set_name";
bool IReducerArgs.InvokeHandler(ReducerEvent reducerEvent) => Reducer.OnSetName(reducerEvent, this);
bool IReducerArgs.InvokeHandler(EventContext ctx) => ctx.Reducers.InvokeSetName(ctx, this);

public string Name = "";
}

public static partial class Reducer
{
public delegate void SetNameHandler(ReducerEvent reducerEvent, string name);
public static event SetNameHandler? OnSetNameEvent;

public static void SetName(string name)
{
SpacetimeDBClient.instance.InternalCallReducer(new SetNameArgsStruct { Name = name });
}

public static bool OnSetName(ReducerEvent reducerEvent, SetNameArgsStruct args)
{
if (OnSetNameEvent == null) return false;
OnSetNameEvent(
reducerEvent,
args.Name
);
return true;
}
}

}
20 changes: 18 additions & 2 deletions examples~/quickstart/client/module_bindings/User.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,31 @@ namespace SpacetimeDB.Types
{
[SpacetimeDB.Type]
[DataContract]
public partial class User : SpacetimeDB.DatabaseTableWithPrimaryKey<User, SpacetimeDB.Types.ReducerEvent>
public partial class User : SpacetimeDB.DatabaseTableWithPrimaryKey<User, SpacetimeDB.Types.EventContext>
{
[DataMember(Name = "identity")]
public SpacetimeDB.Identity Identity = new();
public SpacetimeDB.Identity Identity;
[DataMember(Name = "name")]
public string? Name;
[DataMember(Name = "online")]
public bool Online;

public User(
SpacetimeDB.Identity Identity,
string? Name,
bool Online
)
{
this.Identity = Identity;
this.Name = Name;
this.Online = Online;
}

public User()
{
this.Identity = new();
}

private static Dictionary<SpacetimeDB.Identity, User> Identity_Index = new(16);

public override void InternalOnValueInserted()
Expand Down
Loading

0 comments on commit 8bd8055

Please sign in to comment.