public async Task Should_update_repository_when_enqueing() { var @event = Envelope.Create <IEvent>(new ContentCreated { AppId = appId }); var rule = CreateRule(); var job = new RuleJob { Created = now }; A.CallTo(() => ruleService.CreateJobsAsync(rule.RuleDef, rule.Id, @event, true)) .Returns(new List <(RuleJob, Exception?)> { (job, null) }); await sut.Enqueue(rule.RuleDef, rule.Id, @event); A.CallTo(() => ruleEventRepository.EnqueueAsync(job, now, default)) .MustHaveHappened(); A.CallTo(() => localCache.StartContext()) .MustHaveHappened(); }
public async Task Enqueue(Rule rule, Guid ruleId, Envelope <IEvent> @event) { Guard.NotNull(rule, nameof(rule)); Guard.NotNull(@event, nameof(@event)); using (localCache.StartContext()) { var jobs = await ruleService.CreateJobsAsync(rule, ruleId, @event); foreach (var(job, ex) in jobs) { if (ex != null) { await ruleEventRepository.EnqueueAsync(job, null); await ruleEventRepository.UpdateAsync(job, new RuleJobUpdate { JobResult = RuleJobResult.Failed, ExecutionResult = RuleResult.Failed, ExecutionDump = ex.ToString(), Finished = job.Created }); } else { await ruleEventRepository.EnqueueAsync(job, job.Created); } } } }
public async Task InvokeAsync(HttpContext context, RequestDelegate next) { using (localCache.StartContext()) { await next(context); } }
private async Task RebuildManyAsync(string filter, Func <Guid, Task> action, CancellationToken ct) { using (localCache.StartContext()) { var handledIds = new HashSet <Guid>(); var worker = new ActionBlock <Guid>(action, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 32 }); await eventStore.QueryAsync(async storedEvent => { var headers = storedEvent.Data.Headers; var id = headers.AggregateId(); if (handledIds.Add(id)) { await worker.SendAsync(id); } }, filter, ct); worker.Complete(); await worker.Completion; } }
public async Task InvokeAsync(HttpContext context, ILocalCache localCache) { using (localCache.StartContext()) { await next(context); } }
private async Task ProcessAsync(State currentState, CancellationToken ct) { try { currentReminder = await RegisterOrUpdateReminder("KeepAlive", TimeSpan.Zero, TimeSpan.FromMinutes(2)); var rules = await appProvider.GetRulesAsync(DomainId.Create(Key)); var rule = rules.Find(x => x.Id == currentState.RuleId); if (rule == null) { throw new InvalidOperationException("Cannot find rule."); } using (localCache.StartContext()) { if (currentState.FromSnapshots && ruleService.CanCreateSnapshotEvents(rule.RuleDef)) { await EnqueueFromSnapshotsAsync(rule); } else { await EnqueueFromEventsAsync(currentState, rule, ct); } } } catch (OperationCanceledException) { return; } catch (Exception ex) { log.LogError(ex, w => w .WriteProperty("action", "runRule") .WriteProperty("status", "failed") .WriteProperty("ruleId", currentState.RuleId?.ToString())); } finally { if (!isStopping) { currentState.RuleId = null; currentState.Position = null; await state.WriteAsync(); if (currentReminder != null) { await UnregisterReminder(currentReminder); currentReminder = null; } currentJobToken?.Dispose(); currentJobToken = null; } } }
public async Task Should_add_item_to_cache_when_context_exists() { using (sut.StartContext()) { sut.Add("Key", 1); await Task.Delay(5); AssertCache(sut, "Key", 1, true); await Task.Delay(5); sut.Remove("Key"); AssertCache(sut, "Key", null, false); } }
public AssetFolderResolverTests() { requestContext = Context.Anonymous(Mocks.App(appId)); localCache.StartContext(); sut = new AssetFolderResolver(localCache, assetQuery); }
public async Task Invoke(IIncomingGrainCallContext context) { if (!context.Grain.GetType().Namespace !.StartsWith("Orleans", StringComparison.OrdinalIgnoreCase)) { using (localCache.StartContext()) { await context.Invoke(); } }
private async Task RebuildManyAsync <TState, TGrain>(string filter, CancellationToken ct) where TState : IDomainState <TState>, new() { var handledIds = new HashSet <Guid>(); var worker = new ActionBlock <Guid>(async id => { try { var state = new TState { Version = EtagVersion.Empty }; var persistence = store.WithSnapshotsAndEventSourcing(typeof(TGrain), id, (TState s) => state = s, e => { state = state.Apply(e); state.Version++; }); await persistence.ReadAsync(); await persistence.WriteSnapshotAsync(state); } catch (DomainObjectNotFoundException) { return; } }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = Environment.ProcessorCount * 2 }); using (localCache.StartContext()) { await store.GetSnapshotStore <TState>().ClearAsync(); await eventStore.QueryAsync(async storedEvent => { var id = storedEvent.Data.Headers.AggregateId(); if (handledIds.Add(id)) { await worker.SendAsync(id, ct); } }, filter, ct : ct); worker.Complete(); await worker.Completion; } }
public virtual async Task InsertManyAsync <TState, TGrain>(IdSource source, CancellationToken ct = default) where TState : IDomainState <TState>, new() { Guard.NotNull(source); var worker = new ActionBlock <Guid>(async id => { try { var state = new TState { Version = EtagVersion.Empty }; var persistence = store.WithSnapshotsAndEventSourcing(typeof(TGrain), id, (TState s) => state = s, e => { state = state.Apply(e); state.Version++; }); await persistence.ReadAsync(); await persistence.WriteSnapshotAsync(state); } catch (DomainObjectNotFoundException) { return; } }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = Environment.ProcessorCount * 2 }); var handledIds = new HashSet <Guid>(); using (localCache.StartContext()) { await source(new Func <Guid, Task>(async id => { if (handledIds.Add(id)) { await worker.SendAsync(id, ct); } })); worker.Complete(); await worker.Completion; } }
public async Task Should_add_item_to_cache_when_context_exists() { using (sut.StartContext()) { sut.Add("Key", 1); await Task.Delay(5); var found = sut.TryGetValue("Key", out var value); Assert.True(found); Assert.Equal(1, value); await Task.Delay(5); sut.Remove("Key"); var foundAfterRemove = sut.TryGetValue("Key", out value); Assert.False(foundAfterRemove); Assert.Null(value); } }
public async Task On(Envelope <IEvent> @event) { using (localCache.StartContext()) { if (@event.Payload is AppEvent appEvent) { var rules = await GetRulesAsync(appEvent.AppId.Id); foreach (var ruleEntity in rules) { await EnqueueAsync(ruleEntity.RuleDef, ruleEntity.Id, @event); } } } }
public async Task RebuildContentAsync() { using (localCache.StartContext()) { await store.GetSnapshotStore <ContentState>().ClearAsync(); await RebuildManyAsync("^content\\-", async id => { try { await RebuildAsync <ContentState, ContentGrain>(id, (e, s) => s.Apply(e)); } catch (DomainObjectNotFoundException) { return; } }); } }
public virtual async Task InsertManyAsync <T, TState>(IdSource source, CancellationToken ct = default) where T : DomainObjectBase <TState> where TState : class, IDomainState <TState>, new() { Guard.NotNull(source); var worker = new ActionBlock <Guid>(async id => { try { var domainObject = (T)serviceProvider.GetService(typeof(T)); domainObject.Setup(id); await domainObject.EnsureLoadedAsync(); await domainObject.RebuildStateAsync(); } catch (DomainObjectNotFoundException) { return; } }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = Environment.ProcessorCount * 2 }); var handledIds = new HashSet <Guid>(); using (localCache.StartContext()) { await source(new Func <Guid, Task>(async id => { if (handledIds.Add(id)) { await worker.SendAsync(id, ct); } })); worker.Complete(); await worker.Completion; } }
private async Task InsertManyAsync <T, TState>(IAsyncEnumerable <DomainId> source, int batchSize, double errorThreshold, CancellationToken ct = default) where T : DomainObject <TState> where TState : class, IDomainState <TState>, new() { var store = serviceProvider.GetRequiredService <IStore <TState> >(); var parallelism = Environment.ProcessorCount; var handledIds = new HashSet <DomainId>(); var handlerErrors = 0; using (localCache.StartContext()) { var workerBlock = new ActionBlock <DomainId[]>(async ids => { try { await using (var context = store.WithBatchContext(typeof(T))) { await context.LoadAsync(ids); foreach (var id in ids) { try { var domainObject = Factory <T, TState> .Create(serviceProvider, context); domainObject.Setup(id); await domainObject.RebuildStateAsync(); } catch (DomainObjectNotFoundException) { return; } catch (Exception ex) { log.LogWarning(ex, w => w .WriteProperty("reason", "CorruptData") .WriteProperty("domainObjectId", id.ToString()) .WriteProperty("domainObjectType", typeof(T).Name)); Interlocked.Increment(ref handlerErrors); } } } } catch (OperationCanceledException ex) { // Dataflow swallows operation cancelled exception. throw new AggregateException(ex); } }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = parallelism, MaxMessagesPerTask = 10, BoundedCapacity = parallelism }); var batchBlock = new BatchBlock <DomainId>(batchSize, new GroupingDataflowBlockOptions { BoundedCapacity = batchSize }); batchBlock.BidirectionalLinkTo(workerBlock); await foreach (var id in source.WithCancellation(ct)) { if (handledIds.Add(id)) { if (!await batchBlock.SendAsync(id, ct)) { break; } } } batchBlock.Complete(); await workerBlock.Completion; } var errorRate = (double)handlerErrors / handledIds.Count; if (errorRate > errorThreshold) { throw new InvalidOperationException($"Error rate of {errorRate} is above threshold {errorThreshold}."); } }
private async Task ProcessAsync(State currentState, CancellationToken ct) { try { currentReminder = await RegisterOrUpdateReminder("KeepAlive", TimeSpan.Zero, TimeSpan.FromMinutes(2)); var rule = await appProvider.GetRuleAsync(DomainId.Create(Key), currentState.RuleId !.Value); if (rule == null) { throw new DomainObjectNotFoundException(currentState.RuleId.ToString() !); } using (localCache.StartContext()) { var context = new RuleContext { AppId = rule.AppId, Rule = rule.RuleDef, RuleId = rule.Id, IgnoreStale = true }; if (currentState.RunFromSnapshots && ruleService.CanCreateSnapshotEvents(context)) { await EnqueueFromSnapshotsAsync(context, ct); } else { await EnqueueFromEventsAsync(currentState, context, ct); } } } catch (OperationCanceledException) { return; } catch (Exception ex) { log.LogError(ex, w => w .WriteProperty("action", "runRule") .WriteProperty("status", "failed") .WriteProperty("ruleId", currentState.RuleId?.ToString())); } finally { if (!isStopping) { currentState.RuleId = null; currentState.Position = null; await state.WriteAsync(); if (currentReminder != null) { await UnregisterReminder(currentReminder); currentReminder = null; } currentJobToken?.Dispose(); currentJobToken = null; } } }
private async Task InsertManyAsync <T, TState>(IStore <TState> store, IdSource source, CancellationToken ct = default) where T : DomainObject <TState> where TState : class, IDomainState <TState>, new() { var parallelism = Environment.ProcessorCount; const int BatchSize = 100; var workerBlock = new ActionBlock <DomainId[]>(async ids => { await using (var context = store.WithBatchContext(typeof(T))) { await context.LoadAsync(ids); foreach (var id in ids) { try { var domainObject = Factory <T, TState> .Create(serviceProvider, context); domainObject.Setup(id); await domainObject.RebuildStateAsync(); } catch (DomainObjectNotFoundException) { return; } } } }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = parallelism, MaxMessagesPerTask = 1, BoundedCapacity = parallelism }); var batchBlock = new BatchBlock <DomainId>(BatchSize, new GroupingDataflowBlockOptions { BoundedCapacity = BatchSize }); batchBlock.LinkTo(workerBlock, new DataflowLinkOptions { PropagateCompletion = true }); var handledIds = new HashSet <DomainId>(); using (localCache.StartContext()) { await source(id => { if (handledIds.Add(id)) { return(batchBlock.SendAsync(id, ct)); } return(Task.CompletedTask); }); batchBlock.Complete(); await workerBlock.Completion; } }