-
-
Save darkl/08e66ddf9b59fa684582365a774a019b to your computer and use it in GitHub Desktop.
WampSharp dealer cache
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Threading.Tasks; | |
using WampSharp.V2; | |
using WampSharp.V2.Client; | |
using WampSharp.V2.Rpc; | |
namespace Callee | |
{ | |
public interface IRandomService | |
{ | |
[WampProcedure("com.arguments.random")] | |
int Random(); | |
} | |
public class RandomService : IRandomService | |
{ | |
public int Random() | |
{ | |
Random random = new Random(); | |
return random.Next(); | |
} | |
} | |
class Program | |
{ | |
public static async Task Main() | |
{ | |
const string location = "ws://127.0.0.1:8080/ws"; | |
DefaultWampChannelFactory channelFactory = new DefaultWampChannelFactory(); | |
IWampChannel channel = channelFactory.CreateJsonChannel(location, "realm1"); | |
await channel.Open().ConfigureAwait(false); | |
IRandomService instance = new RandomService(); | |
IWampRealmProxy realm = channel.RealmProxy; | |
IAsyncDisposable disposable = | |
await realm.Services.RegisterCallee(instance).ConfigureAwait(false); | |
// This line is required in order to release the WebSocket thread, otherwise it will be blocked by the following Console.ReadLine() line. | |
await Task.Yield(); | |
Console.WriteLine("Press enter to unregister"); | |
Console.ReadLine(); | |
await disposable.DisposeAsync().ConfigureAwait(false); | |
Console.WriteLine("Unregistered!"); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Threading.Tasks; | |
using WampSharp.V2; | |
using WampSharp.V2.Rpc; | |
namespace MyNamespace | |
{ | |
public interface IRandomService | |
{ | |
[WampProcedure("com.arguments.random")] | |
Task<int> RandomAsync(); | |
} | |
internal class Program | |
{ | |
public static async Task Main(string[] args) | |
{ | |
DefaultWampChannelFactory factory = | |
new DefaultWampChannelFactory(); | |
const string serverAddress = "ws://127.0.0.1:8080/ws"; | |
IWampChannel channel = | |
factory.CreateJsonChannel(serverAddress, "realm1"); | |
await channel.Open().ConfigureAwait(false); | |
IRandomService proxy = | |
channel.RealmProxy.Services.GetCalleeProxy<IRandomService>(); | |
int value = await proxy.RandomAsync().ConfigureAwait(false); | |
Console.WriteLine("Random value: " + value); | |
Console.ReadLine(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Concurrent; | |
using System.Collections.Generic; | |
using System.Linq; | |
using WampSharp.Binding; | |
using WampSharp.Core.Serialization; | |
using WampSharp.Fleck; | |
using WampSharp.V2; | |
using WampSharp.V2.Core; | |
using WampSharp.V2.Core.Contracts; | |
using WampSharp.V2.PubSub; | |
using WampSharp.V2.Realm; | |
using WampSharp.V2.Rpc; | |
namespace RpcCacheRouter | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
WampHost host = new WampHost(new RpcCacheWampRealmContainer()); | |
host.RegisterTransport(new FleckWebSocketTransport("ws://127.0.0.1:8080/ws"), | |
new JTokenJsonBinding()); | |
host.Open(); | |
Console.ReadLine(); | |
} | |
} | |
public class RpcCacheWampRealmContainer : IWampRealmContainer | |
{ | |
private readonly IWampRealmContainer mContainer; | |
public RpcCacheWampRealmContainer() : this(new WampRealmContainer()) | |
{ | |
} | |
public RpcCacheWampRealmContainer(IWampRealmContainer container) | |
{ | |
mContainer = container; | |
} | |
public IWampRealm GetRealmByName(string name) | |
{ | |
IWampRealm realm = mContainer.GetRealmByName(name); | |
RpcCacheWampRealm wrapped = new RpcCacheWampRealm(realm); | |
return wrapped; | |
} | |
} | |
public class RpcCacheWampRealm : IWampRealm | |
{ | |
private readonly IWampRealm mRealm; | |
private readonly IWampRpcOperationCatalog mRpcCacheOperationCatalog; | |
public RpcCacheWampRealm(IWampRealm realm) | |
{ | |
mRealm = realm; | |
mRpcCacheOperationCatalog = new RpcCacheWampRpcOperationCatalog(mRealm.RpcCatalog); | |
} | |
public string Name => mRealm.Name; | |
public IWampRpcOperationCatalog RpcCatalog => mRpcCacheOperationCatalog; | |
public IWampTopicContainer TopicContainer => mRealm.TopicContainer; | |
} | |
public class RpcCacheWampRpcOperationCatalog : IWampRpcOperationCatalog | |
{ | |
private readonly IWampRpcOperationCatalog mRpcOperationCatalog; | |
private readonly IRpcInvocationCache mInvocationCache = new LocalRpcInvocationCache(); | |
public RpcCacheWampRpcOperationCatalog(IWampRpcOperationCatalog rpcOperationCatalog) | |
{ | |
mRpcOperationCatalog = rpcOperationCatalog; | |
} | |
public IWampCancellableInvocation Invoke<TMessage>(IWampRawRpcOperationRouterCallback caller, IWampFormatter<TMessage> formatter, | |
InvocationDetails details, string procedure) | |
{ | |
if (mRpcOperationCatalog.GetMatchingOperation(procedure) != null) | |
{ | |
return mRpcOperationCatalog.Invoke(new RpcCacheWampRawOperationRouterCallback(caller, procedure, mInvocationCache), | |
formatter, details, procedure); | |
} | |
else | |
{ | |
if (!mInvocationCache.TryGetInvocationResult(procedure, out ResultArguments resultArguments)) | |
{ | |
// Call "base" to throw an exception. | |
return mRpcOperationCatalog.Invoke(caller, formatter, details, procedure); | |
} | |
else | |
{ | |
if (resultArguments.ArgumentsKeywords != null) | |
{ | |
caller.Result(WampObjectFormatter.Value, resultArguments.YieldOptions, | |
resultArguments.Arguments, resultArguments.ArgumentsKeywords); | |
} | |
else if (resultArguments.Arguments != null) | |
{ | |
caller.Result(WampObjectFormatter.Value, resultArguments.YieldOptions, | |
resultArguments.Arguments); | |
} | |
else | |
{ | |
caller.Result(WampObjectFormatter.Value, resultArguments.YieldOptions); | |
} | |
return null; | |
} | |
} | |
} | |
public IWampCancellableInvocation Invoke<TMessage>(IWampRawRpcOperationRouterCallback caller, IWampFormatter<TMessage> formatter, | |
InvocationDetails details, string procedure, TMessage[] arguments) | |
{ | |
if (arguments.Length == 0) | |
{ | |
return Invoke(caller, formatter, details, procedure); | |
} | |
return mRpcOperationCatalog.Invoke(caller, formatter, details, procedure, arguments); | |
} | |
public IWampCancellableInvocation Invoke<TMessage>(IWampRawRpcOperationRouterCallback caller, IWampFormatter<TMessage> formatter, | |
InvocationDetails details, string procedure, TMessage[] arguments, | |
IDictionary<string, TMessage> argumentsKeywords) | |
{ | |
return mRpcOperationCatalog.Invoke(caller, formatter, details, procedure, arguments, argumentsKeywords); | |
} | |
public IWampRegistrationSubscriptionToken Register(IWampRpcOperation operation, RegisterOptions options) | |
{ | |
return mRpcOperationCatalog.Register(operation, options); | |
} | |
public event EventHandler<WampProcedureRegisterEventArgs> RegistrationAdded | |
{ | |
add => mRpcOperationCatalog.RegistrationAdded += value; | |
remove => mRpcOperationCatalog.RegistrationAdded -= value; | |
} | |
public event EventHandler<WampProcedureRegisterEventArgs> RegistrationRemoved | |
{ | |
add => mRpcOperationCatalog.RegistrationRemoved += value; | |
remove => mRpcOperationCatalog.RegistrationRemoved -= value; | |
} | |
public IWampRpcOperation GetMatchingOperation(string criteria) | |
{ | |
return mRpcOperationCatalog.GetMatchingOperation(criteria); | |
} | |
private class RpcCacheWampRawOperationRouterCallback : IWampRawRpcOperationRouterCallback | |
{ | |
private readonly IWampRawRpcOperationRouterCallback mCallback; | |
private readonly string mProcedureName; | |
private readonly IRpcInvocationCache mInvocationCache; | |
public RpcCacheWampRawOperationRouterCallback( | |
IWampRawRpcOperationRouterCallback callback, string procedureName, | |
IRpcInvocationCache invocationCache) | |
{ | |
mCallback = callback; | |
mProcedureName = procedureName; | |
mInvocationCache = invocationCache; | |
} | |
public void Result<TMessage>(IWampFormatter<TMessage> formatter, YieldOptions options) | |
{ | |
mInvocationCache.MapInvocationToResult(mProcedureName, new ResultArguments(options)); | |
mCallback.Result(formatter, options); | |
} | |
public void Result<TMessage>(IWampFormatter<TMessage> formatter, YieldOptions options, TMessage[] arguments) | |
{ | |
mInvocationCache.MapInvocationToResult(mProcedureName, ResultArguments.FromArguments(options, arguments)); | |
mCallback.Result(formatter, options, arguments); | |
} | |
public void Result<TMessage>(IWampFormatter<TMessage> formatter, YieldOptions options, TMessage[] arguments, | |
IDictionary<string, TMessage> argumentsKeywords) | |
{ | |
mInvocationCache.MapInvocationToResult(mProcedureName, ResultArguments.FromArguments(options, arguments, argumentsKeywords)); | |
mCallback.Result(formatter, options, arguments, argumentsKeywords); | |
} | |
public void Error<TMessage>(IWampFormatter<TMessage> formatter, TMessage details, string error) | |
{ | |
mCallback.Error(formatter, details, error); | |
} | |
public void Error<TMessage>(IWampFormatter<TMessage> formatter, TMessage details, string error, TMessage[] arguments) | |
{ | |
mCallback.Error(formatter, details, error, arguments); | |
} | |
public void Error<TMessage>(IWampFormatter<TMessage> formatter, TMessage details, string error, TMessage[] arguments, | |
TMessage argumentsKeywords) | |
{ | |
mCallback.Error(formatter, details, error, arguments, argumentsKeywords); | |
} | |
} | |
} | |
public class ResultArguments | |
{ | |
public YieldOptions YieldOptions { get; } | |
public object[] Arguments { get; } | |
public IDictionary<string, object> ArgumentsKeywords { get; } | |
public ResultArguments(YieldOptions yieldOptions, | |
object[] arguments = null, | |
IDictionary<string, object> argumentsKeywords = null) | |
{ | |
YieldOptions = yieldOptions; | |
Arguments = arguments; | |
ArgumentsKeywords = argumentsKeywords; | |
} | |
public static ResultArguments FromArguments<TMessage> | |
(YieldOptions yieldOptions, | |
TMessage[] arguments = null, | |
IDictionary<string, TMessage> argumentsKeywords = null) | |
{ | |
return new ResultArguments(yieldOptions, | |
arguments?.Cast<object>().ToArray(), | |
argumentsKeywords?.ToDictionary(x => x.Key, | |
x => (object)x.Value)); | |
} | |
} | |
public interface IRpcInvocationCache | |
{ | |
void MapInvocationToResult(string procedure, | |
ResultArguments resultArguments); | |
bool TryGetInvocationResult(string procedure, | |
out ResultArguments value); | |
} | |
public class LocalRpcInvocationCache : IRpcInvocationCache | |
{ | |
private readonly ConcurrentDictionary<string, ResultArguments> mProcedureUriToResult = | |
new ConcurrentDictionary<string, ResultArguments>(); | |
public void MapInvocationToResult(string procedure, ResultArguments resultArguments) | |
{ | |
mProcedureUriToResult[procedure] = resultArguments; | |
} | |
public bool TryGetInvocationResult(string procedure, out ResultArguments value) | |
{ | |
return mProcedureUriToResult.TryGetValue(procedure, out value); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment