public async Task <bool> Execute(ProjectionInput input) { var stores = FilterStores(input); if (stores.IsEmpty()) { _view.DisplayNoStoresMessage(); return(true); } if (input.ListFlag) { foreach (var store in stores) { _view.WriteHeader(store); _view.ListShards(store); } return(true); } if (!input.RebuildFlag) { _host.ListenForUserTriggeredExit(); } foreach (var store in stores) { if (store.Shards.IsEmpty()) { break; } var shards = FilterShards(input, store); if (shards.IsEmpty()) { _view.WriteHeader(store); _view.DisplayNoMatchingProjections(); _view.ListShards(store); break; } var databases = await store.BuildDatabases().ConfigureAwait(false); databases = FilterDatabases(input, databases); if (databases.IsEmpty()) { _view.DisplayNoDatabases(); break; } if (input.RebuildFlag) { _view.WriteHeader(store); foreach (var database in databases) { if (databases.Count > 1) { _view.WriteHeader(database); } var status = await _host.TryRebuildShards(database, shards).ConfigureAwait(false); if (status == RebuildStatus.NoData) { _view.DisplayEmptyEventsMessage(store); } else { _view.DisplayRebuildIsComplete(); } } } else { // Only run async shards here. shards = shards.Where(x => x.Source.Lifecycle == ProjectionLifecycle.Async).ToArray(); if (shards.IsEmpty()) { _view.DisplayNoAsyncProjections(); _view.ListShards(store); break; } foreach (var database in databases) { await _host.StartShards(database, shards).ConfigureAwait(false); } await _host.WaitForExit().ConfigureAwait(false); } } return(true); }