示例#1
0
        public async Task MinionFound()
        {
            var id         = new ClaptrapIdentity("1", "2");
            var store      = new ClaptrapDesignStore();
            var mainDesign = new ClaptrapDesign
            {
                ClaptrapTypeCode = id.TypeCode
            };

            store.AddOrReplace(mainDesign);
            var minionDesign = new ClaptrapDesign
            {
                ClaptrapTypeCode     = "minion",
                ClaptrapMasterDesign = mainDesign
            };

            store.AddOrReplace(minionDesign);


            using var mocker = AutoMock.GetLoose(builder =>
            {
                builder.RegisterInstance(store)
                .AsImplementedInterfaces()
                .SingleInstance();
            });

            mocker.Mock <IActorProxyFactory>()
            .Setup(x => x.Create(new ActorId(id.Id), minionDesign.ClaptrapTypeCode, It.IsAny <ActorProxyOptions>()))
            .Verifiable();

            var daprMinionActivator = mocker.Create <DaprMinionActivator>();

            // act
            await daprMinionActivator.WakeAsync(id);
        }
示例#2
0
        public async Task ExceptionAndCompensate()
        {
            var container = CreateContainer();

            await using var scope = container.BeginLifetimeScope();
            var masterIdentity = new ClaptrapIdentity(Guid.NewGuid().ToString(), "TestCode");

            await using var claptrap = scope.CreateSagaClaptrap(masterIdentity, "testFlow", typeof(TestFlowData));
            var sagaFlow = SagaFlowBuilder.Create()
                           .WithStep <TestStep1, CompensateStep1>()
                           .WithStep <ExceptionStep, CompensateStep2>()
                           .WithUserData(new TestFlowData())
                           .Build();
            var claptrapAccessor = scope.Resolve <IClaptrapAccessor>();
            await claptrap.RunAsync(sagaFlow);

            var claptrapStateData = (SagaStateData <TestFlowData>)claptrapAccessor.Claptrap.State.Data;
            var flowState         = claptrapStateData.SagaFlowState;

            flowState.IsCompleted.Should().BeFalse();
            flowState.IsCompensating.Should().BeFalse();
            flowState.IsCompensated.Should().BeTrue();
            flowState.StepStatuses.Should().Equal(StepStatus.Completed, StepStatus.Error);
            flowState.CompensateStepStatuses.Should().Equal(StepStatus.Completed, StepStatus.Completed);
            var flowData = (TestFlowData)claptrapStateData.GetUserData();

            flowData.Test1.Should().BeFalse();
            flowData.Test2.Should().BeFalse();
            await claptrap.RunAsync(sagaFlow);
        }
