Skip to content

Commit

Permalink
Merge branch 'main' into perf/ws-client
Browse files Browse the repository at this point in the history
  • Loading branch information
Odonno authored Mar 27, 2024
2 parents 4401b34 + aff390a commit bef04c4
Show file tree
Hide file tree
Showing 46 changed files with 698 additions and 125 deletions.
30 changes: 15 additions & 15 deletions SurrealDb.Examples.Blazor.Server/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,40 +35,42 @@
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

_ = Task.Run(async () =>
{
await InitializeDbAsync(app.Services);
});
await InitializeDbAsync();

app.Run();

async Task InitializeDbAsync(IServiceProvider serviceProvider)
async Task InitializeDbAsync()
{
await DefineSchemaAsync(serviceProvider);
var surrealDbClient = new SurrealDbClient(
SurrealDbOptions
.Create()
.FromConnectionString(configuration.GetConnectionString("SurrealDB")!)
.Build()
);

await DefineSchemaAsync(surrealDbClient);

var tasks = new[]
{
GenerateWeatherForecastsAsync(serviceProvider),
GenerateKanbanAsync(serviceProvider)
GenerateWeatherForecastsAsync(surrealDbClient),
GenerateKanbanAsync(surrealDbClient)
};

await Task.WhenAll(tasks);
}

async Task DefineSchemaAsync(IServiceProvider serviceProvider)
async Task DefineSchemaAsync(ISurrealDbClient surrealDbClient)
{
string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "schema.surql");
string schema = File.ReadAllText(filePath, Encoding.UTF8);

var surrealDbClient = serviceProvider.GetRequiredService<ISurrealDbClient>();
await surrealDbClient.RawQuery(schema);
}

async Task GenerateWeatherForecastsAsync(IServiceProvider serviceProvider)
async Task GenerateWeatherForecastsAsync(ISurrealDbClient surrealDbClient)
{
const int initialCount = 5;
var weatherForecasts = new WeatherForecastFaker().Generate(initialCount);
var surrealDbClient = serviceProvider.GetRequiredService<ISurrealDbClient>();

var tasks = weatherForecasts.Select(weatherForecast =>
surrealDbClient.Create(WeatherForecast.Table, weatherForecast)
Expand All @@ -77,10 +79,8 @@ async Task GenerateWeatherForecastsAsync(IServiceProvider serviceProvider)
await Task.WhenAll(tasks);
}

async Task GenerateKanbanAsync(IServiceProvider serviceProvider)
async Task GenerateKanbanAsync(ISurrealDbClient surrealDbClient)
{
var surrealDbClient = serviceProvider.GetRequiredService<ISurrealDbClient>();

var existingColumns = await surrealDbClient.Select<ColumnRecord>(ColumnRecord.Table);
if (existingColumns.Any())
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
}
},
"ConnectionStrings": {
"SurrealDB": "Server=ws://127.0.0.1:8000/rpc;Namespace=examples;Database=blazor.server;Username=root;Password=root"
"SurrealDB": "Server=ws://127.0.0.1:8000/rpc;Namespace=examples;Database=blazor.server;Username=root;Password=root;NamingPolicy=SnakeCase"
}
}
2 changes: 1 addition & 1 deletion SurrealDb.Examples.Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
Console.WriteLine(ToJsonString(people));

var queryResponse = await db.Query(
$"SELECT marketing, count() FROM type::table({TABLE}) GROUP BY marketing"
$"SELECT Marketing, count() AS Count FROM type::table({TABLE}) GROUP BY Marketing"
);
var groups = queryResponse.GetValue<List<Group>>(0);
Console.WriteLine(ToJsonString(groups));
Expand Down
2 changes: 1 addition & 1 deletion SurrealDb.Examples.MinimalApis/Models/WeatherForecast.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace SurrealDb.Examples.MinimalApis.Models;
/// </summary>
public class WeatherForecast : Record
{
internal const string Table = "weather_forecast";
internal const string Table = "weatherForecast";

/// <summary>
/// Date of the weather forecast.
Expand Down
2 changes: 2 additions & 0 deletions SurrealDb.Examples.MinimalApis/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
});
services.AddSurreal(configuration.GetConnectionString("SurrealDB")!);

