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)); } }
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."); }
// [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)); } });
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)); }