Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/kekyo/fluorite
Simplest and fully-customizable RPC standalone infrastructure.
https://github.com/kekyo/fluorite
async bidirectional complementary dotnet full-duplex json rpc-client rpc-server standalone transport websocket
Last synced: 4 months ago
JSON representation
Simplest and fully-customizable RPC standalone infrastructure.
- Host: GitHub
- URL: https://github.com/kekyo/fluorite
- Owner: kekyo
- License: apache-2.0
- Created: 2021-03-16T00:24:47.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2021-09-14T12:38:20.000Z (over 3 years ago)
- Last Synced: 2024-05-29T01:33:55.832Z (9 months ago)
- Topics: async, bidirectional, complementary, dotnet, full-duplex, json, rpc-client, rpc-server, standalone, transport, websocket
- Language: C#
- Homepage:
- Size: 510 KB
- Stars: 5
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Fluorite
![Fluorite](Images/Fluorite.160.png)
Fluorite - Simplest and fully-customizable RPC standalone infrastructure on .NET
[![Project Status: WIP – Initial development is in progress, but there has not yet been a stable, usable release suitable for the public.](https://www.repostatus.org/badges/latest/wip.svg)](https://www.repostatus.org/#wip)
## NuGet
|Package|main|devel|Description|
|:--|:--|:--|:--|
|Fluorite|[![NuGet Fluorite](https://img.shields.io/nuget/v/Fluorite.svg?style=flat)](https://www.nuget.org/packages/Fluorite)|[![MyGet Fluorite](https://img.shields.io/myget/fluorite/v/Fluorite.svg?style=flat&label=myget)](https://www.myget.org/feed/fluorite/package/nuget/Fluorite)|Meta-package (Provides automated generating static proxy / **Experimental**)|
|Fluorite.Dynamic|[![NuGet Fluorite.Dynamic](https://img.shields.io/nuget/v/Fluorite.Dynamic.svg?style=flat)](https://www.nuget.org/packages/Fluorite.Dynamic)|[![MyGet Fluorite.Dynamic](https://img.shields.io/myget/fluorite/v/Fluorite.Dynamic.svg?style=flat&label=myget)](https://www.myget.org/feed/fluorite/package/nuget/Fluorite.Dynamic)|Meta-package (Provides automated generating dynamic proxy)|### Sub packages
|Package|main|devel|Description|
|:--|:--|:--|:--|
|Fluorite.Core|[![NuGet Fluorite.Core](https://img.shields.io/nuget/v/Fluorite.Core.svg?style=flat)](https://www.nuget.org/packages/Fluorite.Core)|[![MyGet Fluorite.Core](https://img.shields.io/myget/fluorite/v/Fluorite.Core.svg?style=flat&label=myget)](https://www.myget.org/feed/fluorite/package/nuget/Fluorite.Core)|Independed core engine|
|Fluorite.Serializer|[![NuGet Fluorite.Serializer](https://img.shields.io/nuget/v/Fluorite.Serializer.svg?style=flat)](https://www.nuget.org/packages/Fluorite.Serializer)|[![MyGet Fluorite.Serializer](https://img.shields.io/myget/fluorite/v/Fluorite.Serializer.svg?style=flat&label=myget)](https://www.myget.org/feed/fluorite/package/nuget/Fluorite.Serializer)|Default serializer implementation (Newtonsoft.Json)|
|Fluorite.Transport|[![NuGet Fluorite.Transport](https://img.shields.io/nuget/v/Fluorite.Transport.svg?style=flat)](https://www.nuget.org/packages/Fluorite.Transport)|[![MyGet Fluorite.Transport](https://img.shields.io/myget/fluorite/v/Fluorite.Transport.svg?style=flat&label=myget)](https://www.myget.org/feed/fluorite/package/nuget/Fluorite.Transport)|Default transport implementation (System.Net.WebSockets)|
|Fluorite.Build|[![NuGet Fluorite.Build](https://img.shields.io/nuget/v/Fluorite.Build.svg?style=flat)](https://www.nuget.org/packages/Fluorite.Build)|[![MyGet Fluorite.Build](https://img.shields.io/myget/fluorite/v/Fluorite.Build.svg?style=flat&label=myget)](https://www.myget.org/feed/fluorite/package/nuget/Fluorite.Build)|Automated static proxy generator at building time|## CI
|main|devel|
|:--|:--|
|[![Fluorite CI build (main)](https://github.com/kekyo/Fluorite/workflows/.NET/badge.svg?branch=main)](https://github.com/kekyo/Fluorite/actions?query=branch%3Amain)|[![Fluorite CI build (devel)](https://github.com/kekyo/Fluorite/workflows/.NET/badge.svg?branch=devel)](https://github.com/kekyo/Fluorite/actions?query=branch%3Adevel)|-----
## What is this ?
An implementation of bi-directional/complementary/asynchronous RPC (remote procedure call) controller with customizable serializer/transport interface.
This is simple diagram for user side Fluorite architecture:
![Fluorite Diagram](./Images/diagram.png)
Fluorite doesn't have any depending other large libraries (For example: ASP.NET).
You can easy integrate flexible RPC messaging system on your own application.### Features
* Can do truly bi-directional operation between server and client.
* Complementary interface.
* With overlapping calls and will do non-blocking (if transport has capability).
* Fully asynchronous sending/receiving operation with `ValueTask` type.
* RPC form on custom interface definition.
* You can choose static proxy (at building time) or dynamic proxy (at runtime).
* Or you can attach your own custom proxy generator.
* Can attach your own custom serializer likes Json or another form by simple interface.
* Json, Bson, XML, Message Pack, Protocol Buffer and etc...
* Will make simpler logical message format.
* Can attach your own custom transport likes WebSocket or another protocol by simple interface.
* WebSocket, TCP/UDP direct, Pipe, IPC, MQ, Persistence data and etc...-----
## Getting started
Default configuration (meta-package) is applied with:
* Will use serializer `Newtonsoft.Json`.
* Will use transport `System.Net.WebSockets`.
* Client side: `ClientWebSocket`.
* Server side: `WebSocket` on `HttpListener`.NOTE: When running on Windows platform, you have to configure `HttpListener`/`HTTP.SYS` related setup protocol on server side. For example:
1. `netsh http add urlacl url=http://+:4649/ user=everyone`
2. `netsh advfirewall firewall add rule name="Fluorite HTTP" dir=in action=allow`
3. `netsh advfirewall firewall set rule name="Fluorite HTTP" new program=system profile=private protocol=tcp localport=4649`### Custom RPC interface definition
We can use independent platform such as `netstandard2.0` or likes.
```csharp
// nuget install Fluorite
// (or Fluorite.Build using static proxy generator)
using Fluorite;// You can use custom types each arguments/return value, constraint depending used serializer.
// (Default serializer is Newtonsoft.Json)
public sealed class Item
{
public int Id;
public string Label;
public int Price;
}// Require inherits `IHost` and method returns ValueTask or ValueTask.
public interface IPartsShop : IHost
{
ValueTask GetItemsAsync(string category, int max);
ValueTask PurchaseAsync(params int[] itemIds);
}
```### Client side
```csharp
// nuget install Fluorite
using Fluorite;// Initialize
Nest.Factory.Initialize();// Connect to server with default WebSocket/Json transport.
// (Optional: You can register client side expose object at last arguments same as server side)
var nest = await Nest.Factory.ConnectAsync("server.example.com", 4649, false);
try
{
// Get transparent proxy instance from the client nest.
var partsShop = nest.GetPeer();// Manipulate via transparent proxy.
var items = await shop.GetItemsAsync("FPGA", 100);
await shop.PurchaseAsync(items[3].Id);
}
finally
{
// Shutdown client nest
await nest.ShutdownAsync();
}
```### Server side
```csharp
// nuget install Fluorite
using Fluorite;// The exposed interface implementer.
internal sealed class PartsShop : IPartsShop
{
public async ValueTask GetItemsAsync(string category, int max)
{
// ...
}public async ValueTask PurchaseAsync(int[] itemIds)
{
// ...
}
}// Initialize
Nest.Factory.Initialize();// Start default WebSocket/Json server (at background)
// with expose objects at last arguments.
var nest = await Nest.Factory.StartServer(4649, false, new PartsShop());
try
{
// ...
}
finally
{
// Shutdown server nest
await nest.ShutdownAsync();
}
```-----
## Transparent proxy
Fluorite requires transparent proxy implementation. You can choice few implementation ways:
* Automatic static proxy generator:
* `Fluorite.Build` (or `Fluorite`) package will generate automatically static transparent proxy class on your project.
* It's easy way and recommended.
* AOT environment friendly and fastest at runtime.
* But some .NET development environemnt couldn't use. Unity (Game engine) and others have unique way to build environment.
* Dynamic proxy generator:
* `Fluorite.Dynamic` package will generate automatically dynamic transparent proxy class at on demand (runtime).
* Stable mostly environments.
* It's better performance, will use CIL/MSIL generator.
* Maybe couldn't use on AOT platform.
* Self implements static proxy:
* Flexible and customizable.
* You dodge referring meta-package `Fluorite` or `Fluorite.Dynamic`. Will make decrease dependency only referring `Fluorite.Core`.
* Tired :)## Automatic static proxy generator (Fluorite.Build)
You don't need anything. It's an example result:
```csharp
// It's automatically generated, you can see it by ILSpy and others.
internal sealed class IPartsShopProxy__ :
GeneratedProxyBase, IPartsShop
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ValueTask GetItemsAsync(string category, int max)
{
return base.InvokeAsync("ExamplePartsShop.IPartsShop.GetItems", new object[2] { category, max });
}[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ValueTask PurchaseAsync(int[] itemIds)
{
return base.InvokeAsync("ExamplePartsShop.IPartsShop.Purchase", new object[1] { itemIds });
}
}
```## Automatic dynamic proxy generator (use Fluorite.Dynamic)
## Self implements static proxy
You have to implement likes:
```csharp
// Hand coded static proxy class.
internal sealed class PartsShopProxy :
StaticProxyBase, IPartsShop
{
public ValueTask GetItemsAsync(string category, int max)
{
return base.InvokeAsync("GetItems", category, max);
}public ValueTask PurchaseAsync(int[] itemIds)
{
// HACK: Requires cast expression because will convert implicitly param array.
return base.InvokeAsync("Purchase", (object)itemIds);
}
}// Register proxy class.
Nest.Register();
```-----
## Advanced topic
### Customize with your own serializer
TODO:
### Customize with your own transport
TODO:
### Customize with your own proxy factory
TODO:
-----
## License
Apache-v2
## History
* 0.6.0:
* Reconstruct transport architecture overall transferring data with `Stream` asynchronously.
* Reconstruct transport architecture enabling truly full-duplex on WebSocket.
* 0.5.0:
* Implemented static proxy generator at running build time (Fluorite.Build)
* 0.2.0:
* Passed full-duplex, bi-directional tests.
* 0.1.0:
* Initial version.