示例#3
0
        public async Task MinionNotFound()
        {
            var id         = new ClaptrapIdentity("1", "2");
            var store      = new ClaptrapDesignStore();
            var mainDesign = new ClaptrapDesign
            {
                ClaptrapTypeCode = id.TypeCode
            };

            store.AddOrReplace(mainDesign);


            using var mocker = AutoMock.GetLoose(builder =>
            {
                builder.RegisterInstance(store)
                .AsImplementedInterfaces()
                .SingleInstance();
            });

            var daprMinionActivator = mocker.Create <DaprMinionActivator>();

            // act
            await daprMinionActivator.WakeAsync(id);

            mocker.Mock <IActorProxyFactory>()
            .Verify(x => x.Create(It.IsAny <ActorId>(), It.IsAny <string>(), It.IsAny <ActorProxyOptions>()),
                    Times.Never);
        }
        public async Task SaveEventAsync(string accountId, int count)
        {
            using var lifetimeScope = BuildService().CreateScope();
            var logger  = lifetimeScope.ServiceProvider.GetRequiredService <ILogger <QuickSetupTestBase> >();
            var factory = (ClaptrapFactory)lifetimeScope.ServiceProvider.GetRequiredService <IClaptrapFactory>();
            var id      = new ClaptrapIdentity(accountId, Codes.Account);

            await using var buildClaptrapLifetimeScope = factory.BuildClaptrapLifetimeScope(id);
            var saver = buildClaptrapLifetimeScope.Resolve <IEventSaver>();
            var tasks = Enumerable.Range(Defaults.EventStartingVersion, count)
                        .Select(x => saver.SaveEventAsync(
                                    new UnitEvent(id, UnitEvent.TypeCode, new UnitEvent.UnitEventData())
            {
                Version = x
            }));
            await Task.WhenAll(tasks);

            var       loader            = buildClaptrapLifetimeScope.Resolve <IEventLoader>();
            const int eventBeginVersion = Defaults.StateStartingVersion + 1;
            var       eventEndVersion   = eventBeginVersion + count;
            var       events            = await loader.GetEventsAsync(eventBeginVersion, eventEndVersion);

            var versions = events.Select(x => x.Version);

            logger.LogInformation("version from event loader : {version}", versions);
            versions.Should().BeInAscendingOrder()
            .And.OnlyHaveUniqueItems()
            .And.ContainInOrder(Enumerable.Range(Defaults.EventStartingVersion, count));
            await OnStopHost(Host);

            await Host.StopAsync();
        }
        public async Task SaveStateOneClaptrapAsync(string accountId, int times)
        {
            using var lifetimeScope = BuildService().CreateScope();
            var factory = (ClaptrapFactory)lifetimeScope.ServiceProvider.GetRequiredService <IClaptrapFactory>();
            var id      = new ClaptrapIdentity(accountId, Codes.Account);

            await using var buildClaptrapLifetimeScope = factory.BuildClaptrapLifetimeScope(id);
            var saver  = buildClaptrapLifetimeScope.Resolve <IStateSaver>();
            var states = Enumerable.Range(Defaults.StateStartingVersion, times)
                         .Select(x => new UnitState
            {
                Data     = UnitState.UnitStateData.Create(),
                Identity = id,
                Version  = x
            })
                         .ToArray();
            var tasks = states
                        .Select(x => saver.SaveAsync(x));
            await Task.WhenAll(tasks);

            var loader = buildClaptrapLifetimeScope.Resolve <IStateLoader>();
            var state  = await loader.GetStateSnapshotAsync();

            Debug.Assert(state != null, nameof(state) + " != null");
            state.Should().NotBeNull();
            state.Version.Should().Be(times - 1);
            await OnStopHost(Host);

            await Host.StopAsync();
        }
示例#6
0
        public async Task Success()
        {
            var container = CreateContainer();

            await using var scope = container.BeginLifetimeScope();
            var masterIdentity = new ClaptrapIdentity(Guid.NewGuid().ToString(), "TestCode");

            await using var claptrap = scope.CreateSagaClaptrap(masterIdentity, "testFlow", typeof(TestFlowData));
            var sagaFlow = SagaFlowBuilder.Create()
                           .WithStep <TestStep1, CompensateStep1>()
                           .WithStep <TestStep2, CompensateStep2>()
                           .WithUserData(new TestFlowData())
                           .Build();
            await claptrap.RunAsync(sagaFlow);

            var claptrapAccessor  = scope.Resolve <IClaptrapAccessor>();
            var claptrapStateData = (SagaStateData <TestFlowData>)claptrapAccessor.Claptrap.State.Data;

            claptrapStateData.SagaFlowState.IsCompleted.Should().BeTrue();
            var flowData = (TestFlowData)claptrapStateData.GetUserData();

            flowData.Test1.Should().BeTrue();
            flowData.Test2.Should().BeTrue();
            // there will be nothing change since flow completed.
            await claptrap.RunAsync(sagaFlow);
        }
示例#7
0
        private async Task MigrateAsync()
        {
            var id = new ClaptrapIdentity("1", Codes.Account);

            await using var scope = _claptrapFactory.BuildClaptrapLifetimeScope(id);
            var eventSaverMigration = scope.Resolve <IEventSaverMigration>();
            await eventSaverMigration.MigrateAsync();
        }
