Пример #1
0
 static void HandleItemsIteratorSession(object iterator, List <SearchItem> allItems, string id, SearchContext context, SearchFlags options)
 {
     if (iterator != null && options.HasAny(SearchFlags.Synchronous))
     {
         using (var stackedEnumerator = new SearchEnumerator <SearchItem>(iterator))
         {
             while (stackedEnumerator.MoveNext())
             {
                 if (stackedEnumerator.Current != null)
                 {
                     allItems.Add(stackedEnumerator.Current);
                 }
             }
         }
     }
     else
     {
         var session = context.sessions.GetProviderSession(context, id);
         session.Reset(context, iterator, k_MaxFetchTimeMs);
         session.Start();
         var sessionEnded = !session.FetchSome(allItems, k_MaxFetchTimeMs);
         if (options.HasAny(SearchFlags.FirstBatchAsync))
         {
             session.SendItems(context.subset != null ? allItems.Intersect(context.subset) : allItems);
             allItems.Clear();
         }
         if (sessionEnded)
         {
             session.Stop();
         }
     }
 }
Пример #2
0
        /// <summary>
        /// Execute a search request that will fetch search results asynchronously.
        /// </summary>
        /// <param name="context">Search context used to track asynchronous request.</param>
        /// <param name="options">Options defining how the query will be performed</param>
        /// <returns>Asynchronous list of search items.</returns>
        public static ISearchList Request(SearchContext context, SearchFlags options = SearchFlags.None)
        {
            ISearchList results = null;

            if (!InternalEditorUtility.CurrentThreadIsMainThread())
            {
                results = new ConcurrentSearchList(context);

                Dispatcher.Enqueue(() =>
                {
                    results.AddItems(GetItems(context, options));
                    (results as ConcurrentSearchList)?.GetItemsDone();
                });

                return(results);
            }

            if (options.HasAny(SearchFlags.Sorted))
            {
                results = new SortedSearchList(context);
            }
            else
            {
                results = new AsyncSearchList(context);
            }

            results.AddItems(GetItems(context, options));
            return(results);
        }
Пример #3
0
        /// <summary>
        /// Execute a search request and callback for every incoming items and when the search is completed.
        /// The user is responsible for disposing of the search context.
        /// </summary>
        public static void Request(SearchContext context,
                                   Action <SearchContext, IEnumerable <SearchItem> > onIncomingItems,
                                   Action <SearchContext> onSearchCompleted,
                                   SearchFlags options = SearchFlags.None)
        {
            var requestId = Guid.NewGuid().ToString("N");

            if (options.HasAny(SearchFlags.Debug))
            {
                Debug.Log($"{requestId} Request started {context.searchText} ({options | context.options})");
            }
            var sessionCount       = 0;
            var firstBatchResolved = false;
            var completed          = false;
            var batchCount         = 1;

            void ReceiveItems(SearchContext c, IEnumerable <SearchItem> items)
            {
                if (options.HasAny(SearchFlags.Debug))
                {
                    Debug.Log($"{requestId} #{batchCount++} Request incoming batch {context.searchText}");
                }
                onIncomingItems?.Invoke(c, items.Where(e => e != null));
            }

            void OnSessionStarted(SearchContext c)
            {
                if (options.HasAny(SearchFlags.Debug))
                {
                    Debug.Log($"{requestId} Request session begin {context.searchText}");
                }
                ++sessionCount;
            }

            void OnSessionEnded(SearchContext c)
            {
                if (options.HasAny(SearchFlags.Debug))
                {
                    Debug.Log($"{requestId} Request session ended {context.searchText}");
                }
                --sessionCount;
                if (sessionCount == 0 && firstBatchResolved)
                {
                    if (options.HasAny(SearchFlags.Debug))
                    {
                        Debug.Log($"{requestId} Request async ended {context.searchText}");
                    }
                    context.asyncItemReceived -= ReceiveItems;
                    context.sessionStarted    -= OnSessionStarted;
                    context.sessionEnded      -= OnSessionEnded;
                    onSearchCompleted?.Invoke(c);
                    completed = true;
                }
            }

            context.asyncItemReceived += ReceiveItems;
            context.sessionStarted    += OnSessionStarted;
            context.sessionEnded      += OnSessionEnded;
            GetItems(context, options | SearchFlags.FirstBatchAsync);
            firstBatchResolved = true;
            if (sessionCount == 0 && !completed)
            {
                if (options.HasAny(SearchFlags.Debug))
                {
                    Debug.Log($"{requestId} Request sync ended {context.searchText}");
                }
                context.asyncItemReceived -= ReceiveItems;
                context.sessionStarted    -= OnSessionStarted;
                context.sessionEnded      -= OnSessionEnded;
                onSearchCompleted?.Invoke(context);
            }
        }
