Skip to content

Commit 2e906a5

Browse files
committed
Refactoring to use channels
1 parent 9937aa3 commit 2e906a5

File tree

8 files changed

+211
-100
lines changed

8 files changed

+211
-100
lines changed

SmartImage.Lib 3/Results/SearchResult.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ public IEnumerable<SearchResultItem> GetAllResults()
8383
[CBN]
8484
public string Overview { get; internal set; }
8585

86-
/*
8786
[CBN]
8887
public SearchResultItem GetBestResult()
8988
{
@@ -94,7 +93,6 @@ public SearchResultItem GetBestResult()
9493
return Results.OrderByDescending(r => r.Similarity)
9594
.FirstOrDefault(r => Url.IsValid(r.Url));
9695
}
97-
*/
9896

9997
public bool IsStatusSuccessful => Status.IsSuccessful();
10098

SmartImage.Lib 3/SearchClient.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@
66
using System.Net.NetworkInformation;
77
using System.Runtime.CompilerServices;
88
using System.Text.Json;
9+
using System.Threading.Channels;
910
using Flurl.Http;
1011
using Flurl.Http.Configuration;
1112
using Flurl.Http.Testing;
1213
using Kantan.Net;
1314
using Kantan.Net.Utilities;
1415
using Kantan.Text;
16+
using Microsoft;
1517
using Microsoft.Extensions.Http;
1618
using Microsoft.Extensions.Http.Logging;
1719
using Microsoft.Extensions.Logging;
@@ -82,6 +84,18 @@ public static void Init()
8284

8385
public event SearchCompleteCallback OnComplete;
8486

