Giter Club home page Giter Club logo

friflo / friflo.json.fliox Goto Github PK

View Code? Open in Web Editor NEW
115.0 2.0 5.0 31.11 MB

C# ORM for .NET with Messaging and Pub-Sub. C# ECS for high performance DoD.

License: GNU Lesser General Public License v3.0

C# 91.22% HTML 3.95% TypeScript 3.28% Kotlin 0.69% JavaScript 0.04% Dockerfile 0.03% CSS 0.48% Batchfile 0.08% GLSL 0.02% Mathematica 0.21%
c-sharp pub-sub unity websocket authentication authorization code-generator entity json-schema-validator no-sql

friflo.json.fliox's Introduction

JSON Fliox    JSON Fliox SPLASH

nuget  nuget  CI  CD 

new 2024-03-26 · Switched project to more permissive license LGPL v3.0. Before AGPL v3.0. See #41.

new 2024-02-19 · New features in Friflo.Engine.ECS - v.1.17.0
Added new features focusing on performance:

  • Add support for multi threaded query (system) execution.
  • Added command buffers typically used in multi threaded queries.
  • Support entity creation as batch and bulk operation.
  • Support entity changes - add/remove components and tags - as batch and bulk operation.
  • Add SIMD support in multi threaded queries. Execute SIMD operations without a scalar remainder loop.

JSON Fliox

A client / server ORM for .NET for SQL & NoSQL databases with focus on Web apps and performance.
Database access is realized by creating a single class to query, create, update or delete table / container records.

This class - a FlioxClient - provide type safety and support validation, batching, transactions and messaging.
A FlioxHub can be used to serve hosted databases via HTTP using ASP.NET Core or an HttpListener.

As Fliox is an ORM it has similarities to projects like Entity Framework Core, Ruby on Rails, Django or Hibernate


Unique ORM Features

As of writing this the list below show unique features not supported by other ORMs like:
EFCore, Dapper, NHibernate, LINQ to DB, PetaPoco or ServiceStack.

  • Fliox provide two schema models for all SQL databases:

    • Relational - the default - storing each entity class property in its own column.

    • JSON columns storing entities in a single column called: json_data.
      This enables schema changes without database migrations and avoid OR impedance mismatch.

  • Create automatically common REST route handlers GET, PUT, PATCH, DELETE to execute LINQ query filters
    and CRUD operations (bulk or single resource) for each table using ASP.NET Core.

  • FlioxClient's can be used client-side on user devices by using a HTTP or WebSocket connection.
    Using the listed ORMs above require to disclose the database credentials to the public.

  • FlioxClient's can also be used in web applications (JS/WASM) using HTTP or WebSocket's.
    Not supported by the mentioned ORMs as they require proprietary - non HTTP based - protocols.

  • Support Pub-Sub to receive push events for subscribed database changes like: create, update, delete & merge.

  • Provide a Web UI - the Hub Explorer - to explore databases using a web browser.

  • Supports batching. Multiple database operations are combined into a single request send to the server.
    This enables execution of database transactions in a single request and enable non-chatty data communication.

TL;DR

Try the example Hub online running on AWS - DemoHub (EC2 instance: t2-micro, us-east-1)
The DemoHub .NET project is available at 🚀 friflo/Fliox.Examples.

Note: JSON Fliox is not a UI library. It is designed for simple integration in .NET and Web UI frameworks.


🚩 Content


🎨 Features

Compact list of features supported by Clients and Hubs

  • ASP.NET Core & HttpListener integration
    • REST API - JSON Schema / OpenAPI
    • GraphQL API
    • Batch API - HTTP, WebSocket & UDP
  • Database
    • CRUD operations - bulk and single resource
    • Transactions - Begin, Commit & Rollback - for SQL databases
    • Schema
    • Queries - LINQ expressions
    • Container relations (associations)
    • Entity validation
    • Send messages (event) & commands (RPC) with validation
    • Pub-Sub - entity changes, messages and commands
  • Hub Explorer - the admin page
  • Monitoring
  • Authentication / Authorization
  • Code generation
    • C#, Typescript & Kotlin
    • JSON Schema, OpenAPI Schema & GraphQL Schema
    • Schema documentation & class diagram
  • Compatibility
    • Frameworks: .NET, .NET Core, .NET Framework and .NET Standard
    • tested on Windows, macOS, Linux & Unity 2021 or higher

