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

Add PluggableComponentServiceBuilder #1

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
79 changes: 49 additions & 30 deletions Dapr.PluggableComponents.AspNetCore/PluggableComponentService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,72 +3,91 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;

namespace Dapr.PluggableComponents.AspNetCore {
namespace Dapr.PluggableComponents.AspNetCore
{
public class PluggableComponentService
{
private readonly WebApplication _app;
private readonly WebApplicationBuilder _builder;

public PluggableComponentService(String? socketPath = null, WebApplicationOptions? options = null)
public PluggableComponentService(
String? socketPath = null,
WebApplicationOptions? options = null
)
{
var udsPath = socketPath ??
Environment.GetEnvironmentVariable(Constants.DaprSocketPathEnvironmentVariable) ??
"daprcomponent.sock";

var udsPath =
socketPath
?? Environment
.GetEnvironmentVariable(Constants
.DaprSocketPathEnvironmentVariable)
?? "daprcomponent.sock";

Console.WriteLine("Starting Dapr pluggable component");
Console.WriteLine(format: @"Using UNIX socket located at {0}", udsPath);

Console
.WriteLine(format: @"Using UNIX socket located at {0}",
udsPath);

if (File.Exists(udsPath))
{
Console.WriteLine("Removing existing socket");
File.Delete(udsPath);
}

var builder = WebApplication.CreateBuilder(options: options ?? new WebApplicationOptions());

builder.WebHost.ConfigureKestrel(options =>
{
options.ListenUnixSocket(udsPath);
});


var builder =
WebApplication
.CreateBuilder(options: options
?? new WebApplicationOptions());

builder
.WebHost
.ConfigureKestrel(options =>
{
options.ListenUnixSocket(udsPath);
});

builder.Services.AddGrpc();
_builder = builder;
_app = builder.Build();
}

public PluggableComponentService WithStateStore<TService>() where TService : StateStoreService

public PluggableComponentService WithStateStore<TService>()
where TService : StateStoreService
{
_app.MapGrpcService<TService>();
return this;
}

public PluggableComponentService WithPubSub<TService>() where TService : PubSubService

public PluggableComponentService WithPubSub<TService>()
where TService : PubSubService
{
_app.MapGrpcService<TService>();
return this;
}

public PluggableComponentService WithInputBinding<TService>() where TService : InputBindingService

public PluggableComponentService WithInputBinding<TService>()
where TService : InputBindingService
{
_app.MapGrpcService<TService>();
return this;
}

public PluggableComponentService WithOutputBinding<TService>() where TService : OutputBindingService

public PluggableComponentService WithOutputBinding<TService>()
where TService : OutputBindingService
{
_app.MapGrpcService<TService>();
return this;
}

public PluggableComponentService WithHttpMiddleware<TService>() where TService : HttpMiddlewareService

public PluggableComponentService WithHttpMiddleware<TService>()
where TService : HttpMiddlewareService
{
_app.MapGrpcService<TService>();
return this;
}

public void Run(string? url = null)
{
_app.Run(url);
}


}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
using Dapr.PluggableComponents.Components;
using Dapr.PluggableComponents.Services;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;

namespace Dapr.PluggableComponents.AspNetCore
{
public class PluggableComponentServiceBuilder
{
private List<Action<WebApplication>> appCallbacks;
private List<Action<WebApplicationBuilder>> builderCallbacks;

private PluggableComponentServiceBuilder()
{
appCallbacks = new List<Action<WebApplication>>();
builderCallbacks = new List<Action<WebApplicationBuilder>>();
}
private PluggableComponentServiceBuilder(PluggableComponentServiceBuilder other) : this()
{
this.appCallbacks = new List<Action<WebApplication>>(other.appCallbacks);
this.builderCallbacks = new List<Action<WebApplicationBuilder>>(other.builderCallbacks);
}

public static PluggableComponentServiceBuilder CreateBuilder(string? socketPath = null)
{
var udsPath =
socketPath
?? Environment
.GetEnvironmentVariable(Constants
.DaprSocketPathEnvironmentVariable)
?? "daprcomponent.sock";

Console.WriteLine("Starting Dapr pluggable component");
Console
.WriteLine(format: @"Using UNIX socket located at {0}",
udsPath);

if (File.Exists(udsPath))
{
Console.WriteLine("Removing existing socket");
File.Delete(udsPath);
}
return new PluggableComponentServiceBuilder().UseSocket(udsPath).WithBuilderCallback(builder =>
{
builder.Services.AddGrpc();
});
}

public PluggableComponentServiceBuilder UseSocket(string socketPath)
{
return this.WithBuilderCallback(builder =>
{
builder
.WebHost
.ConfigureKestrel(options =>
{
options.ListenUnixSocket(socketPath);
});
});
}

public PluggableComponentServiceBuilder UseStateStore(Func<IStateStore> stateStoreFactory)
{
return this.UseServiceFactory<IStateStore, StateStoreService>(stateStoreFactory);
}

public PluggableComponentServiceBuilder UseLockStore(Func<ILockStore> lockStoreFactory)
{
return this.UseServiceFactory<ILockStore, LockService>(lockStoreFactory);
}

public PluggableComponentServiceBuilder UseInputBinding(Func<IInputBinding> inputBindingFactory)
{
return this.UseServiceFactory<IInputBinding, InputBindingService>(inputBindingFactory);
}

public PluggableComponentServiceBuilder UseOutputputBinding(Func<IOutputBinding> outputBindingFactory)
{
return this.UseServiceFactory<IOutputBinding, OutputBindingService>(outputBindingFactory);
}
public PluggableComponentServiceBuilder UseNameResolver(Func<INameResolver> nameResolverFactory)
{
return this.UseServiceFactory<INameResolver, NameResolutionService>(nameResolverFactory);
}
public PluggableComponentServiceBuilder UsePubSub(Func<IPubSubComponent> pubSubFactory)
{
return this.UseServiceFactory<IPubSubComponent, PubSubService>(pubSubFactory);
}
public PluggableComponentServiceBuilder UseHttpMiddleware(Func<IHttpMiddleware> httpMiddlewareFactory)
{
return this.UseServiceFactory<IHttpMiddleware, HttpMiddlewareService>(httpMiddlewareFactory);
}

public PluggableComponentServiceBuilder UseConfigurationStore(Func<IConfigurationStore> configurationStoreFactory)
{
return this.UseServiceFactory<IConfigurationStore, ConfigurationStoreService>(configurationStoreFactory);
}

public PluggableComponentServiceBuilder UseSecretStore(Func<ISecretStore> secretStoreFactory)
{
return this.UseServiceFactory<ISecretStore, SecretStoreService>(secretStoreFactory);
}

private PluggableComponentServiceBuilder UseServiceFactory<TImpl, TService>(Func<TImpl> factory) where TImpl : class where TService : class
{
return this.AsScopped<TImpl>(factory).WithAppCallback(WithGrpcService<TService>());
}

private PluggableComponentServiceBuilder AsScopped<T>(Func<T> factory) where T : class
{
return this.WithBuilderCallback(app =>
{
app.Services.AddScoped<T>((_) => factory());
});
}

private PluggableComponentServiceBuilder WithBuilderCallback(Action<WebApplicationBuilder> callback)
{
return new PluggableComponentServiceBuilder(this)
{
builderCallbacks = new List<Action<WebApplicationBuilder>>(this.builderCallbacks) { callback }
};
}

private PluggableComponentServiceBuilder WithAppCallback(Action<WebApplication> callback)
{
return new PluggableComponentServiceBuilder(this)
{
appCallbacks = new List<Action<WebApplication>>(this.appCallbacks) { callback }
};
}

private static Action<WebApplication> WithGrpcService<T>() where T : class
{
return (app) =>
{
app.MapGrpcService<T>();
};
}

public void Run(string? url = null)
{
var builder = WebApplication.CreateBuilder();
builderCallbacks.ForEach(callback => callback(builder));
var app = builder.Build();
appCallbacks.ForEach(callback => callback(app));
app.Run(url);
}
}
}
22 changes: 13 additions & 9 deletions Dapr.PluggableComponents/Components/IBinding.cs
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
namespace Dapr.PluggableComponents.Components;
namespace Dapr.PluggableComponents.Components;

public struct BindingResult {
public struct BindingResult
{
public string contentType { get; set; }
public byte[] data { get; set; }
public Dictionary<string, string> metadata {get; set; }
public Dictionary<string, string> metadata { get; set; }
}

public interface IInputBinding {
public interface IInputBinding
{
string Name();
void Init(Dictionary<string, string> properties);
BindingResult Read();
BindingResult Read();
void Ping();
}

public struct InvokeResult {
public struct InvokeResult
{
public string contentType { get; set; }
public byte[] data { get; set; }
public Dictionary<string, string> metadata { get; set; }
}

public interface IOutputBinding {
public interface IOutputBinding
{
string Name();
void Init(Dictionary<string, string> properties);
void Init(Dictionary<string, string> properties);
InvokeResult Invoke(string operation, byte[] req, Dictionary<string, string> metadata);
void Ping();
void Ping();
}
29 changes: 16 additions & 13 deletions Dapr.PluggableComponents/Services/OutputBindingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,36 @@

namespace Dapr.PluggableComponents.Services;

public class OutputBindingService : OutputBinding.OutputBindingBase {
public class OutputBindingService : OutputBinding.OutputBindingBase
{

private readonly ILogger<OutputBindingService> _logger;
private readonly IOutputBinding _backend;
private readonly ILogger<OutputBindingService> _logger;
private readonly IOutputBinding _backend;

public OutputBindingService(ILogger<OutputBindingService> logger, IOutputBinding backend) {
this._logger = logger;
public OutputBindingService(ILogger<OutputBindingService> logger, IOutputBinding backend)
{
this._logger = logger;
this._backend = backend;
}

public override Task<Empty> Init(MetadataRequest request, ServerCallContext context) {
public override Task<Empty> Init(MetadataRequest request, ServerCallContext context)
{
this._backend.Init(Utils.ConvertMetadata(request.Properties));
return Task.FromResult(new Empty());
return Task.FromResult(new Empty());
}

public override Task<InvokeResponse> Invoke(InvokeRequest request, ServerCallContext context) {
public override Task<InvokeResponse> Invoke(InvokeRequest request, ServerCallContext context)
{
_logger.LogDebug("Going to invoke output binding {0}", _backend.Name());

byte[] data = request.Data.ToArray();
string operation = request.Operation;
string operation = request.Operation;
var metadata = Utils.ConvertMetadata(request.Metadata);

var result = _backend.Invoke(operation, data, metadata);
InvokeResponse resp = new InvokeResponse();

InvokeResponse resp = new InvokeResponse();
resp.Data = ByteString.CopyFrom(result.data);
resp.Contenttype = result.contentType;
resp.Contenttype = result.contentType;
Utils.MergeDictionaryIntoMetadata(result.metadata, resp.Metadata);

return Task.FromResult(resp);
Expand Down
4 changes: 2 additions & 2 deletions Dapr.PluggableComponents/Services/PubSubService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ namespace Dapr.PluggableComponents.Services;
public class PubSubService : PubSub.PubSubBase {

private readonly ILogger<PubSubService> _logger;
private readonly IPubSubComponent _backend;
private readonly IPubSubComponent _backend;

public PubSubService(ILogger<PubSubService> logger, IPubSubComponent backend) {
this._logger = logger;
this._logger = logger;
this._backend = backend;
}

Expand Down
Loading