// 💡 Be sure to have "NamingPolicy=CamelCase" in your connection string for PATCH methods to work as expected.

var app = builder.Build();

if (app.Environment.IsDevelopment())
Expand Down
2 changes: 1 addition & 1 deletion SurrealDb.Examples.MinimalApis/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
},
"AllowedHosts": "*",
"ConnectionStrings": {
"SurrealDB": "Server=ws://127.0.0.1:8000/rpc;Namespace=test;Database=test;Username=root;Password=root"
"SurrealDB": "Server=ws://127.0.0.1:8000/rpc;Namespace=examples;Database=minimalapis;Username=root;Password=root;NamingPolicy=CamelCase"
}
}
17 changes: 9 additions & 8 deletions SurrealDb.Examples.TodoApi.Aot/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,11 @@
}
);

_ = Task.Run(async () =>
{
await InitializeDbAsync(app.Services);
});
await InitializeDbAsync();

app.Run();

async Task InitializeDbAsync(IServiceProvider serviceProvider)
async Task InitializeDbAsync()
{
var sampleTodos = new Todo[]
{
Expand All @@ -59,9 +56,13 @@ async Task InitializeDbAsync(IServiceProvider serviceProvider)
new(5, "Clean the car", DateOnly.FromDateTime(DateTime.Now.AddDays(2)))
};

using var scope = serviceProvider.CreateScope();

var surrealDbClient = scope.ServiceProvider.GetRequiredService<ISurrealDbClient>();
var surrealDbClient = new SurrealDbClient(
SurrealDbOptions
.Create()
.FromConnectionString(configuration.GetConnectionString("SurrealDB")!)
.Build(),
appendJsonSerializerContexts: () => jsonSerializerContexts
);

var tasks = sampleTodos.Select(async todo =>
{
Expand Down
2 changes: 1 addition & 1 deletion SurrealDb.Examples.TodoApi.Aot/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
},
"AllowedHosts": "*",
"ConnectionStrings": {
"SurrealDB": "Server=ws://127.0.0.1:8000/rpc;Namespace=test;Database=test;Username=root;Password=root"
"SurrealDB": "Server=ws://127.0.0.1:8000/rpc;Namespace=examples;Database=aot;Username=root;Password=root"
}
}
2 changes: 1 addition & 1 deletion SurrealDb.Examples.WeatherApi/appsettings.Development.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
}
},
"ConnectionStrings": {
"SurrealDB": "Server=ws://127.0.0.1:8000/rpc;Namespace=examples;Database=weather;Username=root;Password=root"
"SurrealDB": "Server=ws://127.0.0.1:8000/rpc;Namespace=examples;Database=weather;Username=root;Password=root;NamingPolicy=CamelCase"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@ namespace Microsoft.AspNetCore.Builder;

public static class SurrealDbMinimalApisExtensions
{
private static string ToSnakeCase(this string str)
{
return JsonNamingPolicy.SnakeCaseLower.ConvertName(str);
}

/// <summary>
/// Adds a complete list of <see cref="RouteEndpoint"/> to the <see cref="IEndpointRouteBuilder"/> that matches HTTP requests for the specified pattern.
/// This method will add the following routes by default:
Expand Down Expand Up @@ -123,7 +118,6 @@ public static IEndpointRouteBuilder MapSurrealEndpoints<TEntity, TDbClient>(
where TDbClient : ISurrealDbClient
{
string entityName = typeof(TEntity).Name;
string tableName = entityName.ToSnakeCase();

var group = endpoints.MapGroup(pattern);

Expand All @@ -139,11 +133,12 @@ public static IEndpointRouteBuilder MapSurrealEndpoints<TEntity, TDbClient>(
"/",
(TDbClient surrealDbClient, CancellationToken cancellationToken) =>
{
string tableName = options?.TableName ?? GetDefaultTableName(entityName, surrealDbClient.NamingPolicy);
return surrealDbClient.Select<TEntity>(tableName, cancellationToken);
}
)
.WithName($"GetAll{entityName}")
.WithSummary($"Get all records from {tableName} table.")
.WithSummary($"Get all {entityName} records.")
.Produces<IEnumerable<TEntity>>()
.WithOpenApi();
}
Expand All @@ -159,6 +154,7 @@ public static IEndpointRouteBuilder MapSurrealEndpoints<TEntity, TDbClient>(
CancellationToken cancellationToken
) =>
{
string tableName = options?.TableName ?? GetDefaultTableName(entityName, surrealDbClient.NamingPolicy);
var data = await surrealDbClient.Select<TEntity>(
(tableName, id),
cancellationToken
Expand All @@ -171,7 +167,7 @@ CancellationToken cancellationToken
}
)
.WithName($"Get{entityName}")
.WithSummary($"Get a single record from {tableName} table.")
.WithSummary($"Get a single {entityName} record.")
.Produces<TEntity>()
.ProducesProblem(StatusCodes.Status404NotFound)
.WithOpenApi();
Expand All @@ -188,11 +184,12 @@ CancellationToken cancellationToken
CancellationToken cancellationToken
) =>
{
string tableName = options?.TableName ?? GetDefaultTableName(entityName, surrealDbClient.NamingPolicy);
return surrealDbClient.Create(tableName, data, cancellationToken);
}
)
.WithName($"Create{entityName}")
.WithSummary($"Create a record in {tableName} table.")
.WithSummary($"Create a {entityName} record.")
.Produces<TEntity>()
.WithOpenApi();
}
Expand All @@ -212,7 +209,7 @@ CancellationToken cancellationToken
}
)
.WithName($"Update{entityName}")
.WithSummary($"Update a record in {tableName} table.")
.WithSummary($"Update a {entityName} record.")
.Produces<TEntity>()
.WithOpenApi();
}
Expand All @@ -228,11 +225,12 @@ CancellationToken cancellationToken
CancellationToken cancellationToken
) =>
{
string tableName = options?.TableName ?? GetDefaultTableName(entityName, surrealDbClient.NamingPolicy);
return surrealDbClient.PatchAll(tableName, patches, cancellationToken);
}
)
.WithName($"PatchAll{entityName}")
.WithSummary($"Patch all records in {tableName} table.")
.WithSummary($"Patch all {entityName} records.")
.Produces<IEnumerable<TEntity>>()
.WithOpenApi();
}
Expand All @@ -249,11 +247,12 @@ CancellationToken cancellationToken
CancellationToken cancellationToken
) =>
{
string tableName = options?.TableName ?? GetDefaultTableName(entityName, surrealDbClient.NamingPolicy);
return surrealDbClient.Patch((tableName, id), patches, cancellationToken);
}
)
.WithName($"Patch{entityName}")
.WithSummary($"Patch a single record in {tableName} table.")
.WithSummary($"Patch a single {entityName} record.")
.Produces<TEntity>()
.WithOpenApi();
}
Expand All @@ -265,11 +264,12 @@ CancellationToken cancellationToken
"/",
(TDbClient surrealDbClient, CancellationToken cancellationToken) =>
{
string tableName = options?.TableName ?? GetDefaultTableName(entityName, surrealDbClient.NamingPolicy);
return surrealDbClient.Delete(tableName, cancellationToken);
}
)
.WithName($"DeleteAll{entityName}")
.WithSummary($"Delete the {tableName} table.")
.WithSummary($"Delete all {entityName} records.")
.Produces(StatusCodes.Status200OK)
.WithOpenApi();
}
Expand All @@ -285,6 +285,7 @@ CancellationToken cancellationToken
CancellationToken cancellationToken
) =>
{
string tableName = options?.TableName ?? GetDefaultTableName(entityName, surrealDbClient.NamingPolicy);
bool success = await surrealDbClient.Delete(
(tableName, id),
cancellationToken
Expand All @@ -297,12 +298,50 @@ CancellationToken cancellationToken
}
)
.WithName($"Delete{entityName}")
.WithSummary($"Delete a record in {tableName} table.")
.WithSummary($"Delete a {entityName} record.")
.Produces(StatusCodes.Status200OK)
.ProducesProblem(StatusCodes.Status404NotFound)
.WithOpenApi();
}