示例#8
0
        public async Task MultipleSent(int count)
        {
            var minionLocator = new TestMinionLocator();

            using var host = QuickSetupTestHelper.BuildHost(
                      DatabaseType.SQLite,
                      RelationLocatorStrategy.SharedTable,
                      AppsettingsFilenames,
                      builder =>
            {
                builder.RegisterInstance(minionLocator)
                .As <IMinionLocator>()
                .SingleInstance();
            }, builder =>
                      builder.UseRabbitMQ(rabbitmq => rabbitmq.AsEventCenter())
                      );
            var container         = host.Services;
            var subscriberManager = container.GetRequiredService <IMQSubscriberManager>();
            await subscriberManager.StartAsync();

            var claptrapFactory = (ClaptrapFactory)container.GetRequiredService <IClaptrapFactory>();
            var id = new ClaptrapIdentity("1", Codes.Account);

            await using var scope = claptrapFactory.BuildClaptrapLifetimeScope(id);
            var eventCenter = scope.Resolve <IEventCenter>();
            var task        = Enumerable.Range(0, count)
                              .ToObservable()
                              .Select(version =>
            {
                var unitEvent     = UnitEvent.Create(id);
                unitEvent.Version = version;
                return(unitEvent);
            })
                              .Select(e => Observable.FromAsync(() => eventCenter.SendToMinionsAsync(id, e)))
                              .Merge(100)
                              .ToTask();
            await task;
            await Task.Delay(TimeSpan.FromSeconds(5));

            await subscriberManager.CloseAsync();

            await container.GetRequiredService <IMQSenderManager>().CloseAsync();

            await host.StopAsync();

            var receivedItems = minionLocator.Queue.ToArray();
            var itemGroup     = receivedItems
                                .GroupBy(x => x.Identity);

            foreach (var grouping in itemGroup)
            {
                grouping
                .Select(x => x.Event.Version)
                .Should()
                .BeEquivalentTo(Enumerable.Range(0, count));
            }
        }
示例#9
0
        public IEnumerable <IClaptrapMinionModule> GetClaptrapMinionModules(IClaptrapIdentity identity)
        {
            var claptrapDesign = _claptrapDesignStore.FindDesign(identity);
            var masterIdentity = new ClaptrapIdentity(identity.Id,
                                                      claptrapDesign.ClaptrapMasterDesign.ClaptrapTypeCode);
            var re = new ClaptrapMinionModule(claptrapDesign, masterIdentity, identity);

            yield return(re);
        }
