|
4 | 4 | using System.IO; |
5 | 5 | using System.Linq; |
6 | 6 | using System.Text.RegularExpressions; |
| 7 | +using System.Threading.Tasks; |
7 | 8 | using Dynamo.Configuration; |
8 | 9 | using Dynamo.Engine; |
9 | 10 | using Dynamo.Graph.Connectors; |
@@ -47,6 +48,23 @@ public class NodeAutoCompleteSearchViewModel : SearchViewModel |
47 | 48 | private const string nodeClusterAutocompleteMLEndpoint = "MLNodeClusterAutocomplete"; |
48 | 49 | internal bool IsOpen { get; set; } |
49 | 50 |
|
| 51 | + private bool resultsLoaded; |
| 52 | + |
| 53 | + /// <summary> |
| 54 | + /// Flag that indicates whether results are loading (false) or they have loaded (true). |
| 55 | + /// This is set as true for both succesfully and unsuccessfully loading the results. |
| 56 | + /// </summary> |
| 57 | + [Obsolete("This method will be removed in a future version of Dynamo")] |
| 58 | + public bool ResultsLoaded |
| 59 | + { |
| 60 | + get { return resultsLoaded; } |
| 61 | + set |
| 62 | + { |
| 63 | + resultsLoaded = value; |
| 64 | + RaisePropertyChanged(nameof(ResultsLoaded)); |
| 65 | + } |
| 66 | + } |
| 67 | + |
50 | 68 | // Lucene search utility to perform indexing operations just for NodeAutocomplete. |
51 | 69 | internal LuceneSearchUtility LuceneUtility |
52 | 70 | { |
@@ -161,6 +179,7 @@ public bool DisplayLowConfidence |
161 | 179 | } |
162 | 180 |
|
163 | 181 | internal event Action<NodeModel> ParentNodeRemoved; |
| 182 | + private Guid LastRequestGuid; |
164 | 183 |
|
165 | 184 | /// <summary> |
166 | 185 | /// Constructor |
@@ -290,27 +309,55 @@ internal MLNodeAutoCompletionRequest GenerateRequestForMLAutocomplete() |
290 | 309 |
|
291 | 310 | internal void ShowNodeAutocompleMLResults() |
292 | 311 | { |
| 312 | + //this should run on the UI thread, so thread safety is not a concern |
| 313 | + LastRequestGuid = Guid.NewGuid(); |
| 314 | + var myRequest = LastRequestGuid; |
| 315 | + |
293 | 316 | MLNodeAutoCompletionResponse MLresults = null; |
294 | 317 |
|
295 | 318 | var request = GenerateRequestForMLAutocomplete(); |
296 | 319 |
|
297 | 320 | string jsonRequest = JsonConvert.SerializeObject(request); |
298 | 321 |
|
299 | 322 | // Get results from the ML API. |
300 | | - try |
| 323 | + ResultsLoaded = false; |
| 324 | + Task.Run(() => |
301 | 325 | { |
302 | | - MLresults = GetMLNodeAutocompleteResults(jsonRequest); |
| 326 | + try |
| 327 | + { |
| 328 | + MLresults = GetMLNodeAutocompleteResults(jsonRequest); |
| 329 | + this.dynamoViewModel.UIDispatcher.BeginInvoke(() => UpdateUIWithRresults(MLresults, myRequest)); |
| 330 | + } |
| 331 | + catch (Exception ex) |
| 332 | + { |
| 333 | + this.dynamoViewModel.UIDispatcher.BeginInvoke(() => |
| 334 | + { |
| 335 | + ResultsLoaded = true; //fail gracefully |
| 336 | + dynamoViewModel.Model.Logger.Log("Unable to fetch ML Node autocomplete results: " + ex.Message); |
| 337 | + DisplayAutocompleteMLStaticPage = true; |
| 338 | + AutocompleteMLTitle = Resources.LoginNeededTitle; |
| 339 | + AutocompleteMLMessage = Resources.LoginNeededMessage; |
| 340 | + Analytics.TrackEvent(Actions.View, Categories.NodeAutoCompleteOperations, "UnabletoFetch"); |
| 341 | + return; |
| 342 | + }); |
| 343 | + } |
| 344 | + }); |
| 345 | + } |
| 346 | + private void UpdateUIWithRresults(MLNodeAutoCompletionResponse MLresults, Guid myRequest) |
| 347 | + { |
| 348 | + if (LastRequestGuid != myRequest) |
| 349 | + { |
| 350 | + //a newer request came, we're no longer interested in the results of this one |
| 351 | + //only latest request has the right to be committed to the UI and internal data structures |
| 352 | + return; |
303 | 353 | } |
304 | | - catch (Exception ex) |
| 354 | + if (!IsOpen) |
305 | 355 | { |
306 | | - dynamoViewModel.Model.Logger.Log("Unable to fetch ML Node autocomplete results: " + ex.Message); |
307 | | - DisplayAutocompleteMLStaticPage = true; |
308 | | - AutocompleteMLTitle = Resources.LoginNeededTitle; |
309 | | - AutocompleteMLMessage = Resources.LoginNeededMessage; |
310 | | - Analytics.TrackEvent(Actions.View, Categories.NodeAutoCompleteOperations, "UnabletoFetch"); |
| 356 | + // view disappeared while the background thread was waiting for the server response. |
| 357 | + // Ignore the results as we're no longer interested. |
311 | 358 | return; |
312 | 359 | } |
313 | | - |
| 360 | + ResultsLoaded = true; |
314 | 361 | // no results |
315 | 362 | if (MLresults == null || MLresults.Results.Count() == 0) |
316 | 363 | { |
|
0 commit comments