Skip to content
This repository was archived by the owner on Mar 9, 2021. It is now read-only.

Commit 30b8dc1

Browse files
committed
Check if data structures are complete and valid at startup
- Fixes crawler stall bug if the queue list is empty at startup which was introduced by the new database consistency checks (#284). - Clears queue list before reinitializing it with a possible local Queuelist.json if the database location was changed in the settings view. - Checks if for each IBlog exist an IFiles if the database location was changed in the settings view.
1 parent 3e0cc97 commit 30b8dc1

File tree

8 files changed

+56
-11
lines changed

8 files changed

+56
-11
lines changed

src/TumblThree/TumblThree.Applications/Controllers/CrawlerController.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ private async Task Crawl()
152152
pauseCommand.RaiseCanExecuteChanged();
153153
stopCommand.RaiseCanExecuteChanged();
154154

155-
await crawlerService.DatabasesLoaded.Task;
155+
await Task.WhenAll(crawlerService.LibraryLoaded.Task, crawlerService.DatabasesLoaded.Task);
156156

157157
for (var i = 0; i < shellService.Settings.ConcurrentBlogs; i++)
158158
{

src/TumblThree/TumblThree.Applications/Controllers/ManagerController.cs

+16-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ internal class ManagerController
4343

4444
private readonly AsyncDelegateCommand checkStatusCommand;
4545
private readonly DelegateCommand copyUrlCommand;
46+
private readonly DelegateCommand checkIfDatabasesCompleteCommand;
4647
private readonly AsyncDelegateCommand addBlogCommand;
4748
private readonly DelegateCommand autoDownloadCommand;
4849
private readonly DelegateCommand enqueueSelectedCommand;
@@ -88,6 +89,7 @@ public ManagerController(IShellService shellService, ISelectionService selection
8889
enqueueSelectedCommand = new DelegateCommand(EnqueueSelected, CanEnqueueSelected);
8990
loadLibraryCommand = new AsyncDelegateCommand(LoadLibraryAsync, CanLoadLibrary);
9091
loadAllDatabasesCommand = new AsyncDelegateCommand(LoadAllDatabasesAsync, CanLoadAllDatbases);
92+
checkIfDatabasesCompleteCommand = new DelegateCommand(CheckIfDatabasesComplete, CanCheckIfDatabasesComplete);
9193
listenClipboardCommand = new DelegateCommand(ListenClipboard);
9294
autoDownloadCommand = new DelegateCommand(EnqueueAutoDownload, CanEnqueueAutoDownload);
9395
showDetailsCommand = new DelegateCommand(ShowDetailsCommand);
@@ -113,6 +115,7 @@ public async Task Initialize()
113115
crawlerService.EnqueueSelectedCommand = enqueueSelectedCommand;
114116
crawlerService.LoadLibraryCommand = loadLibraryCommand;
115117
crawlerService.LoadAllDatabasesCommand = loadAllDatabasesCommand;
118+
crawlerService.CheckIfDatabasesCompleteCommand = checkIfDatabasesCompleteCommand;
116119
crawlerService.AutoDownloadCommand = autoDownloadCommand;
117120
crawlerService.ListenClipboardCommand = listenClipboardCommand;
118121
crawlerService.PropertyChanged += CrawlerServicePropertyChanged;
@@ -128,6 +131,7 @@ public async Task Initialize()
128131
ManagerViewModel.QueueItems = QueueManager.Items;
129132
QueueManager.Items.CollectionChanged += QueueItemsCollectionChanged;
130133
ManagerViewModel.QueueItems.CollectionChanged += ManagerViewModel.QueueItemsCollectionChanged;
134+
BlogManagerFinishedLoadingLibrary += OnBlogManagerFinishedLoadingLibrary;
131135
BlogManagerFinishedLoadingDatabases += OnBlogManagerFinishedLoadingDatabases;
132136

133137
shellService.ContentView = ManagerViewModel.View;
@@ -144,6 +148,11 @@ public void Shutdown()
144148
{
145149
}
146150

151+
private void OnBlogManagerFinishedLoadingLibrary(object sender, EventArgs e)
152+
{
153+
crawlerService.LibraryLoaded.SetResult(true);
154+
}
155+
147156
private void OnBlogManagerFinishedLoadingDatabases(object sender, EventArgs e)
148157
{
149158
crawlerService.DatabasesLoaded.SetResult(true);
@@ -164,8 +173,9 @@ private void QueueItemsCollectionChanged(object sender, NotifyCollectionChangedE
164173
private async Task LoadDataBasesAsync()
165174
{
166175
// TODO: Methods have side effects!
176+
// They remove blogs from the blog manager.
167177
await LoadLibraryAsync();
168-
await LoadAllDatabasesAsync();
178+
await LoadAllDatabasesAsync();
169179
CheckIfDatabasesComplete();
170180
await CheckBlogsOnlineStatusAsync();
171181
}
@@ -359,6 +369,11 @@ private bool CanLoadAllDatbases()
359369
return !crawlerService.IsCrawl;
360370
}
361371

372+
private bool CanCheckIfDatabasesComplete()
373+
{
374+
return crawlerService.DatabasesLoaded.Task.GetAwaiter().IsCompleted && crawlerService.LibraryLoaded.Task.GetAwaiter().IsCompleted;
375+
}
376+
362377
private bool CanEnqueueSelected()
363378
{
364379
return ManagerViewModel.SelectedBlogFile != null && ManagerViewModel.SelectedBlogFile.Online;

src/TumblThree/TumblThree.Applications/Controllers/ModuleController.cs

+4-3
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,14 @@ public void Initialize()
106106
ManagerController.QueueManager = queueManager;
107107
ManagerController.ManagerSettings = managerSettings;
108108
ManagerController.BlogManagerFinishedLoadingLibrary += OnBlogManagerFinishedLoadingLibrary;
109-
Task managerControllerInit = ManagerController.Initialize();
110109
QueueController.QueueSettings = queueSettings;
111110
QueueController.QueueManager = queueManager;
112-
QueueController.Initialize();
113111
DetailsController.QueueManager = queueManager;
114-
DetailsController.Initialize();
115112
CrawlerController.QueueManager = queueManager;
113+
114+
Task managerControllerInit = ManagerController.Initialize();
115+
QueueController.Initialize();
116+
DetailsController.Initialize();
116117
CrawlerController.Initialize();
117118
cookieService.SetUriCookie(cookieList);
118119
}

src/TumblThree/TumblThree.Applications/Controllers/QueueController.cs

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ public void Run()
9191

9292
public void LoadQueue()
9393
{
94+
ClearList();
9495
IReadOnlyList<string> blogNamesToLoad = QueueSettings.Names;
9596
IReadOnlyList<BlogTypes> blogTypesToLoad = QueueSettings.Types;
9697
InsertFilesCore(0, blogNamesToLoad, blogTypesToLoad);

src/TumblThree/TumblThree.Applications/Services/CrawlerService.cs

+15
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ public class CrawlerService : Model, ICrawlerService
2323
private ICommand enqueueSelectedCommand;
2424
private ICommand loadLibraryCommand;
2525
private ICommand loadAllDatabasesCommand;
26+
private ICommand checkIfDatabasesCompleteCommand;
2627
private bool isCrawl;
2728
private bool isPaused;
2829
private bool isTimerSet;
30+
private TaskCompletionSource<bool> libraryLoaded;
2931
private TaskCompletionSource<bool> databasesLoaded;
3032
private ICommand listenClipboardCommand;
3133
private string newBlogUrl;
@@ -47,6 +49,7 @@ public CrawlerService(IShellService shellService)
4749

4850
activeItems = new ObservableCollection<QueueListItem>();
4951
readonlyActiveItems = new ReadOnlyObservableList<QueueListItem>(activeItems);
52+
libraryLoaded = new TaskCompletionSource<bool>();
5053
databasesLoaded = new TaskCompletionSource<bool>();
5154
activeItems.CollectionChanged += ActiveItemsCollectionChanged;
5255
}
@@ -57,6 +60,12 @@ public bool IsTimerSet
5760
set => SetProperty(ref isTimerSet, value);
5861
}
5962

63+
public TaskCompletionSource<bool> LibraryLoaded
64+
{
65+
get => libraryLoaded;
66+
set => SetProperty(ref libraryLoaded, value);
67+
}
68+
6069
public TaskCompletionSource<bool> DatabasesLoaded
6170
{
6271
get => databasesLoaded;
@@ -107,6 +116,12 @@ public ICommand LoadAllDatabasesCommand
107116
set => SetProperty(ref loadAllDatabasesCommand, value);
108117
}
109118

119+
public ICommand CheckIfDatabasesCompleteCommand
120+
{
121+
get => checkIfDatabasesCompleteCommand;
122+
set => SetProperty(ref checkIfDatabasesCompleteCommand, value);
123+
}
124+
110125
public ICommand RemoveBlogFromQueueCommand
111126
{
112127
get => removeBlogFromQueueCommand;

src/TumblThree/TumblThree.Applications/Services/ICrawlerService.cs

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ public interface ICrawlerService : INotifyPropertyChanged
2424

2525
ICommand LoadAllDatabasesCommand { get; set; }
2626

27+
ICommand CheckIfDatabasesCompleteCommand { get; set; }
28+
2729
ICommand RemoveBlogFromQueueCommand { get; set; }
2830

2931
ICommand ListenClipboardCommand { get; set; }
@@ -52,6 +54,8 @@ public interface ICrawlerService : INotifyPropertyChanged
5254

5355
Timer Timer { get; set; }
5456

57+
TaskCompletionSource<bool> LibraryLoaded { get; set; }
58+
5559
TaskCompletionSource<bool> DatabasesLoaded { get; set; }
5660

5761
void AddActiveItems(QueueListItem itemToAdd);

src/TumblThree/TumblThree.Applications/ViewModels/SettingsViewModel.cs

+11-5
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public class SettingsViewModel : ViewModel<ISettingsView>
2727
private readonly DelegateCommand browseExportLocationCommand;
2828
private readonly DelegateCommand enableAutoDownloadCommand;
2929
private readonly DelegateCommand exportCommand;
30-
private readonly DelegateCommand saveCommand;
30+
private readonly AsyncDelegateCommand saveCommand;
3131
private readonly AsyncDelegateCommand tumblrLoginCommand;
3232
private readonly AsyncDelegateCommand tumblrLogoutCommand;
3333
private readonly AsyncDelegateCommand tumblrSubmitTFACommand;
@@ -143,7 +143,7 @@ public SettingsViewModel(ISettingsView view, IShellService shellService, ICrawle
143143
tumblrLoginCommand = new AsyncDelegateCommand(TumblrLogin);
144144
tumblrLogoutCommand = new AsyncDelegateCommand(TumblrLogout);
145145
tumblrSubmitTFACommand = new AsyncDelegateCommand(TumblrSubmitTFA);
146-
saveCommand = new DelegateCommand(Save);
146+
saveCommand = new AsyncDelegateCommand(Save);
147147
enableAutoDownloadCommand = new DelegateCommand(EnableAutoDownload);
148148
exportCommand = new DelegateCommand(ExportBlogs);
149149
bloglistExportFileType = new FileType(Resources.Textfile, SupportedFileTypes.BloglistExportFileType);
@@ -993,33 +993,39 @@ private void LoadSettings()
993993
}
994994
}
995995

996-
private void Save()
996+
private async Task Save()
997997
{
998998
bool downloadLocationChanged = DownloadLocationChanged();
999999
bool loadAllDatabasesChanged = LoadAllDatabasesChanged();
10001000
SaveSettings();
1001-
ApplySettings(downloadLocationChanged, loadAllDatabasesChanged);
1001+
await ApplySettings(downloadLocationChanged, loadAllDatabasesChanged);
10021002
}
10031003

1004-
private void ApplySettings(bool downloadLocationChanged, bool loadAllDatabasesChanged)
1004+
private async Task ApplySettings(bool downloadLocationChanged, bool loadAllDatabasesChanged)
10051005
{
10061006
CrawlerService.Timeconstraint.SetRate((MaxConnections / (double)ConnectionTimeInterval));
10071007

10081008
if (loadAllDatabasesChanged && downloadLocationChanged)
10091009
{
1010+
CrawlerService.LibraryLoaded = new TaskCompletionSource<bool>();
10101011
CrawlerService.DatabasesLoaded = new TaskCompletionSource<bool>();
10111012
if (CrawlerService.StopCommand.CanExecute(null))
10121013
CrawlerService.StopCommand.Execute(null);
10131014
CrawlerService.LoadLibraryCommand.Execute(null);
10141015
CrawlerService.LoadAllDatabasesCommand.Execute(null);
1016+
await Task.WhenAll(CrawlerService.LibraryLoaded.Task, CrawlerService.DatabasesLoaded.Task);
1017+
CrawlerService.CheckIfDatabasesCompleteCommand.Execute(null);
10151018
}
10161019
else if (downloadLocationChanged)
10171020
{
1021+
CrawlerService.LibraryLoaded = new TaskCompletionSource<bool>();
10181022
CrawlerService.DatabasesLoaded = new TaskCompletionSource<bool>();
10191023
if (CrawlerService.StopCommand.CanExecute(null))
10201024
CrawlerService.StopCommand.Execute(null);
10211025
CrawlerService.LoadLibraryCommand.Execute(null);
10221026
CrawlerService.LoadAllDatabasesCommand.Execute(null);
1027+
await Task.WhenAll(CrawlerService.LibraryLoaded.Task, CrawlerService.DatabasesLoaded.Task);
1028+
CrawlerService.CheckIfDatabasesCompleteCommand.Execute(null);
10231029
}
10241030
else if (loadAllDatabasesChanged)
10251031
{

src/TumblThree/TumblThree.Presentation/DesignData/MockCrawlerService.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ public void RemoveActiveItem(QueueListItem itemToRemove)
5050

5151
public ICommand LoadAllDatabasesCommand { get; set; }
5252

53+
public ICommand CheckIfDatabasesCompleteCommand { get; set; }
54+
5355
public ICommand ListenClipboardCommand { get; set; }
5456

5557
public ICommand CrawlCommand { get; set; }
@@ -75,8 +77,9 @@ public void RemoveActiveItem(QueueListItem itemToRemove)
7577

7678
public Timer Timer { get; set; }
7779

78-
public TaskCompletionSource<bool> DatabasesLoaded { get; set; }
80+
public TaskCompletionSource<bool> LibraryLoaded { get; set; }
7981

82+
public TaskCompletionSource<bool> DatabasesLoaded { get; set; }
8083

8184
public void SetActiveBlogFiles(IEnumerable<IBlog> blogFilesToAdd)
8285
{

0 commit comments

Comments
 (0)