return endpoints;
}

private static string GetDefaultTableName(string entityName, string? namingPolicy)
{
return (namingPolicy?.ToLowerInvariant()) switch
{
"camelcase" => entityName.ToCamelCase(),
"snakecase" or "snakecaselower" => entityName.ToSnakeCaseLower(),
"snakecaseupper" => entityName.ToSnakeCaseUpper(),
"kebabcase" or "kebabcaselower" => entityName.ToKebabCaseLower(),
"kebabcaseupper" => entityName.ToKebabCaseUpper(),
_ => entityName
};
}

private static string ToCamelCase(this string str)
{
return JsonNamingPolicy.CamelCase.ConvertName(str);
}

private static string ToSnakeCaseLower(this string str)
{
return JsonNamingPolicy.SnakeCaseLower.ConvertName(str);
}

private static string ToSnakeCaseUpper(this string str)
{
return JsonNamingPolicy.SnakeCaseUpper.ConvertName(str);
}

private static string ToKebabCaseLower(this string str)
{
return JsonNamingPolicy.KebabCaseLower.ConvertName(str);
}

private static string ToKebabCaseUpper(this string str)
{
return JsonNamingPolicy.KebabCaseUpper.ConvertName(str);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,10 @@ public class SurrealDbMinimalApisOptions
/// A set of tags to be used to document the generated endpoints using OpenAPI.
/// </summary>
public string[]? Tags { get; set; }

/// <summary>
/// The name of the SurrealDB table to be used in the generated endpoints.
/// Defaults to the type name.
/// </summary>
public string? TableName { get; set; }
}
7 changes: 6 additions & 1 deletion SurrealDb.Net.Benchmarks/BaseBenchmark.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Text;
using System.Text;
using System.Text.Json.Serialization;
using SurrealDb.Net.Benchmarks.Constants;

