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

Update C# server and client quickstart examples to match tutorial document. #258

Merged
merged 32 commits into from
Mar 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
7c776a8
Bump package versions to 1.0.0
bfops Feb 19, 2025
7777b05
empty commit to bump CI
bfops Feb 19, 2025
613c9cf
Updated DLLs
Feb 26, 2025
7eac77c
Commit meta files
Feb 26, 2025
041dcc7
Updated quickstart folder to quickstart-chat
rekhoff Feb 26, 2025
344b83d
Copy meta file from old codegen dll
Feb 26, 2025
d76b092
Remove unused meta file
Feb 26, 2025
4302e34
Updated client to match output from completing C# client SDK from web…
rekhoff Feb 27, 2025
f973abd
Updates to client SDK generated files from performing tutorial
rekhoff Feb 27, 2025
26ddf71
Added server output from completing C# server module from website
rekhoff Feb 27, 2025
66f465b
Trigger Build
rekhoff Feb 27, 2025
9b704aa
Merge branch 'master' into rekhoff/update-csharp-quickstart-1.0
rekhoff Feb 27, 2025
4c7edeb
Trigger Build
rekhoff Feb 27, 2025
e058a95
Trigger Build
rekhoff Feb 27, 2025
7e4ad51
Updated Visual Studio Solution file with new quickstart-chat client l…
rekhoff Feb 27, 2025
746c12d
Removing server module from SLN, as it adds additional dependencies t…
rekhoff Feb 27, 2025
43840fc
Trigger Build
rekhoff Feb 27, 2025
96d9e24
Updated tests project with new quickstart-chat client path
rekhoff Feb 28, 2025
3597836
Test - reverted imports
Feb 28, 2025
ef7a3e8
Updated test timestamp
rekhoff Feb 28, 2025
c1bfc5e
Changes server table names to lower case
rekhoff Feb 28, 2025
bc74416
Fixed long being used in place of Timestamp
rekhoff Feb 28, 2025
9f82b06
Trigger Build
rekhoff Feb 28, 2025
fc22d29
bump CI
Feb 28, 2025
5a9e243
Matching quicktstart-chat server CSProj file settings to Blackhol.io …
rekhoff Mar 1, 2025
3337df2
Merge branch 'release/latest' into rekhoff/update-csharp-quickstart-1.0
rekhoff Mar 1, 2025
a275224
Merge branch 'master' of https://github.com/clockworklabs/com.clockwo…
rekhoff Mar 1, 2025
7fb3b69
Removing old client module after merging from master to resolve conflict
rekhoff Mar 1, 2025
2d75875
Fixed C# formatting
rekhoff Mar 1, 2025
1c611f1
Clarified we are registering callbacks
rekhoff Mar 3, 2025
9b5e233
Fixes as requested in PR comments
rekhoff Mar 3, 2025
47c8dc6
Removing unintended meta file add.
rekhoff Mar 3, 2025
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
4 changes: 2 additions & 2 deletions SpacetimeDB.ClientSDK.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
<PackageReadmeFile>README.md</PackageReadmeFile>
<RepositoryUrl>https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk</RepositoryUrl>
<AssemblyVersion>1.0.0</AssemblyVersion>
<Version>1.0.0-rc4</Version>
<Version>1.0.0</Version>
<DefaultItemExcludes>$(DefaultItemExcludes);*~/**</DefaultItemExcludes>
<!-- We want to save DLLs for Unity which doesn't support NuGet. -->
<RestorePackagesPath>packages</RestorePackagesPath>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="SpacetimeDB.BSATN.Runtime" Version="1.0.0-rc4" />
<PackageReference Include="SpacetimeDB.BSATN.Runtime" Version="1.0.0" />

<InternalsVisibleTo Include="SpacetimeDB.Tests" />
</ItemGroup>
Expand Down
12 changes: 6 additions & 6 deletions SpacetimeDB.ClientSDK.sln
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,18 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.6.33717.318
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client", "examples~\quickstart\client\client.csproj", "{8F33709C-DEE9-41CC-A477-D6128E3700B1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpacetimeDB.ClientSDK", "SpacetimeDB.ClientSDK.csproj", "{242A8146-A58D-43E9-A2BD-31FFC6851AA6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tests", "tests~\tests.csproj", "{5CD31104-4719-4CE3-8D39-8BAE0B75C085}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client", "examples~\quickstart-chat\client\client.csproj", "{FE261832-1594-DE21-C8C8-2D525680CBD7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8F33709C-DEE9-41CC-A477-D6128E3700B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8F33709C-DEE9-41CC-A477-D6128E3700B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8F33709C-DEE9-41CC-A477-D6128E3700B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8F33709C-DEE9-41CC-A477-D6128E3700B1}.Release|Any CPU.Build.0 = Release|Any CPU
{242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{242A8146-A58D-43E9-A2BD-31FFC6851AA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand All @@ -27,6 +23,10 @@ Global
{5CD31104-4719-4CE3-8D39-8BAE0B75C085}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5CD31104-4719-4CE3-8D39-8BAE0B75C085}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5CD31104-4719-4CE3-8D39-8BAE0B75C085}.Release|Any CPU.Build.0 = Release|Any CPU
{FE261832-1594-DE21-C8C8-2D525680CBD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FE261832-1594-DE21-C8C8-2D525680CBD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FE261832-1594-DE21-C8C8-2D525680CBD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FE261832-1594-DE21-C8C8-2D525680CBD7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,54 +5,101 @@
using SpacetimeDB;
using SpacetimeDB.Types;

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

// our local client SpacetimeDB identity
Identity? local_identity = null;

// declare a thread safe queue to store commands
var input_queue = new ConcurrentQueue<(string Command, string Args)>();

void Main()
{
// Initialize the `AuthToken` module
AuthToken.Init(".spacetime_csharp_quickstart");

// TODO: just do `var conn = DbConnection...` when OnConnect signature is fixed.
// Builds and connects to the database
DbConnection? conn = null;
conn = ConnectToDB();
// Registers callbacks to run in response to database events.
RegisterCallbacks(conn);
// Declare a threadsafe cancel token to cancel the process loop
var cancellationTokenSource = new CancellationTokenSource();
// Spawn a thread to call process updates and process commands
var thread = new Thread(() => ProcessThread(conn, cancellationTokenSource.Token));
thread.Start();
// Handles CLI input
InputLoop();
// This signals the ProcessThread to stop
cancellationTokenSource.Cancel();
thread.Join();
}

/// The URI of the SpacetimeDB instance hosting our chat module.
const string HOST = "http://localhost:3000";

/// The module name we chose when we published our module.
const string DBNAME = "quickstart-chat";

/// Load credentials from a file and connect to the database.
DbConnection ConnectToDB()
{
DbConnection? conn = null;
conn = DbConnection.Builder()
.WithUri(HOST)
.WithModuleName(DBNAME)
//.WithToken(AuthToken.Token)
.OnConnect(OnConnect)
.WithToken(AuthToken.Token)
.OnConnect(OnConnected)
.OnConnectError(OnConnectError)
.OnDisconnect(OnDisconnect)
.OnDisconnect(OnDisconnected)
.Build();
return conn;
}

/// Our `OnConnect` callback: save our credentials to a file.
void OnConnected(DbConnection conn, Identity identity, string authToken)
{
local_identity = identity;
AuthToken.SaveToken(authToken);

conn.SubscriptionBuilder()
.OnApplied(OnSubscriptionApplied)
.SubscribeToAllTables();
}

/// Our `OnConnectError` callback: print the error, then exit the process.
void OnConnectError(Exception e)
{
Console.Write($"Error while connecting: {e}");
}

/// Our `OnDisconnect` callback: print a note, then exit the process.
void OnDisconnected(DbConnection conn, Exception? e)
{
if (e != null)
{
Console.Write($"Disconnected abnormally: {e}");
}
else
{
Console.Write($"Disconnected normally.");
}
}

/// Register all the callbacks our app will use to respond to database events.
void RegisterCallbacks(DbConnection conn)
{
conn.Db.User.OnInsert += User_OnInsert;
conn.Db.User.OnUpdate += User_OnUpdate;

conn.Db.Message.OnInsert += Message_OnInsert;

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

// declare a threadsafe cancel token to cancel the process loop
var cancellationTokenSource = new CancellationTokenSource();

// spawn a thread to call process updates and process commands
var thread = new Thread(() => ProcessThread(conn, cancellationTokenSource.Token));
thread.Start();

InputLoop();

// this signals the ProcessThread to stop
cancellationTokenSource.Cancel();
thread.Join();
}

/// If the user has no set name, use the first 8 characters from their identity.
string UserNameOrIdentity(User user) => user.Name ?? user.Identity.ToString()[..8];

/// Our `User.OnInsert` callback: if the user is online, print a notification.
void User_OnInsert(EventContext ctx, User insertedValue)
{
if (insertedValue.Online)
Expand All @@ -61,6 +108,8 @@ void User_OnInsert(EventContext ctx, User insertedValue)
}
}

/// Our `User.OnUpdate` callback:
/// print a notification about name and status changes.
void User_OnUpdate(EventContext ctx, User oldValue, User newValue)
{
if (oldValue.Name != newValue.Name)
Expand All @@ -80,6 +129,18 @@ void User_OnUpdate(EventContext ctx, User oldValue, User newValue)
}
}

/// Our `Message.OnInsert` callback: print new messages.
void Message_OnInsert(EventContext ctx, Message insertedValue)
{
// We are filtering out messages inserted during the subscription being applied,
// since we will be printing those in the OnSubscriptionApplied callback,
// where we will be able to first sort the messages before printing.
if (ctx.Event is not Event<Reducer>.SubscribeApplied)
{
PrintMessage(ctx.Db, insertedValue);
}
}

void PrintMessage(RemoteTables tables, Message message)
{
var sender = tables.User.Identity.Find(message.Sender);
Expand All @@ -92,15 +153,7 @@ void PrintMessage(RemoteTables tables, Message message)
Console.WriteLine($"{senderName}: {message.Text}");
}

void Message_OnInsert(EventContext ctx, Message insertedValue)
{

if (ctx.Event is not Event<Reducer>.SubscribeApplied)
{
PrintMessage(ctx.Db, insertedValue);
}
}

/// Our `OnSetNameEvent` callback: print a warning if the reducer failed.
void Reducer_OnSetNameEvent(ReducerEventContext ctx, string name)
{
var e = ctx.Event;
Expand All @@ -110,6 +163,7 @@ void Reducer_OnSetNameEvent(ReducerEventContext ctx, string name)
}
}

/// Our `OnSendMessageEvent` callback: print a warning if the reducer failed.
void Reducer_OnSendMessageEvent(ReducerEventContext ctx, string text)
{
var e = ctx.Event;
Expand All @@ -119,34 +173,12 @@ void Reducer_OnSendMessageEvent(ReducerEventContext ctx, string text)
}
}

void OnConnect(DbConnection conn, Identity identity, string authToken)
{
local_identity = identity;
AuthToken.SaveToken(authToken);

var subscription = conn.SubscriptionBuilder()
.OnApplied(OnSubscriptionApplied)
.Subscribe(new string[] {
"SELECT * FROM user",
"SELECT * FROM message",
// It is legal to have redundant subscriptions.
// However, keep in mind that data will be sent over the wire multiple times,
// once for each subscriptions. This can cause slowdowns if you aren't careful.
"SELECT * FROM message" });

// You can also use SubscribeToAllTables, but it should be avoided if you have any large tables:
// conn.SubscriptionBuilder().OnApplied(OnSubscriptionApplied).SubscribeToAllTables();

}

void OnConnectError(Exception e)
{

}

void OnDisconnect(DbConnection conn, Exception? e)
/// Our `OnSubscriptionApplied` callback:
/// sort all past messages and print them in timestamp order.
void OnSubscriptionApplied(SubscriptionEventContext ctx)
{

Console.WriteLine("Connected");
PrintMessagesInOrder(ctx.Db);
}

void PrintMessagesInOrder(RemoteTables tables)
Expand All @@ -157,12 +189,7 @@ void PrintMessagesInOrder(RemoteTables tables)
}
}

void OnSubscriptionApplied(SubscriptionEventContext ctx)
{
Console.WriteLine("Connected");
PrintMessagesInOrder(ctx.Db);
}

/// Our separate thread from main, where we can call process updates and process commands without blocking the main thread.
void ProcessThread(DbConnection conn, CancellationToken ct)
{
try
Expand All @@ -183,6 +210,7 @@ void ProcessThread(DbConnection conn, CancellationToken ct)
}
}

/// Read each line of standard input, and either set our name or send a message as appropriate.
void InputLoop()
{
while (true)
Expand Down
Loading