public async Task StartShard(IAsyncProjectionShard shard, CancellationToken cancellationToken) { if (!_hasStarted) { StartNode(); } // Don't duplicate the shard if (_agents.ContainsKey(shard.Name.Identity)) { return; } await TryAction(null, async() => { try { var agent = new ProjectionAgent(_store, shard, _logger, cancellationToken); var position = await agent.Start(this); Tracker.Publish(new ShardState(shard.Name, position) { Action = ShardAction.Started }); _agents[shard.Name.Identity] = agent; } catch (Exception e) { _logger.LogError(e, "Error when trying to start projection shard '{ShardName}'", shard.Name.Identity); throw new ShardStartException(shard.Name, e); } }, cancellationToken); }
public async Task StartShard(IAsyncProjectionShard shard) { if (!_hasStarted) { StartNode(); } // TODO -- log the start, or error if it fails var agent = new ProjectionAgent(_store, shard, _logger); var position = await agent.Start(Tracker); Tracker.Publish(new ShardState(shard.ProjectionOrShardName, position) { Action = ShardAction.Started }); _agents[shard.ProjectionOrShardName] = agent; }
internal async Task TryAction(ProjectionAgent projection, Func <Task> action, CancellationToken token, int attempts = 0, TimeSpan delay = default) { if (delay != default) { await Task.Delay(delay, token); } if (token.IsCancellationRequested) { return; } try { await action(); } catch (Exception ex) { if (token.IsCancellationRequested) { return; } var continuation = Settings.DetermineContinuation(ex, attempts); switch (continuation) { case RetryLater r: await TryAction(projection, action, token, attempts + 1, r.Delay); break; case StopProjection: if (projection != null) { await StopShard(projection.ShardName.Identity, ex); } break; case StopAllProjections: var tasks = _agents.Keys.ToArray().Select(name => { return(Task.Run(async() => { await StopShard(name, ex); }, _cancellation.Token)); }); await Task.WhenAll(tasks); Tracker.Publish(new ShardState(ShardName.All, Tracker.HighWaterMark) { Action = ShardAction.Stopped, Exception = ex }); break; case PauseProjection pause: if (projection != null) { await projection.Pause(pause.Delay); } break; case PauseAllProjections pauseAll: var tasks2 = _agents.Values.ToArray().Select(agent => { return(Task.Run(async() => { await agent.Pause(pauseAll.Delay); }, _cancellation.Token)); }); await Task.WhenAll(tasks2); break; case DoNothing: // Don't do anything. break; } } }