Expand All @@ -9,6 +9,7 @@ public class BaseBenchmark
public static string Host { get; } = "127.0.0.1:8000";
protected string HttpUrl { get; } = $"http://{Host}";
protected string WsUrl { get; } = $"ws://{Host}/rpc";
protected string NamingPolicy { get; } = "SnakeCase";

private readonly Func<JsonSerializerContext[]>? _funcJsonSerializerContexts;

Expand Down Expand Up @@ -37,6 +38,7 @@ protected async Task CreatePostTable(string url, DatabaseInfo databaseInfo)
{
var client = new SurrealDbClient(
url,
NamingPolicy,
appendJsonSerializerContexts: GetFuncJsonSerializerContexts()
);
InitializeSurrealDbClient(client, databaseInfo);
Expand All @@ -49,6 +51,7 @@ protected async Task CreateEcommerceTables(string url, DatabaseInfo databaseInfo
{
var client = new SurrealDbClient(
url,
NamingPolicy,
appendJsonSerializerContexts: GetFuncJsonSerializerContexts()
);
InitializeSurrealDbClient(client, databaseInfo);
Expand All @@ -65,6 +68,7 @@ protected async Task<List<GeneratedPost>> SeedData(
{
var client = new SurrealDbClient(
url,
NamingPolicy,
appendJsonSerializerContexts: GetFuncJsonSerializerContexts()
);
InitializeSurrealDbClient(client, databaseInfo);
Expand All @@ -91,6 +95,7 @@ protected async Task<Post> GetFirstPost(string httpUrl, DatabaseInfo databaseInf
{
var client = new SurrealDbClient(
httpUrl,
NamingPolicy,
appendJsonSerializerContexts: GetFuncJsonSerializerContexts()
);
InitializeSurrealDbClient(client, databaseInfo);
Expand Down
Loading

0 comments on commit bef04c4

Please sign in to comment.