示例#10
0
 public static AutoMock CreateAutoMock(this IClaptrapDesign claptrapDesign,
                                       string id,
                                       IStateData stateData,
                                       Action <ContainerBuilder, ActorHost>?builderAction = default,
                                       Func <AutoMock>?autoMockFunc = default)
 {
     var claptrapIdentity     = new ClaptrapIdentity(id, claptrapDesign.ClaptrapTypeCode);
     var actorTypeInformation = ActorTypeInformation.Get(claptrapDesign.ClaptrapBoxImplementationType);
     var actorHost            = new ActorHost(actorTypeInformation,
                                              new ActorId(id),
示例#11
0
        public async Task CustomFactory()
        {
            using var root = BuildService().CreateScope();
            var factory =
                (ClaptrapFactory)root.ServiceProvider.GetRequiredService <IClaptrapFactory>();
            var claptrapIdentity = new ClaptrapIdentity("testId", Codes.CustomFactoryClaptrap);

            await using var claptrapScope = factory.BuildClaptrapLifetimeScope(claptrapIdentity);
            // Configuration files do not override custom factories that use Attribute
            await claptrapScope.Resolve <IEventSaver>().SaveEventAsync(default !);
示例#12
0
        public async Task InitAsync()
        {
            _logger.LogInformation("Start to init async");
            if (_options.Value.SetupLocalDatabase)
            {
                var databaseType = _options.Value.DatabaseType;
                await _dataBaseService.StartAsync(databaseType, 30);

                _logger.LogInformation("Database setup completed.");
            }

            var optionsValue = _options.Value;

            accounts = new IEventSaver[optionsValue.ActorCount];
            _scopes  = new ILifetimeScope[optionsValue.ActorCount];
            var scopes = Enumerable.Range(0, optionsValue.ActorCount)
                         .Select((i, x) =>
            {
                var re = new
                {
                    Scope = _claptrapFactory.BuildClaptrapLifetimeScope(new ClaptrapIdentity(x.ToString(),
                                                                                             Codes.Account)),
                    ClaptrapIdentity = new ClaptrapIdentity(x.ToString(),
                                                            Codes.Account),
                };
                _scopes[i] = re.Scope;
                return(re);
            })
                         .ToArray();

            _logger.LogInformation("Scopes created.");
            for (var i = 0; i < optionsValue.ActorCount; i++)
            {
                accounts[i] = scopes[i].Scope.Resolve <IEventSaver>();
            }

            _logger.LogInformation("Accounts created.");
            events = new UnitEvent[optionsValue.ActorCount];
            for (var i = 0; i < optionsValue.ActorCount; i++)
            {
                events[i] = UnitEvent.Create(scopes[i].ClaptrapIdentity);
            }

            _logger.LogInformation("Events created.");
            versions = new int[optionsValue.ActorCount];

            var id = new ClaptrapIdentity("1", Codes.Account);

            await using var scope = _claptrapFactory.BuildClaptrapLifetimeScope(id);
            var eventSaverMigration = scope.Resolve <IEventSaverMigration>();
            await eventSaverMigration.MigrateAsync();

            _logger.LogInformation("Database migration done.");
        }
示例#13
0
        public async Task Success(string id, int inventory)
        {
            using var mocker = AutoMock.GetStrict();
            mocker.Mock <ISkuRepository>()
            .Setup(x => x.GetInitInventoryAsync(id))
            .ReturnsAsync(inventory);

            var handler  = mocker.Create <SkuStateInitHandler>();
            var identity = new ClaptrapIdentity(id, ClaptrapCodes.SkuGrain);
            var data     = (SkuState)await handler.Create(identity);

            data.Inventory.Should().Be(inventory);
        }
示例#14
0
        public async Task <IActionResult> GetState(int itemId = 1)
        {
            var id = new ClaptrapIdentity(itemId.ToString(),
                                          ClaptrapCodes.AuctionItemActor);
            var auctionItemActor = _actorProxyFactory.GetClaptrap <IAuctionItemActor>(id);
            var state            = await auctionItemActor.GetStateAsync();

            var result = new
            {
                state = state
            };

            return(Ok(result));
        }
        public IEvent Deserialize(string source)
        {
            var jsonModel = JsonConvert.DeserializeObject <EventJsonModel>(source);
            var eventData = _eventDataStringSerializer.Deserialize(jsonModel.ClaptrapTypeCode,
                                                                   jsonModel.EventTypeCode,
                                                                   jsonModel.DataJson);
            var id = new ClaptrapIdentity(jsonModel.ClaptrapId, jsonModel.ClaptrapTypeCode);
            var re = new DataEvent(id, jsonModel.EventTypeCode, eventData)
            {
                Version = jsonModel.Version
            };

            return(re);
        }
示例#16
0
        // [TestCase(1000, 10, false)]
        public async Task SaveEventAsync(int actorCount, int count, bool validateByLoader)
        {
            using var lifetimeScope = BuildService().CreateScope();
            var logger  = lifetimeScope.ServiceProvider.GetRequiredService <ILogger <QuickSetupTestBase> >();
            var factory = (ClaptrapFactory)lifetimeScope.ServiceProvider.GetRequiredService <IClaptrapFactory>();

            var showTimeIndex = actorCount / 10;

            showTimeIndex = showTimeIndex == 0 ? 1 : showTimeIndex;
            var round = 1;
            var tasks = Enumerable.Range(0, actorCount)
                        .Select(async actorId =>
            {
                var index             = Interlocked.Increment(ref round);
                var accountId         = $"acc_{actorId}_{actorCount}_{count}_{index}";
                var id                = new ClaptrapIdentity(accountId, Codes.Account);
                await using var scope = factory.BuildClaptrapLifetimeScope(id);
                var saver             = scope.Resolve <IEventSaver>();
                var sourceEvent       = UnitEvent.Create(id);
                var unitEvents        = Enumerable.Range(Defaults.EventStartingVersion, count)
                                        .Select(x => sourceEvent with {
                    Version = x
                })
                                        .ToArray();
                var sw = Stopwatch.StartNew();
                foreach (var unitEvent in unitEvents)
                {
                    await saver.SaveEventAsync(unitEvent);
                }

                sw.Stop();
                if (actorId / showTimeIndex == 0)
                {
                    Console.WriteLine($"cost {sw.ElapsedMilliseconds} ms to save event");
                }

                if (validateByLoader)
                {
                    var loader = scope.Resolve <IEventLoader>();
                    const int eventBeginVersion = Defaults.StateStartingVersion + 1;
                    var eventEndVersion         = eventBeginVersion + count;
                    var events   = await loader.GetEventsAsync(eventBeginVersion, eventEndVersion);
                    var versions = events.Select(x => x.Version);
                    logger.LogInformation("version from event loader : {version}", versions);
                    versions.Should().BeInAscendingOrder()
                    .And.OnlyHaveUniqueItems()
                    .And.ContainInOrder(Enumerable.Range(Defaults.EventStartingVersion, count));
                }
            });
示例#17
0
        public async Task <IActionResult> TryBidding([FromBody] TryBiddingWebApiInput webApiInput)
        {
            var input = new TryBiddingInput
            {
                Price  = webApiInput.Price,
                UserId = webApiInput.UserId,
            };
            var itemId = webApiInput.ItemId;
            var id     = new ClaptrapIdentity(itemId.ToString(),
                                              ClaptrapCodes.AuctionItemActor);
            var auctionItemActor = _actorProxyFactory.GetClaptrap <IAuctionItemActor>(id);
            var result           = await auctionItemActor.TryBidding(input);

            return(Ok(result));
        }
示例#18
0
        public Task Failed()
        {
            using var mocker = AutoMock.GetStrict();
            const string skuId = "yueluo-666";

            mocker.Mock <ISkuRepository>()
            .Setup(x => x.GetInitInventoryAsync(skuId))
            .Throws <BizException>();

            var handler  = mocker.Create <SkuStateInitHandler>();
            var identity = new ClaptrapIdentity(skuId, ClaptrapCodes.SkuGrain);

            Assert.ThrowsAsync <BizException>(() => handler.Create(identity));
            return(Task.CompletedTask);
        }
        public async Task HandleEventAsync()
        {
            decimal       oldBalance;
            decimal       nowBalance;
            const decimal diff   = 100M;
            const int     times  = 10;
            const string  testId = "testId";

            using (var lifetimeScope = BuildService().CreateScope())
            {
                var      factory          = lifetimeScope.ServiceProvider.GetRequiredService <Account.Factory>();
                var      claptrapIdentity = new ClaptrapIdentity(testId, Codes.Account);
                IAccount account          = factory.Invoke(claptrapIdentity);
                await account.ActivateAsync();

                oldBalance = await account.GetBalanceAsync();

                await Task.WhenAll(Enumerable.Range(0, times)
                                   .Select(i => account.ChangeBalanceAsync(diff)));

                var balance = await account.GetBalanceAsync();

                await account.DeactivateAsync();

                nowBalance = oldBalance + times * 100;
                balance.Should().Be(nowBalance);
            }

            Console.WriteLine($"balance change: {oldBalance} + {diff} = {nowBalance}");

            using (var lifetimeScope = BuildService().CreateScope())
            {
                var factory          = lifetimeScope.ServiceProvider.GetService <AccountBalanceMinion.Factory>();
                var claptrapIdentity = new ClaptrapIdentity(testId, Codes.AccountBalanceMinion);
                IAccountBalanceMinion accountBalance = factory.Invoke(claptrapIdentity);
                await accountBalance.ActivateAsync();

                var balance = await accountBalance.GetBalanceAsync();

                balance.Should().Be(nowBalance);
                Console.WriteLine($"balance from minion {balance}");
            }

            await OnStopHost(Host);

            await Host.StopAsync();
        }
示例#20
0
        public async Task Success()
        {
            using var mocker = AutoMock.GetStrict();
            const string userId    = "userId";
            var          stateData = new OrderState
            {
                OrderCreated = false
            };
            var identity         = new ClaptrapIdentity("666", ClaptrapCodes.OrderGrain);
            var createOrderInput = new CreateOrderInput
            {
                CartId = identity.Id,
                UserId = userId
            };
            const string skuId          = "yueluo-666";
            const int    skuCountInCart = 666;
            var          cartItems      = new Dictionary <string, int>
            {
                { skuId, skuCountInCart }
            };

            mocker.MockStateData(stateData);
            mocker.MockStateIdentity(identity);
            var cartGrain = new Mock <ICartGrain>();

            cartGrain.Setup(x => x.GetItemsAsync())
            .ReturnsAsync(cartItems);
            cartGrain.Setup(x => x.RemoveAllItemsAsync())
            .Returns(Task.CompletedTask);
            mocker.MockGrain(createOrderInput.CartId, cartGrain.Object);

            var skuGrain = new Mock <ISkuGrain>();

            skuGrain.Setup(x => x.UpdateInventoryAsync(skuCountInCart))
            .ReturnsAsync(0);
            mocker.MockGrain(skuId, skuGrain.Object);

            mocker.MockerEventCode <OrderCreatedEvent>(ClaptrapCodes.OrderCreated);

            mocker.Mock <IClaptrapGrainCommonService>()
            .Setup(x => x.ClaptrapAccessor.Claptrap.HandleEventAsync(It.IsAny <IEvent>()))
            .Returns(Task.CompletedTask);
            var handler = mocker.Create <OrderGrain>();

            await handler.CreateOrderAsync(createOrderInput);
        }
示例#21
0
        public async Task HandleAsync(HttpContext context)
        {
            var sr   = new StreamReader(context.Request.Body);
            var body = await sr.ReadToEndAsync();

            var e         = _eventStringSerializer.Deserialize(body);
            var jsonModel = _eventSerializer.Serialize(e);

            var minionTypeCode = _minionTypeCodes[e.ClaptrapIdentity.TypeCode];

            var tasks = minionTypeCode.Select(async x =>
            {
                var minionId   = new ClaptrapIdentity(e.ClaptrapIdentity.Id, x);
                var actorProxy = _actorProxyFactory.Create(new ActorId(minionId.Id), minionId.TypeCode);
                await actorProxy.InvokeMethodAsync(nameof(IClaptrapMinionActor.MasterEventReceivedJsonAsync),
                                                   new[] { jsonModel });
            });

            await Task.WhenAll(tasks);
        }
示例#22
0
        private async Task AsyncEventingBasicConsumerOnReceived(object sender,
                                                                BasicDeliverEventArgs args,
                                                                IClaptrapDesign minionDesign)
        {
            _logger.LogDebug("message received from rabbit mq, exchange : {exchange} ,routeKey : {routeKey}",
                             args.Exchange,
                             args.RoutingKey);
            var consumer = (IAsyncBasicConsumer)sender;

            consumer.Model.BasicAck(args.DeliveryTag, false);
            var payload     = Decompress(args);
            var data        = _messageSerializer.Deserialize(payload);
            var evt         = _eventStringSerializer.Deserialize(data);
            var minionId    = new ClaptrapIdentity(evt.ClaptrapIdentity.Id, minionDesign.ClaptrapTypeCode);
            var minionProxy = _minionLocator.CreateProxy(minionId);

            _logger.LogTrace("create minion proxy for {id}", minionId);
            await minionProxy.MasterEventReceivedAsync(new[] { evt });

            _logger.LogDebug("a message sent to minion {minionId}", minionId);
        }
示例#23
0
        public Task AlreadyCreated()
        {
            using var mocker = AutoMock.GetStrict();
            var stateData = new OrderState
            {
                OrderCreated = true
            };

            mocker.MockStateData(stateData);

            var identity = new ClaptrapIdentity("666", ClaptrapCodes.OrderGrain);

            mocker.MockStateIdentity(identity);

            var handler          = mocker.Create <OrderGrain>();
            var createOrderInput = new CreateOrderInput {
            };

            Assert.ThrowsAsync <BizException>(() => handler.CreateOrderAsync(createOrderInput));
            return(Task.CompletedTask);
        }
示例#24
0
        private async Task RunCoreAsync()
        {
            await MigrateAsync();

            var totalCount = _options.Value.TotalCount;
            var batchSize  = _options.Value.BatchSize;
            var batchCount = totalCount / batchSize;
            var totalW     = Stopwatch.StartNew();
            var endSign    = new int[_options.Value.WorkerCount];
            var tcs        = new TaskCompletionSource <int>();
            var timeBag    = new ConcurrentBag <List <long> >();

            Parallel.For(0, _options.Value.WorkerCount, async workerId =>
            {
                var id = new ClaptrapIdentity(workerId.ToString(), Codes.Account);
                await using var scope = _claptrapFactory.BuildClaptrapLifetimeScope(id);
                var saver             = scope.Resolve <IEventEntitySaver <EventEntity> >();
                var mapper            = scope.Resolve <IEventEntityMapper <EventEntity> >();

                var timeList  = new List <long>();
                var unitEvent = UnitEvent.Create(id);
                var entity    = mapper.Map(unitEvent);

                for (var i = 0; i < batchCount; i++)
                {
                    var versionStart = i * batchSize;
                    var events       = Enumerable.Range(versionStart, batchSize)
                                       .Select(version => entity with {
                        Version = version
                    });

                    var sw = Stopwatch.StartNew();
                    await saver.SaveManyAsync(events);
                    sw.Stop();
                    timeList.Add(sw.ElapsedMilliseconds);
                    _logger.LogTrace("batch {i} {percent:00.00}%: {total}", i, i * 1.0 / batchCount * 100,
                                     sw.Elapsed.Humanize(maxUnit: TimeUnit.Millisecond));
                }
        public async Task SaveStateMultipleClaptrapAsync(int claptrapCount)
        {
            const int stateVersion = 100;

            using var lifetimeScope = BuildService().CreateScope();
            var logger  = lifetimeScope.ServiceProvider.GetRequiredService <ILogger <QuickSetupTestBase> >();
            var factory = (ClaptrapFactory)lifetimeScope.ServiceProvider.GetRequiredService <IClaptrapFactory>();
            var sw      = Stopwatch.StartNew();

            var data = Enumerable.Range(0, claptrapCount)
                       .Select(accountId =>
            {
                var claptrapIdentity = new ClaptrapIdentity($"acc{accountId}", Codes.Account);
                return(new
                {
                    id = claptrapIdentity,
                    state = new UnitState
                    {
                        Data = UnitState.UnitStateData.Create(),
                        Identity = claptrapIdentity,
                        Version = stateVersion
                    }
                });
            })
                       .AsParallel()
                       .ToArray();

            sw.Stop();
            logger.LogInformation("cost {time} ms to build data", sw.ElapsedMilliseconds);
            sw.Restart();

            var lifetimes = data.Select(d =>
            {
                var id = d.id;
                var buildClaptrapLifetimeScope = factory.BuildClaptrapLifetimeScope(id);
                return(new
                {
                    id,
                    d.state,
                    lifetimeScope = buildClaptrapLifetimeScope,
                });
            })
                            .ToArray();

            sw.Stop();
            logger.LogInformation("cost {time} ms to build lifetime", sw.ElapsedMilliseconds);
            sw.Restart();

            var items = lifetimes.Select(d =>
            {
                var id    = d.id;
                var saver = d.lifetimeScope.Resolve <IStateSaver>();
                return(new
                {
                    id,
                    d.state,
                    saver,
                    d.lifetimeScope,
                });
            })
                        .ToArray();

            sw.Stop();
            logger.LogInformation("cost {time} ms to build items", sw.ElapsedMilliseconds);
            sw.Restart();

            var tasks = items
                        .Select(item => item.saver.SaveAsync(item.state));
            await Task.WhenAll(tasks);

            sw.Stop();
            logger.LogInformation("cost {time} ms to save items", sw.ElapsedMilliseconds);

            foreach (var item in items)
            {
                var loader = item.lifetimeScope.Resolve <IStateLoader>();
                var state  = await loader.GetStateSnapshotAsync();

                Debug.Assert(state != null, nameof(state) + " != null");
                state.Version.Should().Be(item.state.Version);
            }

            Parallel.ForEach(items, item => { item.lifetimeScope.Dispose(); });
            await OnStopHost(Host);

            await Host.StopAsync();
        }
示例#26
0
        public async Task Normal(CompressType compressType)
        {
            var random        = new Random();
            var minionLocator = new TestMinionLocator();

            using var host = QuickSetupTestHelper.BuildHost(
                      DatabaseType.SQLite,
                      RelationLocatorStrategy.SharedTable,
                      AppsettingsFilenames.Concat(new[]
                                                  { $"configs/rabbitmq/appsettings.{compressType.ToString("G").ToLower()}.json" }),
                      builder =>
            {
                builder.RegisterInstance(minionLocator)
                .As <IMinionLocator>()
                .SingleInstance();
            }, builder =>
                      builder.UseRabbitMQ(rabbitmq => rabbitmq.AsEventCenter())
                      );

            var container         = host.Services;
            var subscriberManager = container.GetRequiredService <IMQSubscriberManager>();
            await subscriberManager.StartAsync();

            var claptrapFactory = (ClaptrapFactory)container.GetRequiredService <IClaptrapFactory>();
            var id1             = new ClaptrapIdentity("1", Codes.Account);

            await using var scope = claptrapFactory.BuildClaptrapLifetimeScope(id1);
            var eventCenter = scope.Resolve <IEventCenter>();
            var eventData   = new AccountBalanceChangeEvent
            {
                Diff = random.Next(0, 1000)
            };
            var evt = new DataEvent(id1, Codes.AccountBalanceChangeEvent, eventData)
            {
                Version = 1
            };
            await eventCenter.SendToMinionsAsync(id1, evt);

            await Task.Delay(TimeSpan.FromSeconds(3));

            minionLocator.Queue.Count.Should().Be(2);
            var dic               = minionLocator.Queue.ToDictionary(x => x.Identity);
            var balanceMinionId   = new ClaptrapIdentity(id1.Id, Codes.AccountBalanceMinion);
            var balanceMinionItem = dic[balanceMinionId];

            AssertEvent(balanceMinionId, balanceMinionItem);

            var balanceHistoryMinionId   = new ClaptrapIdentity(id1.Id, Codes.AccountBalanceMinion);
            var balanceHistoryMinionItem = dic[balanceHistoryMinionId];

            AssertEvent(balanceHistoryMinionId, balanceHistoryMinionItem);

            await subscriberManager.CloseAsync();

            await container.GetRequiredService <IMQSenderManager>().CloseAsync();

            await host.StopAsync();

            void AssertEvent(ClaptrapIdentity minionId, ReceivedItem item)
            {
                var(id, e) = item;
                id.Should().BeEquivalentTo(minionId);
                e.Version.Should().Be(evt.Version);
                e.EventTypeCode.Should().Be(evt.EventTypeCode);
                e.Data.Should().BeOfType <AccountBalanceChangeEvent>();
                var data = (AccountBalanceChangeEvent)e.Data;

                data.Diff.Should().Be(eventData.Diff);
            }
        }