Features are explained in more detail in the sections: Hub and Fliox

Performance characteristics
RTT request / response roundtrip 0.3 ms
Pub-Sub delay send message ➞ subscriber event sub millisecond latency
Pub-Sub throughput FIFO 3 subscribers each using a WebSocket 50k messages / sec
Query request 1M rows, each row 124 byte => response 125MB 1.3 sec
Throughput request / response WebSocket, 4 concurrent clients 27k requests / sec
ASP.NET Core Hub integration 1 LOC Startup.cs
Minimal Client & Server with: REST, CRUD, Queries, Pub-Sub & Explorer 60 LOC Client & Server
            run on Intel(R) Core(TM) i7-4790K CPU 4.00GHz

Quickstart

Direct database access

Create a Console Application and add the following dependencies:
nuget nuget

dotnet add package Friflo.Json.Fliox.Hub
dotnet add package Friflo.Json.Fliox.Hub.SQLite

Create a TodoClient client to specify the database schema.

📄 TodoClient.cs

public class TodoClient : FlioxClient
{
    // --- containers
    public  readonly    EntitySet <long, Job>   jobs;
    
    public TodoClient(FlioxHub hub, string dbName = null) : base (hub, dbName) { }
}

// ---------------------------------- entity models ----------------------------------
public class Job
{
    [Key]       public  long    id;
    [Required]  public  string  title;
                public  bool?   completed;
}

The following code create / open a SQLite database by using TodoClient as the database schema.
It also perform some database operations like: UpsertRange() & Query()

📄 Program.cs

    var schema      = DatabaseSchema.Create<TodoClient>();
    var database    = new SQLiteDatabase("todo_db", "Data Source=todo.sqlite3", schema);
    await database.SetupDatabaseAsync(); // for development: create database or update ist schema
    var hub         = new FlioxHub(database);

    var client      = new TodoClient(hub);
    client.jobs.UpsertRange(new[] {
        new Job { id = 1, title = "Buy milk", completed = true },
        new Job { id = 2, title = "Buy cheese", completed = false }
    });
    var jobs = client.jobs.Query(job => job.completed == true);
    await client.SyncTasks(); // execute UpsertRange & Query task

    foreach (var job in jobs.Result) {
        Console.WriteLine($"{job.id}: {job.title}");
    }
    // output:  1: Buy milk

Run the application

dotnet run

Remote database access

Remote database access - client / servers setup - require two console applications:

  1. HTTP server to host a single - or multiple - databases
  2. HTTP client  to access a hosted database

1. HTTP Server

Add dependency to Hub Explorer to host a Web UI to browse databases.
The Hub Explorer is optional but speedup development. It contains the static files for the Web UI.
nuget

dotnet add package Friflo.Json.Fliox.Hub.Explorer

Replace the code in 📄 Program.cs above to host a database by an HTTP server.

📄 Program.cs (server)

    var schema      = DatabaseSchema.Create<TodoClient>();
    var database    = new SQLiteDatabase("todo_db", "Data Source=todo.sqlite3", schema);
    await database.SetupDatabaseAsync(); // for development: create database or update ist schema
    var hub         = new FlioxHub(database);
    hub.Info.Set ("TodoHub", "dev", "https://github.com/friflo/Fliox.Examples/tree/main/Todo", "rgb(0 171 145)"); // optional
    hub.UseClusterDB(); // required by HubExplorer
    hub.UsePubSub();    // optional - enables Pub-Sub
    // --- create HttpHost
    var httpHost    = new HttpHost(hub, "/fliox/");
    httpHost.UseStaticFiles(HubExplorer.Path); // nuget: https://www.nuget.org/packages/Friflo.Json.Fliox.Hub.Explorer
    
    HttpServer.RunHost("http://localhost:5000/", httpHost); // http://localhost:5000/fliox/

Start the server and check the Hub Explorer is available at http://localhost:5000/fliox/

dotnet run

ASP.NET Core integration

