jirenius / csharp-res Goto Github PK
View Code? Open in Web Editor NEWRES protocol service library for .NET
License: MIT License
RES protocol service library for .NET
License: MIT License
Add support for the changes made in RES Service Protocol v1.2.0
When setting owned resourced with ResService.SetOwnedResources
, where the resource patterns does not contain full wildcards (>
), the auth and call request NATS subjects will not be correctly subscribed to.
Wondering if you have explored blazer wasm aspects ?
Travis CI should be added to run CI builds on commits and PRs.
ResgateIO.Service.csproj element PackageIconUrl has been deprecated. PackageIcon should be used instead.
https://docs.microsoft.com/en-us/nuget/reference/msbuild-targets#packageiconurl
The service library should be available through NuGet.
Add support for the changes made in RES Service Protocol v1.1.1
Currently, the IResourceHandler
has synchronous methods, but there is a need to allow asynchronous methods to handle the requests.
Example:
var h = new DynamicHandler()
.SetGet(async req => {
var model = await MyDB.GetModel(req.ResourceName);
req.Model(model);
});
Update IResourceHandler
to have all methods return Task
.
This would be a backwards incompatible change, and would not allow for any synchronous handling which might cause a slight overhead (?).
Create a new IResourceHandlerAsync
interface with the same methods but returning Task
.
This would lead to a set of similar classes, such as IBaseHandlerAsync
, IModelHandlerAsync
, ICollectionHandlerAsync
, and IDynamicHandlerAsync
. Also, it would not allow mixing synchronous and asynchronous handlers.
Add a duplicate set of methods to IResourceHandler
with for Async methods, such as Task GetAsync(IGetRequest req)
.
This alternative requires a way for ResService
to determine whether to use the Get
or GetAsync
method when handling a get request.
This issue might also include the scope of the making the With
and WithGroup
methods return Tasks:
Task t = service.With("myservice.mymodel", r => {
r.Event("custom");
});
When calling ResourceContext.QueryEvent(callback)
, if the call fails to create a subscription to the temporary inbox, the async callback method will be called without waiting for the result before the call to QueryEvent returns.
This can in rare cases cause a race condition.
In case of failed subscription, the callback should be queued on the same resource worker Task from which QueryEvent was called.
New call request is currently handled by the Call handler, but should have its own handler to make it easier to comply with the RES service protocol specification.
Unit tests should be added to find existing bugs and stop new bugs from enter the code.
The testing suite from the go-res package would be a good reference for the scope of the tests.
In addition, the testing suite from timerqueue can be used as reference for the TimerQueue
class.
When sending a query event with an async callback, the library will instantly send an empty event response on each query request without awaiting the completion of the callback.
The .NETStandard 1.6 target will explicitly require NETStandard.Library >= 1.6.1 . From .NETStandard 2.0 and onward, this will not be needed, and will reduce the number of dependencies required when installing the NuGet package.
Add .NETStandard2.0 as a target to the project.
It should be possible to run a callback on a group thread/task without having a specific ResourceContext or resource ID.
Also, IResourceContext
should have a Group
property with the contexts group ID, that defaults to the resource name in case a group is not set.
service.WithGroup("books", () => {
// Callback is called on the thread/task of "books"
});
WithGroup
overloads should exist:
WithGroup(string group, Action callback)
WithGroup(string group, Action<ResService> callback)
WithGroup
should be used instead of overloading With
, to avoid ambiguity when using lambda expressions:
service.With("test.model", resource => {});
service.WithGroup("mygroup", service => {});
The Set prefix on all DynamicHandler methods only causes unnecessary clutter without improving readability. They should be deprecated.
The csharp-res
library lacks basic features found in more complete libraries, such as the go-res package.
The following features should be added or updated
The README should contain basic usage snippets, to help understand how to use the library.
ResService should implement IDisposable.
All necessary steps are performed in ResService.cleanup()
, so the implementation should just be:
public void Dispose()
{
cleanup();
}
When creating resources whose content is dependent on other resources (eg. A collection of model references sorted by a property value in the referenced models), there must be a way to listen for events on the dependent resource.
Or in other terms: a handler should have a way to listen to events triggered by other handlers.
These listeners should both be possible to make from the ResService
instance:
var service = new ResService("example");
service.AddHandler("book.$id", new BookModelHandler());
var h = new BooksCollectionHandler();
service.AddHandler("books", h);
// Maybe like this
service.AddEventListener("book.$id", h.OnBookEvent);
Or by using attributes to make the handler more self contained:
class BooksCollectionHandler: CollectionHandler {
[EventListener("book.$id")]
public void OnBookEvent(IResourceContext r, object ev)
{
if (ev is IChangeEvent change)
{
// Do stuff with change
}
}
}
The handler will be called from the same worker task of the resource triggering the event, and not the resource listening for events.
The EventListeners will be resolved when ResService.Serve
is called. This makes it possible to add listeners for handlers before they are registered.
ResService should have the following events:
Serving
- On serving after the initial system.reset is sent.Disconnected
- On disconnect from NATS.Reconnected
- On reconnect to NATS, after system.reset is sent.Stopped
- On service being stopped.Error
- On any error that causes an Error log.Events attempted to be sent by the service prior to the initial system.reset
is sent, should be discarded with a Log.Trace message.
This is to prevent events being sent for resources which might be stale in Resgate's cache.
This also applies to events attempted to be sent during a reconnect.
Using DynamicHandler or_BaseHandler_ to register a call method with the name "new"
will result in the exception:
System.ArgumentException: Must use SetNew to register handler for new call requests
This is due to a deprecated validation used to enforce correct behavior prior to v0.4.2 and RES protocol v1.2.0. The validation should be removed and any example updated.
There should be an example showing how to work with queries.
Multiple resources might want to be handled on the same worker thread to avoid having to add additional synchronization.
This can be handled by adding the concept of Group, a pattern string that works as the ID for the worker thread. Multiple resources with the same Group will be running on the same worker thread.
The Group pattern should be allowed to contain placeholder tags. Eg.:
group.${contextId}
These tags must also exist as placeholder tags in the resource pattern used when calling AddHandler
.
Let's say we have a filtered collection, users.admins
, containing a list of model references to user models with the role of admin
. This collection is dependent upon the content of the user models, and may change whenever any model role is updated.
To simplify synchronization, the users.admins
collection and all the user models may be handled serialized by the same worker thread.
The default JSON serializer settings used by ResService may not be preferred. It should be possible to set a custom setting to be used instead.
Add a method to set custom JSON serializer settings:
/// <summary>
/// Sets the settings used with JSON serialization.
/// </summary>
/// <param name="settings">JSON serializer settings.</param>
/// <returns>The ResService instance.</returns>
public ResService SetSerializerSettings(JsonSerializerSettings settings)
The NuGet package should have multi target support for the following two targets:
It should be allowed to add a handler to the root of a router, if the router has a pattern set.
ResService service = new ResService("example");
service.AddHandler(new DynamicHandler().SetCallMethod("foo", r = r.Ok()));
The IAsyncHandler
interface should provide means for ResService
to pass its own instance and the full pattern string back to the handler once it has been registered to the service.
Add a new method to IAsyncHandler
:
/// <summary>
/// Called when the handler is registered to a service.
/// </summary>
/// <param name="service">Service which the handler is registered to.</param>
/// <param name="pattern">Full resource id pattern being handled.</param>
void OnRegister(ResService service, String pattern);
Should add the simplest Hello World example.
The current ILogger
interface requires the service library to generate log strings even if they are not to be logged. This produces unnecessary garbage which can be avoided.
In addition, debug logging should be added too ILogger
. The default ConsoleLogger
implementation should have Debug deactivated by default.
Debug logging should, for starters, include logging the cleanup steps taken.
The interface should be changed to accept variadic parameters, similar to those of String.Format
.
Previously implementation of the ILogger
interface will need to be updated.
The BaseHandler should have a method attribute to look for named methods.
Example
class MyHandler : BaseHandler
{
[CallMethod("add")]
public void Add(ICallRequest request)
{
request.Ok(2 * (double)request.Params["value"]);
}
[AuthMethod("login")]
public void Login(IAuthRequest request)
{
/* Perform login */
}
}
It may additionally look up named method based on their signature. In such a case, the name of the call method will be the same as the class method but with first-letter-lowercase.
Example
class MyHandler : BaseHandler
{
// Add matches the signature of a call method.
// It will be automatically added with the method name "add".
public void Add(ICallRequest request)
{
request.Ok(2 * (double)request.Params["value"]);
}
}
The methods void Call(ICallRequest request)
and void Auth(IAuthRequest request)
should be excluded from reflection as they are part of the IResourceHandler
interface.
It should be possible to register a custom error handler.
When calling ResService.Serve(IConnection conn)
, no listeners are added to the provided NATS conn
object.
This will cause ResService to fail responding to reconnects and other NATS events.
Options opts = ConnectionFactory.GetDefaultOptions();
opts.Url = url;
IConnection conn = new ConnectionFactory().CreateConnection(opts);
var service = new ResService("example");
service.AddHandler("model", new DynamicHandler().SetGet(r => r.Model(new { foo = "bar" })));
service.Serve(conn);
// Restart NATS to force a reconnect.
// ResService should react with sending a system.reset event, but doesn't.
Listeners are currently only added when ResService creates its own IConnection object when calling ResService.Serve(string url)
.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.