Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/revamp #105

Open
wants to merge 53 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
51ae923
taking shape
eduard-dumitru Jun 11, 2024
ee679a0
temporarily disable branch check for CI nuget push
eduard-dumitru Jun 11, 2024
f1927a2
Fix/namedpipe close (#97)
danutboanta Feb 2, 2024
047d405
cherry pick fix to Spurious Closed Pipes (ROBO-3083)
eduard-dumitru Jun 12, 2024
753be9c
rename assembly and package
eduard-dumitru Jun 12, 2024
a25cd01
fixes
eduard-dumitru Jun 12, 2024
22df014
decommission object params (#103)
eduard-dumitru Jun 26, 2024
2601f27
decommission cryptography
eduard-dumitru Jun 27, 2024
0959a95
change namespace from UiPath.CoreIpc to UiPath.Ipc
eduard-dumitru Jun 27, 2024
71cc234
fixes after namespace change
eduard-dumitru Jun 27, 2024
ab26f0c
fix tests
eduard-dumitru Jun 27, 2024
b53aeb0
reduce public api 1st round
eduard-dumitru Jun 27, 2024
8897b05
downgrade Microsoft.Extensions.DependencyInjection.Abstractions back …
eduard-dumitru Jul 1, 2024
a044fc5
revamp configuration and callback management
eduard-dumitru Jul 4, 2024
da0d120
static all the things almost
eduard-dumitru Jul 4, 2024
84f780e
taking shape
eduard-dumitru Jul 5, 2024
7158d57
extensibility
eduard-dumitru Jul 10, 2024
1df069a
after quick review
eduard-dumitru Jul 15, 2024
45e3370
simplify IpcServer config and decommission server's Callbacks setting
eduard-dumitru Jul 17, 2024
9f1a386
taking shape
eduard-dumitru Jul 17, 2024
b6930af
taking shape
eduard-dumitru Jul 24, 2024
481ef4e
taking shape
eduard-dumitru Jul 25, 2024
c87d9bf
working state
eduard-dumitru Jul 26, 2024
8f7f5be
tests taking shape
eduard-dumitru Jul 26, 2024
46ce612
fixes and test reconciliation
eduard-dumitru Jul 27, 2024
a491e3a
fix js NodeInterop
eduard-dumitru Jul 27, 2024
be30f9c
taking shape
eduard-dumitru Jul 29, 2024
4b29ac9
GetProxy simplification
eduard-dumitru Jul 29, 2024
5fdca6d
allow BeforeCall to set AsyncLocal for the targeted method itself
eduard-dumitru Jul 29, 2024
321dbe0
adjust public members
eduard-dumitru Jul 31, 2024
2b5b90a
system tests
eduard-dumitru Aug 4, 2024
7bfd50f
fix test brittleness
eduard-dumitru Aug 6, 2024
3506106
tests working
eduard-dumitru Aug 6, 2024
1cfc3c3
decomission Pollyfill nuget and replace it with manual polyfills
eduard-dumitru Aug 6, 2024
decb270
decommission Nito.AsyncEx
eduard-dumitru Aug 6, 2024
521e536
fix bug
eduard-dumitru Aug 7, 2024
c6c737c
decomission old tests
eduard-dumitru Aug 7, 2024
e966d75
fixes, tweaks and enhancements
eduard-dumitru Aug 7, 2024
0135fa5
integrate js nodeinterop
eduard-dumitru Aug 7, 2024
bc60228
fix nuget.config and move benchmarks
eduard-dumitru Aug 7, 2024
4e24f36
tweak test timeouts
eduard-dumitru Aug 7, 2024
3f9902d
fix nodeinterop integration
eduard-dumitru Aug 7, 2024
558f282
benchmark fixes
eduard-dumitru Aug 7, 2024
cc84e0f
nodeinterop fixes
eduard-dumitru Aug 8, 2024
ef34081
expand router to all inherited interfaces with last come wins semantics
eduard-dumitru Aug 8, 2024
e93e8ed
namedpipe impersonation fix
eduard-dumitru Aug 12, 2024
b5ce48c
fix: no beforecall for incomming callbacks
eduard-dumitru Aug 13, 2024
28c6d3c
simplify Ipc client api
eduard-dumitru Aug 15, 2024
b1dc8ab
reintroduce ConnectionFactory as BeforeConnect
eduard-dumitru Aug 16, 2024
6dd4d9a
commission waitforstart
eduard-dumitru Aug 26, 2024
2f07b37
decommission IAsyncStream and the Network union
eduard-dumitru Aug 28, 2024
90aff05
update public API report
eduard-dumitru Aug 28, 2024
1811e00
fixes and simplification
eduard-dumitru Aug 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/NuGet.Config → NuGet.Config
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
<configuration>
<packageSources>
<add key="Nuget" value="https://api.nuget.org/v3/index.json" />
<add key="UiPath-Internal" value="https://uipath.pkgs.visualstudio.com/Public.Feeds/_packaging/UiPath-Internal/nuget/v3/index.json" />
</packageSources>
</configuration>
28 changes: 28 additions & 0 deletions benchmarks/Benchmarks.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UiPath.CoreIpc", "..\src\UiPath.CoreIpc\UiPath.CoreIpc.csproj", "{6E3048EE-987B-4846-84EF-305A286092B1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UiPath.Ipc.Benchmarks", "UiPath.Ipc.Benchmarks\UiPath.Ipc.Benchmarks.csproj", "{D12CCF62-00C5-4291-A6A8-D3321C107EE7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6E3048EE-987B-4846-84EF-305A286092B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6E3048EE-987B-4846-84EF-305A286092B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6E3048EE-987B-4846-84EF-305A286092B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6E3048EE-987B-4846-84EF-305A286092B1}.Release|Any CPU.Build.0 = Release|Any CPU
{D12CCF62-00C5-4291-A6A8-D3321C107EE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D12CCF62-00C5-4291-A6A8-D3321C107EE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D12CCF62-00C5-4291-A6A8-D3321C107EE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D12CCF62-00C5-4291-A6A8-D3321C107EE7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
41 changes: 41 additions & 0 deletions benchmarks/UiPath.Ipc.Benchmarks/IpcBenchmark.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using UiPath.Ipc.Benchmarks;

[SimpleJob(RuntimeMoniker.Net461, baseline: true)]
[SimpleJob(RuntimeMoniker.Net80)]
[RPlotExporter]
public class IpcBenchmark
{
private Technology _technology = null!;
private Technology.IProxy _proxy = null!;

[Params(TechnologyId.Old, TechnologyId.New)]
public TechnologyId TechId;

[GlobalSetup]
public async Task Setup()
{
_technology = TechId.Create();
await _technology.Init();
_proxy = _technology.GetProxy();
}

[GlobalCleanup]
public async Task Cleanup()
{
await _technology.DisposeAsync();
}

[Benchmark]
public async Task SimpleCall()
{
_ = await _proxy.AddFloats(1, 1);
}

[Benchmark]
public async Task CallWithCallback()
{
_ = await _proxy.GetCallbackThreadName();
}
}
15 changes: 15 additions & 0 deletions benchmarks/UiPath.Ipc.Benchmarks/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using BenchmarkDotNet.Running;
using UiPath.Ipc.Benchmarks;


// await Run(TechnologyId.New);
// BenchmarkRunner.Run<IpcBenchmark>();
BenchmarkRunner.Run<SchedulerBenchmark>();

static async Task Run(TechnologyId techId)
{
await using var tech = techId.Create();
await tech.Init();
var x = await tech.GetProxy().AddFloats(1, 1);
Console.WriteLine($"{nameof(x)} == {x}");
}
65 changes: 65 additions & 0 deletions benchmarks/UiPath.Ipc.Benchmarks/SchedulerBenchmark.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using Nito.AsyncEx;

[SimpleJob(RuntimeMoniker.Net461, baseline: true)]
[SimpleJob(RuntimeMoniker.Net80)]
[RPlotExporter]
public class SchedulerBenchmark
{
private TaskScheduler _scheduler = null!;

[Params(SchedulerKind.ConcurrentExclusive, SchedulerKind.AsyncContextThread)]
public SchedulerKind SchedulerKind;

[GlobalSetup]
public void Setup()
{
_scheduler = SchedulerKind.Create();
}

[GlobalCleanup]
public void Cleanup()
{
_scheduler = null!;
}

[Benchmark]
public void Schedule()
{
_scheduler.RunAsync(async () =>
{
});
}
}

public enum SchedulerKind
{
ConcurrentExclusive,
AsyncContextThread
}

public static class SchedulerKindExtensions
{
public static TaskScheduler Create(this SchedulerKind schedulerKind)
{
switch (schedulerKind)
{
case SchedulerKind.ConcurrentExclusive:
return new ConcurrentExclusiveSchedulerPair().ExclusiveScheduler;
case SchedulerKind.AsyncContextThread:
return new AsyncContextThread().Context.Scheduler;
default:
throw new ArgumentOutOfRangeException(nameof(schedulerKind));
}
}
}

public static class TaskExtensions
{
public static Task RunAsync(this TaskScheduler scheduler, Func<Task> asyncAction)
=> Task.Factory.StartNew(asyncAction, CancellationToken.None, TaskCreationOptions.DenyChildAttach, scheduler).Unwrap();

public static Task<T> RunAsync<T>(this TaskScheduler scheduler, Func<Task<T>> asyncFunc)
=> Task.Factory.StartNew(asyncFunc, CancellationToken.None, TaskCreationOptions.DenyChildAttach, scheduler).Unwrap();
}
106 changes: 106 additions & 0 deletions benchmarks/UiPath.Ipc.Benchmarks/Switch/Technology.New.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using UiPath.Ipc.Transport.NamedPipe;

namespace UiPath.Ipc.Benchmarks;

partial class Technology
{
public sealed class New : Technology, IProxy
{
private const string PipeName = "BenchmarkPipeNew";
private const int ConcurrentAccepts = 10;
private const int MaxRequestMB = 100;

private static readonly TimeSpan ServerTimeout = TimeSpan.FromDays(1);
private static readonly TimeSpan ClientTimeout = TimeSpan.FromDays(1);
private readonly TaskScheduler _scheduler = new ConcurrentExclusiveSchedulerPair().ExclusiveScheduler;

private readonly ComputingCallback _computingCallback = new();
private readonly ServiceProvider _serviceProvider;
private readonly IpcServer _server;
private readonly ClientBase _client;
private readonly IComputingService _proxy;

public New()
{
_serviceProvider = new ServiceCollection()
.AddLogging()
.AddSingleton<IComputingService, ComputingService>()
.BuildServiceProvider();

_server = new IpcServer
{
Endpoints = new()
{
{ typeof(IComputingService) }
},
Listeners = [
new NamedPipeListener
{
PipeName = PipeName,
RequestTimeout = ServerTimeout,
ConcurrentAccepts = ConcurrentAccepts,
MaxReceivedMessageSizeInMegabytes = MaxRequestMB
}
],
Scheduler = _scheduler,
ServiceProvider = _serviceProvider
};

_client = new NamedPipeClient
{
PipeName = PipeName,
AllowImpersonation = true,
RequestTimeout = TimeSpan.FromSeconds(5),
Scheduler = _scheduler,
Callbacks = new()
{
{ typeof(IComputingCallback), _computingCallback }
}
};

_proxy = _client.GetProxy<IComputingService>();
}

public override async Task Init()
{
_server.Start();
_ = await GetProxy().GetCallbackThreadName();
}

public override async ValueTask DisposeAsync()
{
(_proxy as IpcProxy)!.Dispose();
await _server.DisposeAsync();
}

public override IProxy GetProxy() => this;

Task<float> IProxy.AddFloats(float x, float y) => _proxy.AddFloats(x, y);
Task<string> IProxy.GetCallbackThreadName() => _proxy.GetCallbackThreadName(TimeSpan.Zero);


private interface IComputingService
{
Task<float> AddFloats(float x, float y, CancellationToken ct = default);
Task<string> GetCallbackThreadName(TimeSpan duration, Message message = null!, CancellationToken cancellationToken = default);
}

private sealed class ComputingService(ILogger<ComputingService> logger) : IComputingService
{
public async Task<float> AddFloats(float a, float b, CancellationToken ct = default)
{
logger.LogInformation($"{nameof(AddFloats)} called.");
return a + b;
}

public async Task<string> GetCallbackThreadName(TimeSpan duration, Message message = null!, CancellationToken cancellationToken = default)
{
await Task.Delay(duration);
return await message.GetCallback<IComputingCallback>().GetThreadName();
}
}
}
}

99 changes: 99 additions & 0 deletions benchmarks/UiPath.Ipc.Benchmarks/Switch/Technology.Old.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using UiPath.CoreIpc;
using UiPath.CoreIpc.NamedPipe;

namespace UiPath.Ipc.Benchmarks;

partial class Technology
{
public sealed class Old : Technology, IProxy
{
private const string PipeName = "BenchmarkPipeOld";
private const int ConcurrentAccepts = 10;
private const int MaxRequestMB = 100;

private static readonly TimeSpan ServerTimeout = TimeSpan.FromDays(1);
private static readonly TimeSpan ClientTimeout = TimeSpan.FromSeconds(1);
private readonly TaskScheduler _scheduler = new ConcurrentExclusiveSchedulerPair().ExclusiveScheduler;
private Task? _serverRunning;

private readonly ComputingCallback _computingCallback = new();
private readonly ServiceProvider _serverServiceProvider;
private readonly ServiceProvider _clientServiceProvider;
private readonly ServiceHost _serviceHost;
private readonly IComputingService _proxy;

public Old()
{
_serverServiceProvider = new ServiceCollection()
.AddIpc()
.AddLogging()
.AddSingleton<IComputingService, ComputingService>()
.BuildServiceProvider();

_clientServiceProvider = new ServiceCollection()
.AddIpc()
.AddLogging()
.AddSingleton<IComputingCallback>(_computingCallback)
.BuildServiceProvider();

_serviceHost = new ServiceHostBuilder(_serverServiceProvider)
.AddEndpoint<IComputingService, IComputingCallback>()
.UseNamedPipes(new NamedPipeSettings(PipeName)
{
RequestTimeout = ServerTimeout,
ConcurrentAccepts = ConcurrentAccepts,
MaxReceivedMessageSizeInMegabytes = MaxRequestMB,
})
.Build();

_proxy = new NamedPipeClientBuilder<IComputingService, IComputingCallback>(PipeName, _clientServiceProvider)
.AllowImpersonation()
.RequestTimeout(ClientTimeout)
.TaskScheduler(_scheduler)
.CallbackInstance(_computingCallback)
.Build();
}

public override async Task Init()
{
_serverRunning = _serviceHost.RunAsync(_scheduler);
_ = await GetProxy().GetCallbackThreadName();
}

public override async ValueTask DisposeAsync()
{
(_proxy as CoreIpc.IpcProxy)!.Dispose();
_serviceHost.Dispose();
await (_serverRunning ?? Task.CompletedTask);
}

public override IProxy GetProxy() => this;

Task<float> IProxy.AddFloats(float x, float y) => _proxy.AddFloats(x, y);
Task<string> IProxy.GetCallbackThreadName() => _proxy.GetCallbackThreadName(TimeSpan.Zero);

private interface IComputingService
{
Task<float> AddFloats(float x, float y, CancellationToken ct = default);
Task<string> GetCallbackThreadName(TimeSpan duration, CoreIpc.Message message = null!, CancellationToken cancellationToken = default);
}

private sealed class ComputingService(ILogger<ComputingService> logger) : IComputingService
{
public async Task<float> AddFloats(float a, float b, CancellationToken ct = default)
{
logger.LogInformation($"{nameof(AddFloats)} called.");
return a + b;
}

public async Task<string> GetCallbackThreadName(TimeSpan duration, CoreIpc.Message message = null!, CancellationToken cancellationToken = default)
{
await Task.Delay(duration);
return await message.GetCallback<IComputingCallback>().GetThreadName();
}
}
}
}

26 changes: 26 additions & 0 deletions benchmarks/UiPath.Ipc.Benchmarks/Switch/Technology.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
namespace UiPath.Ipc.Benchmarks;

public abstract partial class Technology : IAsyncDisposable
{
public abstract Task Init();
public abstract ValueTask DisposeAsync();

public abstract IProxy GetProxy();

public interface IProxy
{
Task<float> AddFloats(float x, float y);
Task<string> GetCallbackThreadName();
}

public interface IComputingCallback
{
Task<string> GetThreadName();
}

public sealed class ComputingCallback : IComputingCallback
{
public async Task<string> GetThreadName() => Thread.CurrentThread.Name!;
}
}

Loading