public CommandContext( string entityId, long sequence, string commandName, long commandId, AnySupport anySupport, IEventSourcedEntityHandler eventSourcedEntityHandler, int snapshotEvery, AbstractContext abstractContext, AbstractClientActionContext abstractClientActionContext, AbstractEffectContext abstractEffectContext, IActivatableContext activatableContext) { EntityId = entityId; Sequence = sequence; CommandName = commandName; CommandId = commandId; AnySupport = anySupport; EventSourcedEntityHandler = eventSourcedEntityHandler; SnapshotEvery = snapshotEvery; AbstractContext = abstractContext; AbstractClientActionContext = abstractClientActionContext; AbstractEffectContext = abstractEffectContext; ActivatableContext = activatableContext; }
public void HandleEvent(Any @event, IEventContext context) { Unwrap(() => { var obj = AnySupport.Decode(@event); if (!CurrentBehaviors .Any(behavior => GetCachedBehaviorReflection(behavior) .GetEventHandler(obj.GetType()) .Match(handler => { var active = true; var ctx = new EventBehaviorContext(context, behaviors => { // ReSharper disable once AccessToModifiedClosure if (!active) { throw new InvalidOperationException("Context is not active!"); } CurrentBehaviors = ValidateBehaviors(behaviors).ToArray(); }); handler.Invoke(behavior, obj, ctx); active = false; return(true); }, () => false) ) ) { throw new CloudStateException( $"No event handler [{obj.GetType()}] found for any of the current behaviors: {BehaviorsString}"); } }); }
public static IEventSourcedEntityHandler CreateHandler <T>(Func <IEventSourcedEntityCreationContext, object> entityFactory = null) { var anySupport = new AnySupport( new[] { Com.Example.Shoppingcart.Persistence.DomainReflection.Descriptor } ); var mockSupport = new Mock <IEventSourcedContext>(); mockSupport.Setup(x => x.EntityId) .Returns("foo"); var method = new ResolvedServiceMethod <string, Wrapped>( Com.Example.Shoppingcart.ShoppingCart .Descriptor.Methods .First(x => x.Name == "AddItem"), new StringResolvedType(), new WrappedResolvedType() ); return(new AttributeBasedEntityHandlerFactory( typeof(T), anySupport, new[] { method }.ToDictionary( x => x.Descriptor.Name, x => x as IResolvedServiceMethod), entityFactory ).CreateEntityHandler(mockSupport.Object)); }
public void HandleSnapshot(Any anySnapshot, ISnapshotContext context) { Unwrap(() => { var snapshot = AnySupport.Decode(anySnapshot); if (!CurrentBehaviors.Any(behavior => BehaviorReflectionCache.GetOrAdd(behavior.GetType()) .GetSnapshotHandler(snapshot.GetType()) .Match(handler => { var active = true; var ctx = new SnapshotBehaviorContext(context, behaviors => { // TODO: Check sequence number override on this context is set correctly. // ReSharper disable once AccessToModifiedClosure if (!active) { throw new InvalidOperationException("Context is not active!"); } CurrentBehaviors = ValidateBehaviors(behaviors).ToArray(); }); handler.Invoke(behavior, snapshot, ctx); active = false; return(true); }, () => false)) ) { throw new CloudStateException( $"No snapshot handler found for snapshot [{snapshot.GetType()}] on any of the current behaviors [{BehaviorsString}]" ); } }); }
internal EventSourcedEntityHandler(AnySupport anySupport, IEventSourcedContext context, IBehaviorResolver behaviorReflectionCache, Func <IEventSourcedEntityCreationContext, object> entityCreationFactory = null) { AnySupport = anySupport; Context = context; EntityCreationFactory = entityCreationFactory; BehaviorReflectionCache = behaviorReflectionCache; var explicitBehaviors = Option.None <object[]>(); var active = true; void Become(object[] behaviors) { // ReSharper disable once AccessToModifiedClosure if (!active) { throw new InvalidOperationException("Context is not active!"); } explicitBehaviors = Option.Some(ValidateBehaviors(behaviors).ToArray()); } var ctx = new EventSourcedEntityCreationContext(context, Become); var entity = EntityCreationFactory(ctx); active = false; CurrentBehaviors = explicitBehaviors.Match(behaviors => behaviors, () => new[] { entity }); }
public CrdtStatefulService( ICrdtEntityHandlerFactory factory, ServiceDescriptor descriptor, AnySupport anySupport) : base(factory, descriptor, anySupport) { Factory = factory; Streamed = descriptor.Methods.Where(x => x.IsServerStreaming).Select(x => x.Name).ToArray(); }
protected EntityHandlerFactory(Type initialClass, AnySupport anySupport, Func <TContext, object> factory, IReadOnlyDictionary <string, IResolvedServiceMethod> resolvedMethods) { InitialClass = initialClass; AnySupport = anySupport; Factory = Constructor(InitialClass, factory); ResolvedMethods = resolvedMethods; }
// [Fact(Skip = "Not ready")] public void SupportSerializingAndDeserializingProtobufs() { var any = AnySupport.Encode(AddLineItem); Assert.Equal("type.googleapis.com/" + AddLineItem.Descriptor.FullName, any.TypeUrl); Assert.Equal(AddLineItem, AnySupport.Decode(any)); }
public AttributeBasedEntityHandlerFactory( Type initialClass, AnySupport anySupport, IReadOnlyDictionary <string, IResolvedServiceMethod> resolvedMethods = null, Func <IEventSourcedEntityCreationContext, object> factory = null ) : base(initialClass, anySupport, factory, resolvedMethods) { BehaviorResolver = new ReflectionCacheBehaviorResolver(() => ResolvedMethods); InitCache(); }
public AttributeBasedEntityHandlerFactory( Type initialClass, AnySupport anySupport, ServiceDescriptor descriptor, Func <IEventSourcedContext, object> factory = null ) : base(initialClass, anySupport, factory, anySupport.ResolveServiceDescriptor(descriptor)) { BehaviorResolver = new ReflectionCacheBehaviorResolver(() => ResolvedMethods); InitCache(); }
protected StatefulEntityService(IEntityHandlerFactory <TContext, THandler> factory, ServiceDescriptor serviceDescriptor, AnySupport anySupport, string persistenceId = null) { EntityHandlerFactory = factory; ServiceDescriptor = serviceDescriptor; AnySupport = anySupport; Methods = factory switch { IResolvedEntityFactory resolved => resolved.ResolvedMethods, _ => new Dictionary <string, IResolvedServiceMethod>() }; PersistenceId = persistenceId ?? ServiceDescriptor.Name; }
public void TestPrimitive(string name, object value, object defaultValue) { var any = AnySupport.Encode(value); var res = AnySupport.Decode(any); Assert.Equal(value, res); // TODO: support for encoding (null as type) // any = AnySupport.Encode(null); // res = AnySupport.Decode(any); // Assert.Equal(defaultValue, res); }
public void TestPrimitiveBytes() { var str = "foo"; var bytes = ByteString.CopyFromUtf8(str); var any = AnySupport.Encode(bytes); var res = AnySupport.Decode(any) as ByteString; Assert.NotNull(res); Assert.Equal(bytes, res); var val = res.ToStringUtf8(); Assert.Equal(str, val); }
public static IInternalCrdt Create(CrdtState state, AnySupport anySupport) { IInternalCrdt crdt = null; switch (state.StateCase) { case CrdtState.StateOneofCase.Gcounter: crdt = new GCounterImpl(); break; default: throw new NotImplementedException(); } crdt.ApplyState(state); return(crdt); }
internal static IEventSourcedEntityHandler CreateHandler <T>(Func <IEventSourcedEntityCreationContext, object> entityFactory = null) { var anySupport = new AnySupport( new[] { Com.Example.Shoppingcart.Persistence.DomainReflection.Descriptor } ); var mockSupport = new Mock <IEventSourcedContext>(); mockSupport.Setup(x => x.EntityId) .Returns("foo"); return(new AttributeBasedEntityHandlerFactory( typeof(T), anySupport, new IResolvedServiceMethod[] { }.ToDictionary( x => x.Descriptor.Name, x => x), entityFactory ).CreateEntityHandler(mockSupport.Object)); }
protected internal AttributeBasedCrdtHandlerFactory(Type initialClass, AnySupport anySupport, ServiceDescriptor descriptor, Func <ICrdtEntityCreationContext, object> factory = null) : base(initialClass, anySupport, factory, anySupport.ResolveServiceDescriptor(descriptor)) { var allMethods = ReflectionHelper.GetAllDeclaredMethods(initialClass); var handlers = allMethods.Where(x => x.GetCustomAttribute <CommandHandlerAttribute>() != null) .Select(method => { var attribute = method.GetCustomAttribute <CommandHandlerAttribute>(); var name = string.IsNullOrEmpty(attribute.Name) ? ReflectionHelper.GetCapitalizedName(method) : attribute.Name; if (!ResolvedMethods.TryGetValue(name, out var serviceMethod)) { throw new CloudStateException( $"Command handler method [{method.Name}] for command [{name}] found, but the service has no command by that name."); } return(method, serviceMethod); }).ToArray(); CommandHandlers = GetHandlers <ICommandContext>(handlers, false); StreamedCommandHandlers = GetHandlers <IStreamedCommandContext <ICommandContext> >(handlers, true); }
public void ResolveServiceDescriptor() { var methods = AnySupport.ResolveServiceDescriptor( ShoppingcartReflection.Descriptor.FindTypeByName <ServiceDescriptor>("ShoppingCart") ); Assert.Equal(3, methods.Count); var method = methods["AddItem"].Method; Assert.Equal(AddLineItem.Descriptor.FullName, method.InputType.FullName); Assert.Equal(typeof(AddLineItem), method.InputType.ClrType); var bytes = AddLineItem.ToByteString(); Assert.Equal(AddLineItem, method.InputType.Parser.ParseFrom(bytes)); Assert.Equal(Empty.Descriptor.FullName, method.OutputType.FullName); Assert.Equal(typeof(Empty), method.OutputType.ClrType); var defaultEmpty = new Empty(); bytes = defaultEmpty.ToByteString(); Assert.Equal(defaultEmpty, method.OutputType.Parser.ParseFrom(bytes)); }
/// <summary> /// Service discovery endpoint called by the CloudState operator in order to determine /// the list of <see cref="IStatefulService" />'s running within the current local process. /// </summary> /// <param name="request">ProxyInfo request</param> /// <param name="context">ServerCallContext</param> /// <returns></returns> public override async Task <EntitySpec> discover(ProxyInfo request, ServerCallContext context) { Logger.LogInformation( $"Received discovery call from sidecar [{request.ProxyName} {request.ProxyVersion}] supporting CloudState {request.ProtocolMajorVersion}.{request.ProtocolMinorVersion}" ); Logger.LogDebug($"Supported sidecar entity types: {string.Join(", ", request.SupportedEntityTypes)}"); var unsupportedServices = Services.Values.Where(service => !request.SupportedEntityTypes.Contains(service.StatefulServiceTypeName) ); if (unsupportedServices.Any()) { Logger.LogError( "Proxy doesn't support the entity types for the following services: " + string.Join(", ", unsupportedServices .Select(s => s.ServiceDescriptor.FullName + ": " + s.StatefulServiceTypeName) ) ); } if (false) { // TODO: verify compatibility with in.protocolMajorVersion & in.protocolMinorVersion // await Task.FromException(new CloudStateException("Proxy version not compatible with library protocol support version")); } else { var allDescriptors = new AnySupport(Services.Values.Select(x => x.ServiceDescriptor.File)).FlattenDescriptors( Services.Values.Select(x => x.ServiceDescriptor.File) ); var set = new FileDescriptorSet(); set.File.AddRange(allDescriptors.Select(x => FileDescriptorProto.Parser.ParseFrom(x.Value.SerializedData))); var fileDescriptorSet = set.ToByteString(); var entities = Services.Select(x => new Entity { EntityType = x.Value.StatefulServiceTypeName, ServiceName = x.Key, PersistenceId = x.Value.PersistenceId } ); var spec = new EntitySpec { ServiceInfo = ServiceInfo, Proto = fileDescriptorSet }; try { spec.Entities.AddRange(entities); } catch (Exception ex) { Logger.LogError($"Exception: {ex.StackTrace}", ex.InnerException ?? ex); } return(await Task.FromResult(spec)); } }
internal EventSourcedStatefulService(IEventSourcedEntityHandlerFactory factory, ServiceDescriptor serviceDescriptor, AnySupport anySupport, string persistenceId = null, int snapshotEvery = 0) : base(factory, serviceDescriptor, anySupport, persistenceId) { SnapshotEvery = snapshotEvery; }