ASP.NET Core integration requires the nuget package.
nuget

dotnet add package Friflo.Json.Fliox.Hub.AspNetCore

Integration into an existing WebApplication app is enabled adding

    app.MapHost("/fliox/{*path}", httpHost);`

Or create an WebApplication from scratch by replacing HttpServer.RunHost() in the snippet above by

    var app = WebApplication.Create();
    app.MapRedirect("/", httpHost);
    app.MapHost("/fliox/{*path}", httpHost);
    app.Run();

C# documentation in Hub Explorer (optional)

The C# documentation of TodoClient and other model classes can be utilized in the Hub Explorer.
Therefor add the following xml snippet to the *.csproj. It will copy the *.xml files next to the *.dll files.
The server read and add the documentation to schema definition.

  <PropertyGroup>
	<GenerateDocumentationFile>True</GenerateDocumentationFile>
  </PropertyGroup>
  <!-- Copy XML files from all PackageReferences to output dir -->
  <Target Name="_ResolveCopyLocalNuGetPkgXmls" AfterTargets="ResolveReferences">
    <ItemGroup>
      <ReferenceCopyLocalPaths Include="@(ReferenceCopyLocalPaths->'%(RootDir)%(Directory)%(Filename).xml')" Condition="'%(ReferenceCopyLocalPaths.NuGetPackageId)'!='' and Exists('%(RootDir)%(Directory)%(Filename).xml')" />
    </ItemGroup>
  </Target>

2. HTTP Client

Create a second Console application to access the hosted database via HTTP.

Add required nuget dependencies
nuget

dotnet add package Friflo.Json.Fliox.Hub

Copy 📄 TodoClient.cs from above to Console project.

  • Note: The intention is to implement the TodoClient and its model classes in a separate library project.
    Client & server applications reference this library as their dependency.
    But for simplicity create a copy in the client application for now.

📄 Program.cs (client)

    var hub     = new WebSocketClientHub("todo_db", "ws://localhost:5000/fliox/");
    var client  = new TodoClient(hub);
    var jobs    = client.jobs.Query(job => job.completed == true);
    client.jobs.SubscribeChanges(Change.All, (changes, context) => {
        Console.WriteLine(changes);
    });
    await client.SyncTasks(); // execute Query & SubscribeChanges task

    foreach (var job in jobs.Result) {
        Console.WriteLine($"{job.id}: {job.title}");
    }
    // output:  1: Buy milk
    Console.WriteLine("\n wait for events ... (exit with: CTRL + C)\n note: generate events by clicking 'Save' on a record in the Hub Explorer\n");
    await Task.Delay(3_600_000); // wait 1 hour

Ensure the server is running and start the client application

dotnet run

Database providers

Database class / nuget connection string examples
in-memory MemoryDatabase none
build-in
file-system FileDatabase path of root folder
build-in
SQLite SQLiteDatabase "Data Source=test_db.sqlite3"
nuget dotnet add package Friflo.Json.Fliox.Hub.SQLite
MySQL MySQLDatabase "Server=localhost;User ID=root;Password=;Database=test_db;"
nuget dotnet add package Friflo.Json.Fliox.Hub.MySQL
MariaDB MariaDBDatabase "Server=localhost;User ID=root;Password=;Database=test_db;"
nuget dotnet add package Friflo.Json.Fliox.Hub.MySQL
PostgreSQL PostgreSQLDatabase "Host=localhost;Username=postgres;Password=postgres;Database=test_db;"
nuget dotnet add package Friflo.Json.Fliox.Hub.PostgreSQL
SQL Server SQLServerDatabase "Data Source=.;Integrated Security=True;Database=test_db"
nuget dotnet add package Friflo.Json.Fliox.Hub.SQLServer

The connection string of each provider is documented in its nuget README

Example snippet to create a database using SQLite looks like:

    var connection  = "Data Source=todo_db.sqlite3";
    var schema      = DatabaseSchema.Create<TodoClient>();
    var database    = new SQLiteDatabase("todo_db", connection, schema);

🚀 Examples

📄   friflo/Fliox.Examples

A separate git repository with two small ready-to-run examples (70 LOC & 550 LOC) using Fliox Clients and Servers.
Build and run a server with Gitpod using VSCode in the browser without installing anything.


screenshot: DemoHub server logs

📦 Hub

Namespace  Friflo.Json.Fliox.Hub.*
Assembly     Friflo.Json.Fliox.Hub.dll  CI

Client

📄   README.md

Fliox clients are strongly typed C# classes used to access SQL or NoSQL databases.
They are implemented by creating a class e.g. MyClient extending FlioxClient.
The database containers are represented as properties in the derived class MyClient.

These classes also acts as a database schemas. They can be assigned to databases hosted on the Hub.
Doing this enables features like:

  • JSON validation of entities aka records
  • generate a JSON Schema, an OpenAPI Schema and a GraphQL Schema
  • generate a HTML Schema documentation and a UML class diagram
  • generate classes for various programming languages: C#, Typescript & Kotlin

The MyClient can be used to declare custom database commands using DTO's as input and result types.

Host

📄   README.md

A HttpHost instance is used to host multiple databases.
It is designed to be integrated into HTTP servers like ASP.NET Core.
This enables access to hosted databases via HTTP, WebSocket or UDP supporting the following Web API's:

  • REST
  • GraphQL
  • Batch API

A FlioxHub instance is used to configure the hosted databases, authentication / authorization and Pub-Sub.
This FlioxHub instance need to be passed to the constructor of the HttpHost

Explorer

📄   README.md
Assembly     Friflo.Json.Fliox.Hub.Explorer.dll  CI

The Hub Explorer is an admin page used to access databases, containers and entities hosted by a Fliox Hub.
The Explorer also enables to execute application specific database commands.


screenshot: Hub Explorer

DB

📄   README.md

Provide a set of support databases used to:

  • serve the Hub configuration - used by the Hub Explorer. Schema: ClusterStore
  • serve monitoring data. Schema: MonitorStore
  • perform user authentication, authorization and management. Schema: UserStore

Protocol

📄   README.md

The Protocol is the communication interface between a FlioxClient and a FlioxHub.
Web clients can use this Protocol to access a Hub using the Batch API via HTTP & JSON.
A language specific API - e.g. written in Typescript, Kotlin, ... - is not a requirement.

The Protocol is not intended to be used by C# .NET clients directly.
Instead they are using a FlioxClient that is optimized to transform API calls into the Protocol.



📦 Fliox

Namespace  Friflo.Json.Fliox.*
Assembly     Friflo.Json.Fliox.dll  CI

Schema

📄   README.md

This module enables transforming schemas expressed by a set of C# classes into other programming languages and schema formats like:

  • C#, Typescript, Kotlin
  • HTML documentation, Schema Class Diagram
  • JSON Schema, OpenAPI Schema, GraphQL Schema

Its main purpose is to generate schemas and types for various languages of classes extending FlioxClient.
The screenshots below show Hub pages utilizing the schemas mentioned above.


screenshot: MonitorStore schema as class diagram


screenshots: Schema documentation, Swagger UI & GraphiQL

Mapper

📄   README.md

This module enables serialization / deserialization of C# .NET objects to / from JSON.
Its feature set and API is similar to the .NET packages:

The module is utilized by the assembly Friflo.Json.Fliox.Hub to serialize entities and DTO's.
Its also used for serialization of the supported protocols: REST, GraphQL and Batch API.



🔧 Project

API

The Fliox C# .NET API is CLS-compliant
The API is available at fliox-docs API Reference

Properties

The goal of the library, its components and API is to be easy digestible for software developers.
The properties describe the characteristics of this project - at least what it aims for.
These properties are targeted to the needs of users using the library.
They fit mostly the aspects described in CUPID-for joyful coding.

Topics of the CUPID properties focused by this project are

  • Composable
    • No 3rd party dependencies
    • Compatibility .NET Core 3.1 or higher, .NET Framework 4.6.2 or higher and Unity 2020.1 or higher
    • Seamless integration into existing ASP.NET Core applications with a handful lines of code
    • Independence from other parts of existing applications
    • Fliox Clients and Hubs are unit testable without mocking
    • Replace the underlying database without changing application code
    • Add custom code / schema generators without changing the application code
  • Predictable
    • API surface is as small as possible
    • API: class, method and property names are short, simple, and easy to pronounce
    • Observable
      • Monitoring is integral part of the Hub
      • The ToString() methods of classes show only relevant state to avoid noise in debugging sessions
      • Error and runtime assertion messages are short and expressive
  • Domain based
    • Enable implementing compact applications which are easy to read and to maintain

Principles

A set of rules followed by this project to aim for simplicity and performance. See Principles

Build

📄   README.md

The project Json.Tests contains a console application and unit tests.
Build and run instructions for .NET and Unity are in the README file.

unit tests
Code coverage: 86% measured with JetBrains • docCover

Passed! - Failed: 0, Passed: 842, Skipped: 0, Total: 842, Duration: 7 s - Friflo.Json.Tests.dll (net6.0)

summarized logs of unit test execution - they are executed in   CI


🔥 Motivation

The main driver of this project is the development of an competitive online multiplayer game - a still unresolved task in my todo list.
The foundation to achieve this is commonly a module called Netcode in online multiplayer games.
The key aspects of Netcode are: Synchronizing game state, messaging, low latency, high throughput, minimal use of system resources, reliability & easy to use API.
As Unity is selected as the Game engine C# .NET is the way to go.

Another objective is to create an open source software project which may have the potential to be popular.
As I have 15+ years experience as a software developer in enterprise environment - Shout-Out to HERE Technologies - I decided to avoid a Vendor Lock-In to Unity and target for a solution which fits also the needs of common .NET projects.
So development is entirely done with .NET Core while checking Unity compatibility on a regular basis.

The result is a project with a feature set useful in common & gaming projects and targeting for optimal performance.
The common ground of both areas is the need of databases.
In context of game development the game state (Players, NPC, objects, ...) is represented as an in-memory database to enable low latency, high throughput and minimal use of system resources.
In common projects databases are used to store any kind of data persistent by using a popular DBMS.
Specific for online gaming is the ability to send messages from one client to another in real time. This is enabled by supporting Pub-Sub with sub millisecond latency on localhost.


🙏 Credits

NUnit C# unit testing of the library in the CLR and Unity
FluentAssertions C# unit testing of the library
SQLitePCL.raw C# used by DB Provider for SQLite
SqlClient C# used by DB Provider for Microsoft SQL Server
MySqlConnector C# used by DB Provider for MySQL, MariaDB and MySQL compatible DBMS
Npgsql C# used by DB Provider for PostgreSQL
Microsoft.Azure.Cosmos C# used by DB Provider for CosmosDB
SIPSorcery C# WebRTC - Real-time communication between Web clients without server
GraphQL.NET Parser C# used by package: Friflo.Json.Fliox.Hub.GraphQL
MdDocs C# for fliox-docs API Reference
.NET platform C# .NET the platform providing compiler, runtime, IDE's & ASP.NET Core
Swagger static JS a REST / OpenAPI UI linked by the Hub Explorer
GraphiQL static JS a GraphQL UI linked by the Hub Explorer
Mermaid static JS class diagram for database schema linked by the Hub Explorer
Monaco Editor static JS used as JSON editor integrated in the Hub Explorer
WinMerge Application heavily used in this project
Inscape Application to create SVG's for this project

💖 Like this project?
Leave a ⭐ at  friflo/Friflo.Json.Fliox

Happy coding!


License

This project is licensed under LGPLv3.

friflo JSON Fliox
Copyright © 2024   Ullrich Praetz

friflo.json.fliox's People

Contributors

friflo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

friflo.json.fliox's Issues

notes for version: v0.30.0 - add transaction support for SQL dataabases

New feature

Add Transaction interface to FlioxClient. Will become relevant when publishing SQL Providers:
SQLite, MySQL, MariaDB, Postgres & SQL Server.

        /// <summary>Begin a transaction containing all subsequent <see cref="SyncTask"/>'s.<br/>
        /// The transaction ends by either calling <see cref="FlioxClient.SyncTasks"/> or explicit by
        /// <see cref="TransactionCommit"/> / <see cref="TransactionRollback"/></summary>
        public CommandTask<TransactionResult>   TransactionBegin()          => send.Command<TransactionResult>();

        /// <summary>Commit a transaction started previously with <see cref="TransactionBegin"/></summary>
        public CommandTask<TransactionResult>   TransactionCommit()         => send.Command<TransactionResult>();

        /// <summary>Rollback a transaction started previously with <see cref="TransactionBegin"/></summary>
        public CommandTask<TransactionResult>   TransactionRollback()       => send.Command<TransactionResult>();

notes for version: v0.27.0 - new interface: `IServiceCommands`

New interface to add custom database commands.

  • This enables adding command handler methods from any class implementing IServiceCommands
  • It also avoids confusing having protected DatabaseService methods available, which are
    commonly not intended to be used.
    // old
    new MemoryDatabase("test", new DemoService());              // DemoService extended DatabaseService

    // new
    new MemoryDatabase("test").AddCommands(new DemoCommands()); // DemoCommands implements IServiceCommands

Implement missing operations in Cosmos DB adapter

Implement missing cases in QueryCosmos.cs.

Ensure test coverage for every case.

Operations:

  • arithmetic operations

    • Abs
    • Ceiling
    • Floor
    • Exp
    • Log
    • Sqrt
  • aggregate

    • Min
    • Max
    • Sum
    • Count
    • Average
    • Contains
    • StartsWith
    • EndsWith
  • binary comparison

    • Equal
    • NotEqual
    • LessThan
    • LessThanOrEqual
    • GreaterThan
    • GreaterThanOrEqual
  • group

    • OrElse
    • AndAlso
  • binary arithmetic

    • Add
    • Subtract
    • Multiply
    • Divide
    • Modulo

notes for version: v0.11.0

  • introduced Role.hubRights.queueEvents to authorize command std.Client setting queueEvents = true
    Queueing events for disconnected WebSocket client may allocate much memory on the heap.
    So clients asking for queueEvents require authorization
  • introduced fields to command std.User > UserResult: groups, clients, counts
  • introduced fields to command std.Client > ClientResult: clientId, subscriptionEvents
  • ObjectMapper - changed order of class member for generated types (TS, Kotlin, ...)
    members of extended class are above members of derived classes
  • API changes:
    • UserAuth.Role changes
      • rename rights -> taskRights
      • rename TaskRight discriminators:
        allow -> dbFull
        task -> dbTask
        container -> dbContainer
    • moved / rename model classes from: DB.Monitor -> DB.Cluster
      • EventDelivery - > SubscriptionEvents
      • ChangeSubscription
      • RequestCount
  • improved performance to dispatch events to subscribed clients in EventDispatcher
  • simplified setting default permission by Authenticator: introduced AnonymousTaskAuthorizer & AnonymousHubPermission

notes for version: v0.15.0 - perf optimizations, protocol change

version: 0.15.0

Main focus of release was optimization. Especially for Unity Netcode
Optimization goals:

  • removing heap allocation if possible. E.g. be using buffers
  • remove async method calls if possible
  • replacing Protocol task "patch" by "merge". See below
  • Breaking API changes

    • Client: removed EntitySet<,>.Patch() methods. see: 0118497
      reasons:
      • methods were too complex in usage
      • implementation is inherent slow due to massive heap allocations
    • Host: FlioxHub.ExecuteRequestAsync() and .ExecuteRequest() requires now a preceding
      call to FlioxHub.InitSyncRequest()
    • changed EventDisptacher constructor: EventDispatcher(bool background) -> EventDispatcher(EventDispatching)
      EventDispatcher(false) -> (EventDispatching.Direct)
      EventDispatcher(true) -> (EventDispatching.QueueSend)
      new: EventDispatcher(EventDispatching.Queue)
  • Breaking Protocol changes

    • replaced sync request task "patch" by "merge" PatchEntities -> MergeEntities.
      "merge" [RFC 7386: JSON Merge Patch] https://www.rfc-editor.org/rfc/rfc7386
      "patch" [RFC 6902: JavaScript Object Notation (JSON) Patch] https://www.rfc-editor.org/rfc/rfc6902
      reasons:
      • simplicity
        • a "merge" is easy to understand and compact in usage
        • a "merge" is always idempotent
        • a "patch" is not always idempotent. e.g. Remove by index
        • a full "patch" implementation is complex and not required by Fliox
      • performance - a "merge" outperforms a "patch" by magnitudes.
  • New features / API's

    • introduced JsonMerger as an efficient implementation of [RFC 7386: JSON Merge Patch] https://www.rfc-editor.org/rfc/rfc7386
    • introduced JsonAstReader to create a tree representation from a given JSON value. Used by JsonMerger
    • add new button 'Patch' to Hub Explorer additional to 'Delete' and 'Save'
    • add FlioxClient.SyncTasksSynchronous() - can be used if all tasks can be executed synchronously
      throws an exception if execution cannot be executed synchronously
    • add synchronous versions of EntityContainer methods for databases supporting synchronous execution like a MemoryDatabase
  • Unity

    • dropped support for compiling with preprocessor directive: JSON_BURST
    • optimize string equality test for Unity by introducing struct SmallString
  • CLR

    • update all nuget dependencies
      • NUnit3TestAdapter 4.3.1
      • Microsoft.NET.Test.Sdk 17.4.0
      • FluentAssertions 6.8.0
      • Microsoft.Azure.Cosmos 3.31.2
      • Microsoft.Extensions.Configuration.Json 7.0.0
    • dropped support IL code generation -> replaced by source code generation
  • Optimizations

    • avoid async calls when execution requests to avoid task allocation and reduce callstack depth
      in case a requests can be executed synchronously no async method is called
    • reuse object instances if possible to avoid memory allocations
      • reuse objects in ObjectReader using an InstanceBuffer
      • reuse objects of FlioxClient.SyncTasks() with SyncResult.Reuse()
    • minimize heap allocations when creating tasks with a FlioxClient
    • reduce size of JsonKey by 8 bytes
    • removed redundant byte[] copies when using an ObjectReader
    • Pub-Sub optimizations
      • minimize CPU usage when filtering tasks by subscribers
      • optimize sync event creation: reduce heap allocations
      • introduced Deque<> for queueing events without heap allocation
    • avoid heap allocations and byte[] copy when ReadAsync from Stream's
    • support reusing of byte[] values in MemoryContainer for small values
    • removed all async calls when executing a query on a MemoryContainer
    • optimize reading polymorphic types in ObjectReader
    • generate source code to Write() JSON and reading JSON fields
      This removes heap allocation caused by PropertyInfo / FieldInfo .GetValue() and .SetValue()

notes for version: v0.47.0 - Introduced support for relational tables. Change: create / update SQL databases explicit

New feature

This feature has its origin at: Support for 'true' relational schema

All SQL Provider - SQLite, MySQL, MariaDB, PostgreSQL & SQL Server- now support two storage modes

  • TableType.Relational (default) - each entity class field/property is stored in a separate typed column
  • TableType.JsonColumn - The entire object is stored in a single column json_data

To enable JsonColumn mode set the init-only property of an EntityDatabase. E.g.

    new SQLiteDatabase("sqlite_db", connectionString, schema) { TableType = TableType.JsonColumn }

Behavior change

  • Before: When accessing (reading from / writing to) a table the table was created automatically if it was not present in the database.
  • Now: A databases, its tables and their columns are not created automatically anymore.
    On service start call EntityDatabase.SetupDatabaseAsync() to create a database or update its schema.
    See: EntityDatabase.SetupDatabaseAsync()
    var schema      = DatabaseSchema.Create<TodoClient>();
    var database    = new SQLiteDatabase("todo_db", "Data Source=todo.sqlite3", schema);
    await database.SetupDatabaseAsync().ConfigureAwait(false);

notes for version: v0.31.0 - add extension methods to simplify `FlioxHub` configuration

Simplify

add extension methods to simplify server configuration

public static class HubExtensions
{
    public static void UseClusterDB();
    public static void UseMonitorDB();
    public static void UsePubSub();
    public static async Task UseUserDB();
}

public static class HttpHostExtensions
{
    public static void UseStaticFiles();
}

public static class GraphQLExtensions
{
    public static void UseGraphQL();
}

notes for version: v0.28.0 - changed schema for an `EntityDatabase` to constructor parameter

Breaking changes

Changed assignment of a DatabasSchema to an EntityDatabase.

Previous: used init only setter Schema

    var database = new MemoryDatabase(dbName) { Schema = Schema };

Now: used constructor parameter DatabasSchema schema

    var database = new MemoryDatabase(dbName, Schema);

Reason: SQL databases require a Schema. So a missing schema ensures a fail fast in their constructor.

Performance

Changed EntitySet<,> from class to struct to speedup construction of a class extending FlioxClient using EntitySet<,> as fields / properties to define database containers.
E.g. new MyTestClient(hub) with seven EntitySet<,> fields take ~ 0.5 µs and allocates ~ 900 bytes

notes for version: v0.16.0 - Unity integration, perf optimization, add UDP support

Main focus of release was Unity integration & performance

  • Features:

    • Introduced support for UDP client/server for remote access
    • Small adaptations for MacOS - especially UDP and file-system database - to enable
      unit tests having same behavior as on Windows and Linux.
  • Optimizations
    The main goal was to enable a NetCode implementation without any heap allocation and minimize CPU
    load to maximize CCU (players) at 60 Hz tick rate in Unity.

    Current state 350-400 CCU on 4 Core i7-4790K CPU 4.00GHz.
    Host and simulated CCU's running an same machine using raw UDP.
    Unity Player running as Host 20% CPU. CCU Simulation for 350-400 players 60 CPU%

Implemented:

  • Enable omitting message fields in application protocol which are not mandatory
  • Used smaller field names in protocol. Typically 3 or 4 characters
  • Introduced struct SmallString (small string optimization using 24 bytes) to avoid heap allocation for string's <= 15 characters (UTF-8)
  • Introduced support for synchronous request execution to avoid heap allocation caused by async methods
  • Introduced support for queued request execution to enable allocation free & thread-safe access to memory database without locking
  • Pool/reuse class instances used for de-/serialization.
  • Reduced sizeof JsonKey to 24 bytes.

notes for version: v0.26.0 - add init only setter for `EntityDatabase`, improved query cursor interface

Breaking changes

  1. Change property EntityDatabase.Schema to init only setter.
    This was done to ensure that a Schema assigned to an EntityDatabase is available after database instantiation and cannot be mutated afterwards.
  2. Changed interface and declaration of DatabaseService command handlers.
    Two reason for this change:
  • Made declaration of command handler explicit by annotating every command handler method
    with the attribute [CommandHandler].
    Previously command handlers were added by calling DatabaseService.AddMessageHandlers()
  • Added generic Result<> type for command handlers to enable returning command errors like:
   return Result.Error("some error message");

So signature of command handler methods changes:

    // --- asynchronous
    // old
    async Task<TResult> MyMethod(Param<TParam> param, MessageContext context)
    // new
    [CommandHandler]
    async Task<Result<TResult>> MyMethod(Param<TParam> param, MessageContext context)

    // --- synchronous
    // old
    async TResult MyMethod(Param<TParam> param, MessageContext context)
    // new
    [CommandHandler]
    async Result<TResult> MyMethod(Param<TParam> param, MessageContext context)

New features:

  1. Added interfaces to simplify cursor queries:
    bool QueryTask<,>.IsFinished
    bool QueryTask<,>.QueryNext()
  1. Added mermaid.min.js to Fliox.Hub.Explorer.
    Previously is referenced: https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js
    Goals:
    • Avoid issues if behavior of external JavaScript library changes
    • Enable showing class diagram without internet connection

notes for version: v0.29.0 - perf optimization to create a `FlioxClient`

Performance

improved instantiation performance of classes extending FlioxClient

Memory:      ~ 632 + 24 * (EntitySet count) [bytes]
Execution:   ~ 350 + 10 * (EntitySet count) [ns]
Allocations: 6 (independent from EntitySet count)

DX

  • improved InvalidTypeExceptions throw by FlioxClient to ensure type consistency of EntitySet<,>.
  • throw InvalidTypeException's with minimal stacktrace. E.g.
Missing primary [Key] field/property in entity type: MissingKeyEntity. Used by: MissingKeyStore.entities

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.