87+
public Channel<SearchResult> ResultChannel { get; private set; }
88+
89+
public void OpenChannel()
90+
{
91+
ResultChannel?.Writer.TryComplete(new ChannelClosedException("Reopened channel"));
92+
93+
ResultChannel = Channel.CreateUnbounded<SearchResult>(new UnboundedChannelOptions()
94+
{
95+
SingleWriter = true,
96+
});
97+
}
98+
8599
/// <summary>
86100
/// Runs a search of <paramref name="query"/>.
87101
/// </summary>
@@ -95,6 +109,11 @@ public async Task<SearchResult[]> RunSearchAsync(SearchQuery query, bool reload
95109
{
96110
scheduler ??= TaskScheduler.Default;
97111

112+
// Requires.NotNull(ResultChannel);
113+
if (ResultChannel == null) {
114+
OpenChannel();
115+
}
116+
98117
if (!query.IsUploaded) {
99118
throw new ArgumentException($"Query was not uploaded", nameof(query));
100119
}
@@ -119,6 +138,7 @@ public async Task<SearchResult[]> RunSearchAsync(SearchQuery query, bool reload
119138
if (token.IsCancellationRequested) {
120139

121140
Logger.LogWarning("Cancellation requested");
141+
ResultChannel.Writer.Complete();
122142
IsComplete = true;
123143
IsRunning = false;
124144
return results;
@@ -137,6 +157,7 @@ public async Task<SearchResult[]> RunSearchAsync(SearchQuery query, bool reload
137157
// results.Add(result);
138158
}
139159

160+
ResultChannel.Writer.Complete();
140161
OnComplete?.Invoke(this, results);
141162
IsRunning = false;
142163
IsComplete = true;
@@ -174,6 +195,7 @@ public async Task<SearchResult[]> RunSearchAsync(SearchQuery query, bool reload
174195
private void ProcessResult(SearchResult result)
175196
{
176197
OnResult?.Invoke(this, result);
198+
ResultChannel.Writer.TryWrite(result);
177199

178200
if (Config.PriorityEngines.HasFlag(result.Engine.EngineOption)) {
179201
OpenResult(result);
@@ -359,6 +381,7 @@ public void Dispose()
359381
ConfigApplied = false;
360382
IsComplete = false;
361383
IsRunning = false;
384+
ResultChannel.Writer.Complete();
362385
}
363386

364387
}

SmartImage.Lib 3/SmartImage.Lib.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
5454
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.1" />
5555
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
56+
<PackageReference Include="Microsoft.VisualStudio.Validation" Version="17.8.8" />
5657
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.2" />
5758
<PackageReference Include="System.Configuration.ConfigurationManager" Version="8.0.0" />
5859
<PackageReference Include="System.Drawing.Common" Version="8.0.1" />

SmartImage.Rdx/SearchCommand.cs

Lines changed: 140 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@
1919
using SmartImage.Lib.Utilities;
2020
using Spectre.Console.Rendering;
2121
using System.Collections.Concurrent;
22+
using System.Collections.Specialized;
2223
using System.Diagnostics;
2324
using Flurl;
2425
using JetBrains.Annotations;
2526
using Kantan.Diagnostics;
2627
using Kantan.Model.MemberIndex;
2728
using Kantan.Utilities;
2829
using Novus.Streams;
30+
using Novus.Utilities;
2931
using SixLabors.ImageSharp.Processing;
3032
using SmartImage.Rdx.Cli;
3133

@@ -175,22 +177,35 @@ private async Task<int> RunSimpleAsync()
175177
.AutoRefresh(false)
176178
.StartAsync(async c =>
177179
{
178-
var p = c.AddTask("Running search");
179-
p.IsIndeterminate = true;
180180
var cnt = (double) Client.Engines.Length;
181-
var p2 = c.AddTask("Engines", maxValue: cnt);
181+
var p = c.AddTask("Running search", maxValue: cnt);
182+
p.IsIndeterminate = true;
183+
// var p2 = c.AddTask("Engines", maxValue: cnt);
182184

183-
Client.OnResult += OnResultComplete;
185+
// Client.OnResult += OnResultComplete;
184186

185187
var run = Client.RunSearchAsync(Query, token: m_cts.Token);
186188

189+
while (await Client.ResultChannel.Reader.WaitToReadAsync()) {
190+
var x = await Client.ResultChannel.Reader.ReadAsync();
191+
int i = 0;
192+
193+
var rm = new ResultModel(x)
194+
{ };
195+
196+
m_results.Add(rm);
197+
p.Description = $"{rm.Result.Engine.Name} {m_results.Count} / {cnt}";
198+
p.Increment(1);
199+
c.Refresh();
200+
}
201+
187202
await run;
188203

189-
Client.OnResult -= OnResultComplete;
204+
// Client.OnResult -= OnResultComplete;
190205

191206
return;
192207

193-
void OnResultComplete(object sender, SearchResult sr)
208+
/*void OnResultComplete(object sender, SearchResult sr)
194209
{
195210
int i = 0;
196211
@@ -201,7 +216,7 @@ void OnResultComplete(object sender, SearchResult sr)
201216
p2.Description = $"{rm.Result.Engine.Name} {m_results.Count} / {cnt}";
202217
p2.Increment(1);
203218
c.Refresh();
204-
}
219+
}*/
205220
});
206221

207222
await prog;
@@ -218,15 +233,44 @@ private async Task<int> RunTableAsync()
218233
.StartAsync(async (l) =>
219234
{
220235

221-
Client.OnResult += OnResultComplete;
236+
// Client.OnResult += OnResultComplete;
222237

223238
var run = Client.RunSearchAsync(Query, token: m_cts.Token);
224239

240+
while (await Client.ResultChannel.Reader.WaitToReadAsync()) {
241+
var sr = await Client.ResultChannel.Reader.ReadAsync();
242+
int i = 0;
243+
244+
var rm = new ResultModel(sr)
245+
{ };
246+
247+
m_results.Add(rm);
248+
249+
if (!sr.IsStatusSuccessful) {
250+
// Debugger.Break();
251+
var rows = rm.GetRowsForFormat(format);
252+
table.AddRow(rows);
253+
}
254+
else {
255+
var results = rm.GetRowsForFormat2(format);
256+
257+
foreach (IRenderable[] allResult in results) {
258+
table.AddRow(allResult);
259+
260+
}
261+
}
262+
263+
rm.UpdateGrid();
264+
265+
l.Refresh();
266+
}
267+
225268
await run;
226269

227-
Client.OnResult -= OnResultComplete;
270+
// Client.OnResult -= OnResultComplete;
228271
return;
229272

273+
/*
230274
void OnResultComplete(object sender, SearchResult sr)
231275
{
232276
int i = 0;
@@ -255,13 +299,100 @@ void OnResultComplete(object sender, SearchResult sr)
255299
l.Refresh();
256300
257301
}
302+
*/
258303
});
259304

260305
await live;
261306

262307
return EC_OK;
263308
}
264309

310+
public override ValidationResult Validate(CommandContext context, SearchCommandSettings settings)
311+
{
312+
var r = base.Validate(context, settings);
313+
return r;
314+
315+
// var v= base.Validate(context, settings);
316+
// return v;
317+
}
318+
319+
private void OnComplete(object sender, SearchResult[] searchResults)
320+
{
321+
// pt1.Increment(COMPLETE);
322+
if (!String.IsNullOrWhiteSpace(m_scs.CompletionCommand)) {
323+
var proc = new Process()
324+
{
325+
StartInfo =
326+
{
327+
FileName = m_scs.CompletionExecutable,
328+
Arguments = m_scs.CompletionCommand,
329+
UseShellExecute = false,
330+
CreateNoWindow = true,
331+
RedirectStandardError = true,
332+
RedirectStandardOutput = true
333+
}
334+
};
335+
proc.Start();
336+
337+
Debug.WriteLine($"starting {proc.Id}");
338+
339+
// proc.WaitForExit(TimeSpan.FromSeconds(3));
340+
// proc.Dispose();
341+
}
342+
343+
switch (m_scs.OutputFormat) {
344+
345+
case ResultFileFormat.None:
346+
break;
347+
348+
case ResultFileFormat.Delimited:
349+
var fw = File.OpenWrite(m_scs.OutputFile);
350+
351+
var sw = new StreamWriter(fw)
352+
{
353+
AutoFlush = true
354+
};
355+
var res = m_results.ToArray();
356+
var fields = m_scs.OutputFields;
357+
358+
for (int i = 0; i < res.Length; i++) {
359+
var sr = res[i].Result;
360+
361+
for (int j = 0; j < sr.Results.Count; j++) {
362+
var sri = sr.Results[j];
363+
364+
var rg = new List<string>();
365+
366+
if (fields.HasFlag(OutputFields.Name)) {
367+
rg.Add($"{sr.Engine.Name} #{j + 1}");
368+
}
369+
370+
if (fields.HasFlag(OutputFields.Url)) {
371+
rg.Add(sri.Url);
372+
}
373+
374+
if (fields.HasFlag(OutputFields.Similarity)) {
375+
rg.Add($"{sri.Similarity}");
376+
}
377+
378+
// string[] items = [$"{sr.Engine.Name} #{j + 1}", sri.Url?.ToString()];
379+
sw.WriteLine(String.Join(m_scs.OutputFileDelimiter, rg));
380+
}
381+
382+
}
383+
384+
sw.Dispose();
385+
fw.Dispose();
386+
387+
AConsole.WriteLine($"Wrote to {m_scs.OutputFile}");
388+
break;
389+
390+
default:
391+
throw new ArgumentOutOfRangeException();
392+
}
393+
394+
}
395+
265396
public async Task<int> RunInteractiveAsync()
266397
{
267398

@@ -367,77 +498,6 @@ public async Task<int> RunInteractiveAsync()
367498
return EC_OK;
368499
}
369500

370-
public override ValidationResult Validate(CommandContext context, SearchCommandSettings settings)
371-
{
372-
var r = base.Validate(context, settings);
373-
return r;
374-
375-
// var v= base.Validate(context, settings);
376-
// return v;
377-
}
378-
379-
private void OnComplete(object sender, SearchResult[] searchResults)
380-
{
381-
// pt1.Increment(COMPLETE);
382-
if (!String.IsNullOrWhiteSpace(m_scs.CompletionCommand)) {
383-
var proc = new Process()
384-
{
385-
StartInfo =
386-
{
387-
FileName = m_scs.CompletionExecutable,
388-
Arguments = m_scs.CompletionCommand,
389-
UseShellExecute = false,
390-
CreateNoWindow = true,
391-
RedirectStandardError = true,
392-
RedirectStandardOutput = true
393-
}
394-
};
395-
proc.Start();
396-
397-
Debug.WriteLine($"starting {proc.Id}");
398-
399-
// proc.WaitForExit(TimeSpan.FromSeconds(3));
400-
// proc.Dispose();
401-
}
402-
403-
switch (m_scs.OutputFormat) {
404-
405-
case ResultFileFormat.None:
406-
break;
407-
408-
case ResultFileFormat.Delimited:
409-
var fw = File.OpenWrite(m_scs.OutputFile);
410-
411-
var sw = new StreamWriter(fw)
412-
{
413-
AutoFlush = true
414-
};
415-
var res = m_results.ToArray();
416-
417-
for (int i = 0; i < res.Length; i++) {
418-
var sr = res[i].Result;
419-
420-
for (int j = 0; j < sr.Results.Count; j++) {
421-
var sri = sr.Results[j];
422-
423-
string[] items = [$"{sr.Engine.Name} #{j + 1}", sri.Url?.ToString()];
424-
sw.WriteLine(String.Join(m_scs.OutputFileDelimiter, items));
425-
}
426-
427-
}
428-
429-
sw.Dispose();
430-
fw.Dispose();
431-
432-
AConsole.WriteLine($"Wrote to {m_scs.OutputFile}");
433-
break;
434-
435-
default:
436-
throw new ArgumentOutOfRangeException();
437-
}
438-
439-
}
440-
441501
public void Dispose()
442502
{
443503
foreach (var sr in m_results) {

0 commit comments

Comments
 (0)