Пример #4
0
        /// <summary>
        /// Initiate a search and return all search items matching the search context. Other items can be found later using the asynchronous searches.
        /// </summary>
        /// <param name="context">The current search context</param>
        /// <param name="options">Options defining how the query will be performed</param>
        /// <returns>A list of search items matching the search query.</returns>
        public static List <SearchItem> GetItems(SearchContext context, SearchFlags options = SearchFlags.Default)
        {
            // Stop all search sessions every time there is a new search.
            context.sessions.StopAllAsyncSearchSessions();
            context.searchFinishTime = context.searchStartTime = DateTime.Now.Ticks;
            context.sessionEnded    -= OnSearchEnded;
            context.sessionEnded    += OnSearchEnded;

            context.sessions.StartSessions();

            if (options.HasAny(SearchFlags.WantsMore))
            {
                context.wantsMore = true;
            }

            if (options.HasAny(SearchFlags.Synchronous))
            {
                context.options |= SearchFlags.Synchronous;
            }

            int fetchProviderCount = 0;
            var allItems           = new List <SearchItem>(3);

            if (TryParseExpression(context, out var expression))
            {
                var iterator = EvaluateExpression(expression, context);
                HandleItemsIteratorSession(iterator, allItems, s_SearchServiceProvider.id, context, options);
                fetchProviderCount++;
            }
            else
            {
                foreach (var provider in context.providers)
                {
                    try
                    {
                        var watch = new System.Diagnostics.Stopwatch();
                        watch.Start();
                        fetchProviderCount++;
                        var iterator = provider.fetchItems(context, allItems, provider);
                        HandleItemsIteratorSession(iterator, allItems, provider.id, context, options);
                        provider.RecordFetchTime(watch.Elapsed.TotalMilliseconds);
                    }
                    catch (Exception ex)
                    {
                        Debug.LogException(new Exception($"Failed to get fetch {provider.name} provider items.", ex));
                    }
                }
            }

            if (fetchProviderCount == 0)
            {
                OnSearchEnded(context);
                context.sessions.StopAllAsyncSearchSessions();
            }

            if (context.subset != null)
            {
                allItems = new List <SearchItem>(allItems.Intersect(context.subset));
            }

            if (!options.HasAny(SearchFlags.Sorted))
            {
                return(allItems);
            }

            allItems.Sort(SortItemComparer);
            return(allItems.GroupBy(i => i.id).Select(i => i.First()).ToList());
        }
Пример #5
0
        /// <summary>
        /// Initiate a search and return all search items matching the search context. Other items can be found later using the asynchronous searches.
        /// </summary>
        /// <param name="context">The current search context</param>
        /// <param name="options">Options defining how the query will be performed</param>
        /// <returns>A list of search items matching the search query.</returns>
        public static List <SearchItem> GetItems(SearchContext context, SearchFlags options = SearchFlags.Default)
        {
            // Stop all search sessions every time there is a new search.
            context.sessions.StopAllAsyncSearchSessions();
            context.searchFinishTime = context.searchStartTime = DateTime.Now.Ticks;
            context.sessionEnded    -= OnSearchEnded;
            context.sessionEnded    += OnSearchEnded;

            if (options.HasAny(SearchFlags.WantsMore))
            {
                context.wantsMore = true;
            }

            if (options.HasAny(SearchFlags.Synchronous))
            {
                context.options |= SearchFlags.Synchronous;
            }

            int fetchProviderCount = 0;
            var allItems           = new List <SearchItem>(3);

            foreach (var provider in context.providers)
            {
                try
                {
                    var watch = new System.Diagnostics.Stopwatch();
                    watch.Start();
                    fetchProviderCount++;
                    var iterator = provider.fetchItems(context, allItems, provider);
                    if (iterator != null && options.HasAny(SearchFlags.Synchronous))
                    {
                        using (var stackedEnumerator = new SearchEnumerator <SearchItem>(iterator))
                        {
                            while (stackedEnumerator.MoveNext())
                            {
                                if (stackedEnumerator.Current != null)
                                {
                                    allItems.Add(stackedEnumerator.Current);
                                }
                            }
                        }
                    }
                    else
                    {
                        var session = context.sessions.GetProviderSession(context, provider.id);
                        session.Reset(context, iterator, k_MaxFetchTimeMs);
                        session.Start();
                        var sessionEnded = !session.FetchSome(allItems, k_MaxFetchTimeMs);
                        if (options.HasAny(SearchFlags.FirstBatchAsync))
                        {
                            session.SendItems(context.subset != null ? allItems.Intersect(context.subset) : allItems);
                            allItems.Clear();
                        }
                        if (sessionEnded)
                        {
                            session.Stop();
                        }
                    }
                    provider.RecordFetchTime(watch.Elapsed.TotalMilliseconds);
                }
                catch (Exception ex)
                {
                    Debug.LogException(new Exception($"Failed to get fetch {provider.name} provider items.", ex));
                }
            }

            if (fetchProviderCount == 0)
            {
                OnSearchEnded(context);
                context.sessions.StopAllAsyncSearchSessions();
            }

            if (context.subset != null)
            {
                allItems = new List <SearchItem>(allItems.Intersect(context.subset));
            }

            if (!options.HasAny(SearchFlags.Sorted))
            {
                return(allItems);
            }

            allItems.Sort(SortItemComparer);
            return(allItems.GroupBy(i => i.id).Select(i => i.First()).ToList());
        }