1- global using CMN = System . Runtime . CompilerServices . CallerMemberNameAttribute ;
1+ global using EC = System . Runtime . CompilerServices . EnumeratorCancellationAttribute ;
2+ global using CMN = System . Runtime . CompilerServices . CallerMemberNameAttribute ;
23global using JI = System . Text . Json . Serialization . JsonIgnoreAttribute ;
34global using ICBN = JetBrains . Annotations . ItemCanBeNullAttribute ;
45global using INN = JetBrains . Annotations . ItemNotNullAttribute ;
3435using SmartImage . Lib . Results . Data ;
3536using static System . Runtime . InteropServices . JavaScript . JSType ;
3637using SmartImage . Lib . Utilities . Diagnostics ;
38+ using Kantan . Monad ;
3739
3840namespace SmartImage . Lib ;
3941
@@ -62,12 +64,13 @@ public SearchClient(SearchConfig cfg)
6264
6365 }
6466
65- static SearchClient ( )
66- { }
67+ static SearchClient ( ) { }
6768
6869 [ ModuleInitializer ]
6970 public static void Init ( )
7071 {
72+ Trace . AutoFlush = true ;
73+ Debug . AutoFlush = true ;
7174 s_logger . LogInformation ( "Init" ) ;
7275
7376
@@ -99,23 +102,27 @@ public void OpenChannel()
99102 {
100103 var ok = ResultChannel ? . Writer . TryComplete ( new ChannelClosedException ( "Reopened channel" ) ) ;
101104
102- if ( ok . HasValue && ok . Value ) { }
105+ if ( ok . HasValue && ok . Value ) {
106+ // ...
107+ }
103108
104109 ResultChannel = Channel . CreateUnbounded < SearchResult > ( new UnboundedChannelOptions ( )
105110 {
106111 SingleWriter = true ,
112+
107113 } ) ;
108114 }
109115
116+ #if OLD
110117 /// <summary>
111118 /// Runs a search of <paramref name="query"/>.
112119 /// </summary>
113120 /// <param name="query">Search query</param>
114121 /// <param name="scheduler"></param>
115122 /// <param name="token">Cancellation token passed to <see cref="WebSearchEngine{T}.GetResultAsync(SmartImage.Lib.SearchQuery,System.Threading.CancellationToken)"/></param>
116- public async Task < SearchResult [ ] > RunSearchAsync ( SearchQuery query ,
117- TaskScheduler scheduler = default ,
118- CancellationToken token = default )
123+ public async Task < SearchResult [ ] > RunSearchAsync1 ( SearchQuery query ,
124+ TaskScheduler scheduler = default ,
125+ CancellationToken token = default )
119126 {
120127 scheduler ??= TaskScheduler . Default ;
121128
@@ -140,12 +147,12 @@ public async Task<SearchResult[]> RunSearchAsync(SearchQuery query,
140147
141148 Debug . WriteLine ( $ "Config: { Config } | { Engines . QuickJoin ( ) } ") ;
142149
143- List < Task < SearchResult > > tasks = GetSearchTasks ( query , scheduler , token ) . ToList ( ) ;
150+ var tasks = GetSearchTasks ( query , scheduler , token ) ;
144151
145- var results = new SearchResult [ tasks . Count ] ;
146- int i = 0 ;
152+ // var results = new SearchResult[tasks.Count];
153+ int i = 0 ;
147154
148- while ( tasks . Count > 0 ) {
155+ /* while (tasks.Count > 0) {
149156 if (token.IsCancellationRequested) {
150157
151158 Debugger.Break();
@@ -164,6 +171,19 @@ public async Task<SearchResult[]> RunSearchAsync(SearchQuery query,
164171
165172 results[i] = result;
166173 i++;
174+ }*/
175+
176+
177+ await foreach ( var task in Task . WhenEach ( tasks ) . WithCancellation ( token ) ) {
178+ if ( token . IsCancellationRequested ) {
179+
180+ Debugger . Break ( ) ;
181+ s_logger . LogWarning ( "Cancellation requested" ) ;
182+ CompleteSearchAsync ( ) ;
183+ }
184+
185+ var result = await task ;
186+ ProcessResult ( result ) ;
167187 }
168188
169189 CompleteSearchAsync ( ) ;
@@ -191,8 +211,60 @@ public async Task<SearchResult[]> RunSearchAsync(SearchQuery query,
191211
192212 return results ;
193213 }
214+ #endif
215+
216+ public async IAsyncEnumerable < SearchResult > RunSearchAsync ( SearchQuery query ,
217+ TaskScheduler scheduler = default ,
218+ [ EC ] CancellationToken token = default )
219+ {
220+ await RunSearchAsync2 ( query , ResultChannel . Writer , token ) ;
221+
222+ await foreach ( var result in ResultChannel . Reader . ReadAllAsync ( token ) ) {
223+ yield return result ;
224+ }
225+ }
226+
227+
228+ /// <summary>
229+ /// Runs a search of <paramref name="query"/>.
230+ /// </summary>
231+ public async ValueTask < bool > RunSearchAsync2 ( SearchQuery query ,
232+ ChannelWriter < SearchResult > cw ,
233+ CancellationToken token = default )
234+ {
235+ if ( ! query . IsUploaded ) {
236+ throw new SmartImageException ( $ "{ query } was not uploaded") ;
237+ }
238+
239+ var tasks = Engines . Select ( e =>
240+ {
241+ var task = e . GetResultAsync ( query , token ) ;
242+ return task ;
243+ } ) ;
244+
245+ await foreach ( var task in Task . WhenEach ( tasks ) . WithCancellation ( token ) ) {
246+
247+ var result = await task ;
248+
249+ if ( task . IsFaulted || task . IsCanceled ) {
250+ Trace . WriteLine ( $ "{ task } faulted or was canceled") ;
251+ }
252+
253+ if ( cw . TryWrite ( result ) ) {
254+ //
255+ }
256+
257+ if ( Config . PriorityEngines . HasFlag ( result . Engine . EngineOption ) ) {
258+ var url = Config . OpenRaw ? result . RawUrl : result . GetBestResult ( ) ? . Url ;
259+
260+ OpenResult ( url ) ;
261+ }
262+ }
263+
264+ return default ;
265+ }
194266
195- public static SearchResultItem GetBest ( SearchResult [ ] results )
267+ public static SearchResultItem GetBest ( IEnumerable < SearchResult > results )
196268 {
197269 var ordered = results . Select ( x => x . GetBestResult ( ) )
198270 . Where ( x => x != null )
@@ -259,16 +331,10 @@ public IEnumerable<Task<SearchResult>> GetSearchTasks(SearchQuery query, TaskSch
259331 {
260332 var tasks = Engines . Select ( e =>
261333 {
262- try {
334+ /* try {
263335 Debug.WriteLine($"Starting {e} for {query}");
264336
265- Task < SearchResult > res = e . GetResultAsync ( query , token : token )
266- . ContinueWith ( ( r ) =>
267- {
268- ProcessResult ( r . Result ) ;
269- return r . Result ;
270337
271- } , token , TaskContinuationOptions . None , scheduler ) ;
272338
273339 return res;
274340 }
@@ -279,7 +345,19 @@ public IEnumerable<Task<SearchResult>> GetSearchTasks(SearchQuery query, TaskSch
279345 // return Task.FromException(exception);
280346 }
281347
282- return default ;
348+ return default;*/
349+
350+ /*Task<SearchResult> res = e.GetResultAsync(query, token: token)
351+ .ContinueWith((r) =>
352+ {
353+ ProcessResult(r.Result);
354+ return r.Result;
355+
356+ }, token, TaskContinuationOptions.None, scheduler)*/
357+ ;
358+
359+ Task < SearchResult > res = e . GetResultAsync ( query , token : token ) ;
360+ return res ;
283361 } ) ;
284362
285363 return tasks ;
@@ -306,7 +384,7 @@ public async ValueTask LoadEnginesAsync(CancellationToken token = default)
306384 }
307385
308386 if ( Config . FlareSolverr && ! FlareSolverrClient . Value . IsInitialized ) {
309-
387+
310388
311389 var ok = FlareSolverrClient . Value . Configure ( Config . FlareSolverrApiUrl ) ;
312390
@@ -360,4 +438,4 @@ public void Dispose()
360438 ResultChannel ? . Writer . Complete ( ) ;
361439 }
362440
363- }
441+ }
0 commit comments