Skip to content

Commit 0af8120

Browse files
committed
支持进行 IPC 连接减少大量创建进程
1 parent fb61bb1 commit 0af8120

14 files changed

Lines changed: 291 additions & 7 deletions

src/MediaConverters/MediaConverters.Tool.ContextNuGet/MediaConverters.Tool.ContextNuGet.csproj

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,8 @@
1414
</PropertyGroup>
1515

1616
<ItemGroup>
17-
<Compile Include="..\MediaConverters.Tool\Contexts\*.cs" />
17+
<Compile Include="..\MediaConverters.Tool\Contexts\**\*.cs" />
1818
<None Include="..\README.md" Link="README.md" Pack="True" PackagePath="\" />
1919
</ItemGroup>
2020

21-
<ItemGroup>
22-
<Compile Remove="..\MediaConverters.Tool\Contexts\Options.cs" />
23-
</ItemGroup>
24-
2521
</Project>

src/MediaConverters/MediaConverters.Tool/CommandLineHandlers/ConvertHandler.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,12 @@ public class ConvertHandler : ICommandHandler
1919
[Option]
2020
public required string ConvertConfigurationFile { get; init; }
2121

22+
[Option]
2223
public bool? ShouldLogToConsole { get; init; }
24+
25+
[Option]
2326
public bool? ShouldLogToFile { get; init; }
27+
2428
public async Task<int> RunAsync()
2529
{
2630
return await Program.RunAsync(this);
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
using System;
2+
using dotnetCampus.Ipc.Context;
3+
using dotnetCampus.Ipc.IpcRouteds.DirectRouteds;
4+
using dotnetCampus.Ipc.Pipes;
5+
using dotnetCampus.Ipc.Threading;
6+
using dotnetCampus.Ipc.Utils.Buffers;
7+
8+
using DotNetCampus.Cli;
9+
using DotNetCampus.Cli.Compiler;
10+
using DotNetCampus.MediaConverters.Contexts;
11+
using DotNetCampus.MediaConverters.Contexts.IpcContexts;
12+
13+
using System.Buffers;
14+
using System.IO;
15+
using System.Threading;
16+
using System.Threading.Tasks;
17+
18+
namespace DotNetCampus.MediaConverters.CommandLineHandlers;
19+
20+
public class IpcHandler : ICommandHandler
21+
{
22+
[Option]
23+
public required string IpcName { get; init; }
24+
25+
/// <summary>
26+
/// 总的工作路径,可用在后续的转换过程中,存放日志或过程文件等
27+
/// </summary>
28+
[Option]
29+
public required string WorkingFolder { get; init; }
30+
31+
[Option]
32+
public bool? ShouldLogToConsole { get; init; }
33+
34+
[Option]
35+
public bool? ShouldLogToFile { get; init; }
36+
37+
public async Task<int> RunAsync()
38+
{
39+
var ipcConfiguration = new IpcConfiguration()
40+
{
41+
AutoReconnectPeers = false,
42+
IpcLoggerProvider = name => new MediaConverterIpcLogger(name, this),
43+
44+
// 以下为默认配置
45+
SharedArrayPool = new SharedArrayPool(ArrayPool<byte>.Shared),
46+
IpcTaskScheduling = IpcTaskScheduling.GlobalConcurrent,
47+
};
48+
ipcConfiguration.UseSystemJsonIpcObjectSerializer(MediaConverterJsonSerializerSourceGenerationContext.Default);
49+
50+
var ipcProvider = new IpcProvider(IpcName, ipcConfiguration);
51+
52+
var ipcHandlerLogger = new IpcHandlerLogger(this);
53+
var exitTaskCompletionSource = new TaskCompletionSource<int>();
54+
55+
var jsonIpcDirectRoutedProvider = new JsonIpcDirectRoutedProvider(ipcProvider);
56+
57+
jsonIpcDirectRoutedProvider.AddRequestHandler(IpcPaths.RequestConvertImage, async (IpcConvertImageRequest request) =>
58+
{
59+
if (request.InputFile is null || request.OutputFile is null || request.ConvertConfigurationFile is null)
60+
{
61+
return IpcConvertImageResponse.FromErrorCode(MediaConverterErrorCode.InvalidIpcRequestArgument);
62+
}
63+
64+
var traceId = request.TraceId ?? Guid.NewGuid().ToString();
65+
66+
var workingFolder = request.WorkingFolder;
67+
if (string.IsNullOrEmpty(workingFolder))
68+
{
69+
workingFolder = Path.Join(WorkingFolder, traceId);
70+
}
71+
72+
Directory.CreateDirectory(workingFolder);
73+
74+
ipcHandlerLogger.LogMessage($"[{traceId}] Receive RequestConvertImage. InputFile='{request.InputFile}' OutputFile='{request.OutputFile}' ConvertConfigurationFile='{request.ConvertConfigurationFile}' WorkingFolder='{workingFolder}'");
75+
76+
var convertHandler = new ConvertHandler()
77+
{
78+
InputFile = request.InputFile,
79+
OutputFile = request.OutputFile,
80+
ConvertConfigurationFile = request.ConvertConfigurationFile,
81+
WorkingFolder = workingFolder,
82+
ShouldLogToConsole = ShouldLogToConsole,
83+
ShouldLogToFile = ShouldLogToFile,
84+
};
85+
86+
var errorCode = await Program.RunAsync(convertHandler);
87+
ipcHandlerLogger.LogMessage($"[{traceId}] RequestConvertImage completed. ErrorCode={errorCode.Code} Message={errorCode.Message}");
88+
return IpcConvertImageResponse.FromErrorCode(errorCode);
89+
});
90+
91+
jsonIpcDirectRoutedProvider.AddRequestHandler(IpcPaths.Exit, (IpcExitRequest request) =>
92+
{
93+
ipcHandlerLogger.LogMessage($"Request Exit. Code={request.ExitCode} Reason={request.Reason}");
94+
95+
Task.Run(async () =>
96+
{
97+
await Task.Delay(TimeSpan.FromSeconds(1));
98+
exitTaskCompletionSource.SetResult(request.ExitCode);
99+
});
100+
101+
return new IpcExitResponse()
102+
{
103+
Code = MediaConverterErrorCode.Success.Code,
104+
Message = MediaConverterErrorCode.Success.Message
105+
};
106+
});
107+
108+
jsonIpcDirectRoutedProvider.StartServer();
109+
return await exitTaskCompletionSource.Task;
110+
}
111+
}
112+
113+
file class IpcHandlerLogger
114+
{
115+
public IpcHandlerLogger(IpcHandler ipcHandler)
116+
{
117+
_ipcHandler = ipcHandler;
118+
119+
CanLog = _ipcHandler.ShouldLogToConsole is true || _ipcHandler.ShouldLogToFile is true;
120+
121+
if (_ipcHandler.ShouldLogToFile is true)
122+
{
123+
var logFile = Path.Join(_ipcHandler.WorkingFolder, "Log.txt");
124+
_logFile = new FileInfo(logFile);
125+
}
126+
}
127+
128+
private readonly FileInfo? _logFile;
129+
private readonly IpcHandler _ipcHandler;
130+
private readonly Lock _locker = new Lock();
131+
132+
private bool CanLog { get; }
133+
134+
public void LogMessage(string message)
135+
{
136+
if (!CanLog)
137+
{
138+
return;
139+
}
140+
141+
if (_ipcHandler.ShouldLogToConsole is true)
142+
{
143+
Console.WriteLine(message);
144+
}
145+
146+
if (_logFile is { } logFile)
147+
{
148+
var logMessage = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss,fff}] {message}";
149+
lock (_locker)
150+
{
151+
File.AppendAllLines(logFile.FullName, [logMessage]);
152+
}
153+
}
154+
}
155+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using System;
2+
using System.IO;
3+
4+
using dotnetCampus.Ipc.Utils.Logging;
5+
6+
namespace DotNetCampus.MediaConverters.CommandLineHandlers;
7+
8+
class MediaConverterIpcLogger : IpcLogger
9+
{
10+
public MediaConverterIpcLogger(string name, IpcHandler ipcHandler) : base(name)
11+
{
12+
_ipcHandler = ipcHandler;
13+
if (_ipcHandler.ShouldLogToFile is true)
14+
{
15+
var ipcLogFile = Path.Join(_ipcHandler.WorkingFolder, "IpcLog.log");
16+
_logFile = new FileInfo(ipcLogFile);
17+
}
18+
}
19+
20+
private readonly IpcHandler _ipcHandler;
21+
22+
private bool ShouldLogToConsole => _ipcHandler.ShouldLogToConsole ?? false;
23+
private readonly FileInfo? _logFile;
24+
25+
protected override bool IsEnabled(LogLevel logLevel)
26+
{
27+
if (!ShouldLogToConsole && _logFile is null)
28+
{
29+
// 没有任何日志输出
30+
return false;
31+
}
32+
33+
return base.IsEnabled(logLevel);
34+
}
35+
36+
protected override void Log<TState>(LogLevel logLevel, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
37+
{
38+
if (!IsEnabled(logLevel))
39+
{
40+
return;
41+
}
42+
43+
var message = formatter(state, exception);
44+
if (ShouldLogToConsole)
45+
{
46+
Console.WriteLine($"[IPC] {message}");
47+
}
48+
if (_logFile is { } logFile)
49+
{
50+
var logMessage = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss,fff}][{logLevel}] {message}";
51+
lock (logFile)
52+
{
53+
File.AppendAllLines(logFile.FullName, [logMessage]);
54+
}
55+
}
56+
}
57+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace DotNetCampus.MediaConverters.Contexts.IpcContexts;
2+
3+
public class IpcConvertImageRequest
4+
{
5+
public string? TraceId { get; set; }
6+
public string? InputFile { get; set; }
7+
public string? OutputFile { get; set; }
8+
public string? ConvertConfigurationFile { get; set; }
9+
public string? WorkingFolder { get; set; }
10+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
namespace DotNetCampus.MediaConverters.Contexts.IpcContexts;
2+
3+
public class IpcConvertImageResponse
4+
{
5+
/// <summary>
6+
/// 错误代码
7+
/// </summary>
8+
public int Code { get; set; }
9+
10+
/// <summary>
11+
/// 错误信息
12+
/// </summary>
13+
public string? Message { get; set; }
14+
15+
internal static IpcConvertImageResponse FromErrorCode(MediaConverterErrorCode errorCode)
16+
{
17+
return new IpcConvertImageResponse()
18+
{
19+
Code = errorCode.Code,
20+
Message = errorCode.Message
21+
};
22+
}
23+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace DotNetCampus.MediaConverters.Contexts.IpcContexts;
2+
3+
public class IpcExitRequest
4+
{
5+
public int ExitCode { get; set; }
6+
public string? Reason { get; set; }
7+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
namespace DotNetCampus.MediaConverters.Contexts.IpcContexts;
2+
3+
public class IpcExitResponse
4+
{
5+
/// <summary>
6+
/// 错误代码
7+
/// </summary>
8+
public int Code { get; set; }
9+
/// <summary>
10+
/// 错误信息
11+
/// </summary>
12+
public string? Message { get; set; }
13+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace DotNetCampus.MediaConverters.Contexts.IpcContexts;
2+
3+
public static class IpcPaths
4+
{
5+
public const string RequestConvertImage = "/ConvertImage";
6+
public const string Exit = "/Exit";
7+
}

src/MediaConverters/MediaConverters.Tool/Contexts/MediaConverterErrorCode.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ public readonly record struct MediaConverterErrorCode
4242

4343
public static readonly ErrorCode UnknownException = new(1006, "Unknown exception");
4444

45+
public static readonly ErrorCode InvalidIpcRequestArgument = new(1007, "Ipc argument error");
46+
4547
/// <summary>
4648
/// 错误代码
4749
/// </summary>

0 commit comments

Comments
 (0)