Skip to content

Commit

Permalink
Persist the broker between cli runs (#68)
Browse files Browse the repository at this point in the history
* Removed Broker.fs and its references

The Broker.fs file has been deleted, along with all its code. References to this file in the UnMango.Tdl.FSharp.fsproj have also been removed. This change simplifies the project structure by eliminating unnecessary components.

* Refactor client creation and rename modules

- Replaced the method for creating a client channel in Handlers.cs
- Renamed Client.fs to GrpcClient.fs, updating all references accordingly
- Renamed Library.fs to Util.fs, updating all references accordingly
- Updated module name from UnMango.Tdl.Client to UnMango.Tdl.GrpcClient

* Updated F# code formatting

The F# code has been reformatted for better readability. The changes include:
- Adjusted the indentation style in .editorconfig for F# files.
- Simplified async expressions by removing unnecessary newlines and brackets.
- Reformatted function definitions to make them more concise.
- Cleaned up some test cases by removing extra lines and spaces.

* Refactor Docker image creation condition

The conditional compilation directive for creating Docker images has been replaced with a runtime check. Now, the image creation process only occurs if the environment is set to 'Release'. This change enhances code readability and maintainability.

* Refactored container creation and added label-based search

Significant changes include:
- Refactoring of the Container class to use static factory methods for instantiation.
- Addition of a method in the Docker class to find containers based on labels.
- Modification of the Docker.Start method to include label parameters when creating a container.
- Changes in EnsureBroker class to check for socket existence before starting, and addition of labels during container start.
  • Loading branch information
UnstoppableMango authored May 11, 2024
1 parent 73dc0f5 commit 68e31a0
Show file tree
Hide file tree
Showing 14 changed files with 99 additions and 175 deletions.
1 change: 1 addition & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ indent_style = space

[*.fs]
indent_style = space
fsharp_newline_before_multiline_computation_expression = false

[*.cs]
indent_size = 4
Expand Down
2 changes: 1 addition & 1 deletion src/Cli.Tests/Internal/DockerRunnerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public async Task TestDocker() {
var spec = new Spec();
var createResponse = new CreateContainerResponse { ID = "test-id" };
var client = Substitute.For<IDocker>();
var startResult = new Container(client, createResponse);
var startResult = Container.From(client, createResponse);

client.Start(Arg.Any<StartArgs>(), CancellationToken.None)
.Returns(startResult);
Expand Down
2 changes: 1 addition & 1 deletion src/Cli/Handlers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public static async Task<int> Gen(
IEnumerable<FileInfo> files,
CancellationToken cancellationToken) {
Log.Verbose("Creating client channel");
using var channel = Client.createChannel(Config.Socket);
using var channel = GrpcClient.createChannel(Config.Socket);
var client = new UmlService.UmlServiceClient(channel);

var retryCount = 0;
Expand Down
8 changes: 6 additions & 2 deletions src/Cli/Internal/Container.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@ public interface IContainer : IAsyncDisposable
string Id { get; }
}

internal sealed class Container(IDocker docker, CreateContainerResponse create) : IContainer
internal sealed class Container(IDocker docker, string id) : IContainer
{
public string Id => create.ID;
public string Id => id;

public async ValueTask DisposeAsync() {
Log.Verbose("Disposing container");
await docker.Stop(this);
}

public static Container From(IDocker docker, CreateContainerResponse create) => new(docker, create.ID);

public static Container From(IDocker docker, ContainerListResponse list) => new(docker, list.ID);
}
50 changes: 36 additions & 14 deletions src/Cli/Internal/Docker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@ public sealed record StartArgs
public string? Name { get; init; }
public IList<string> Volumes { get; init; } = [];
public string? User { get; init; }
public IDictionary<string, string> Labels { get; init; } = new Dictionary<string, string>();
}

public interface IDocker
{
Task<IContainer?> FindMatching(IDictionary<string, string> labels, CancellationToken cancellationToken);

Task FollowLogs(string id, CancellationToken cancellationToken = default);

Task<IContainer> Start(StartArgs args, CancellationToken cancellationToken = default);
Expand Down Expand Up @@ -49,6 +52,24 @@ internal sealed class Docker(IDockerClient docker, IDockerProgress progress) : I
private static readonly Random Random = new();
private static string RandomName => $"tdl-{Random.Next()}";

public async Task<IContainer?> FindMatching(
IDictionary<string, string> labels,
CancellationToken cancellationToken) {
Log.Debug("Listing containers");
var containers = await docker.Containers.ListContainersAsync(
new ContainersListParameters {
Filters = labels.ToDictionary(
x => x.Key,
x => new Dictionary<string, bool> {
[x.Value] = true,
} as IDictionary<string, bool>),
},
cancellationToken);

var firstMatch = containers.FirstOrDefault();
return firstMatch == null ? null : Container.From(this, firstMatch);
}

public Task FollowLogs(string id, CancellationToken cancellationToken) {
Log.Debug("Getting container logs");
return docker.Containers.GetContainerLogsAsync(
Expand All @@ -63,26 +84,27 @@ public Task FollowLogs(string id, CancellationToken cancellationToken) {
}

public async Task<IContainer> Start(StartArgs args, CancellationToken cancellationToken) {
#if !DEBUG
Log.Debug("Creating image");
await docker.Images.CreateImageAsync(
new ImagesCreateParameters {
FromImage = args.Image,
Tag = args.Tag,
},
new AuthConfig(),
progress,
cancellationToken);
#endif
if (Config.Env.IsRelease) {
Log.Debug("Creating image");
await docker.Images.CreateImageAsync(
new ImagesCreateParameters {
FromImage = args.Image,
Tag = args.Tag,
},
new AuthConfig(),
progress,
cancellationToken);
}

Log.Debug("Creating container");
var container = await docker.Containers.CreateContainerAsync(
var createResponse = await docker.Containers.CreateContainerAsync(
new CreateContainerParameters {
Image = $"{args.Image}:{args.Tag}",
Name = args.Name ?? RandomName,
Cmd = args.Cmd,
User = args.User,
Tty = true,
Labels = args.Labels,
HostConfig = new HostConfig {
Binds = args.Volumes,
},
Expand All @@ -91,7 +113,7 @@ await docker.Images.CreateImageAsync(

Log.Debug("Starting container");
var started = await docker.Containers.StartContainerAsync(
container.ID,
createResponse.ID,
new ContainerStartParameters(),
cancellationToken);

Expand All @@ -100,7 +122,7 @@ await docker.Images.CreateImageAsync(
}

Log.Verbose("Started container");
return new Container(this, container);
return Container.From(this, createResponse);
}

public async Task Stop(string id, CancellationToken cancellationToken) {
Expand Down
33 changes: 19 additions & 14 deletions src/Cli/Internal/EnsureBroker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,39 @@ internal static partial class Patterns

internal static class EnsureBroker
{
private const string OwnerLabel = "tdl.owner", Owner = "tdl-cli";
private static readonly Regex ApplicationStarted = Patterns.ApplicationStarted();

public static InvocationMiddleware Middleware => async (context, next) => {
var cancellationToken = context.GetCancellationToken();
var docker = context.BindingContext.GetRequiredService<IDocker>();
await EnsureStarted(docker, context.GetCancellationToken());
await next(context);
};

private static Task EnsureStarted(IDocker docker, CancellationToken cancellationToken) {
Log.Verbose("Checking for socket existence");
if (!File.Exists(Config.Socket))
return Start(docker, cancellationToken);

Log.Debug("Socket exists");
return Task.CompletedTask;
}

private static async Task Start(IDocker docker, CancellationToken cancellationToken) {
var uid = await Config.Uid();
var gid = await Config.Gid();

Log.Debug("Starting broker");
var container = await docker.Start(new StartArgs {
Image = $"{Config.ContainerRepo}/tdl-broker",
Tag = Config.ContainerTag,
Name = "tdl-test",
User = $"{uid}:{gid}",
Volumes = [$"{Config.SocketDir}:/var/run/tdl"],
Labels = { [OwnerLabel] = Owner },
}, cancellationToken);
Log.Verbose("Started broker");

try {
_ = docker.FollowLogs(container);
await docker.WaitFor(container, ApplicationStarted.IsMatch, cancellationToken);
Log.Verbose("Invoking next");
await next(context);
Log.Verbose("After invoking next");
}
finally {
Log.Debug("Stopping broker");
await docker.Stop(container, cancellationToken);
}
};
_ = docker.FollowLogs(container, cancellationToken);
await docker.WaitFor(container, ApplicationStarted.IsMatch, cancellationToken);
}
}
103 changes: 0 additions & 103 deletions src/FSharp/Broker.fs

This file was deleted.

2 changes: 1 addition & 1 deletion src/FSharp/Client.fs → src/FSharp/GrpcClient.fs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module UnMango.Tdl.Client
module UnMango.Tdl.GrpcClient

open System
open System.IO
Expand Down
18 changes: 8 additions & 10 deletions src/FSharp/Tdl.fs
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,16 @@ module From =
let convert i o = async { failwith "TODO" }

let wrap (c: IConverter) : From =
fun o ->
async {
let! ct = Async.CancellationToken
return! c.FromAsync(o, ct) |> Async.AwaitTask
}
fun o -> async {
let! ct = Async.CancellationToken
return! c.FromAsync(o, ct) |> Async.AwaitTask
}

module Gen =
let generate i o = async { failwith "TODO" }

let wrap (g: IGenerator) : Gen =
fun i o ->
async {
let! ct = Async.CancellationToken
return! g.GenerateAsync(i, o, ct) |> Async.AwaitTask
}
fun i o -> async {
let! ct = Async.CancellationToken
return! g.GenerateAsync(i, o, ct) |> Async.AwaitTask
}
27 changes: 13 additions & 14 deletions src/FSharp/Tools.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,20 @@ module UnMango.Tdl.Tools
open System.Text
open UnMango.CliWrap.FSharp

let id (opts: string list) =
async {
let sb = StringBuilder()
let id (opts: string list) = async {
let sb = StringBuilder()

do!
command "id" {
args opts
stdout (PipeTo.string sb)
async
}
|> Async.Ignore
do!
command "id" {
args opts
stdout (PipeTo.string sb)
async
}
|> Async.Ignore

return sb.ToString().Trim()
}
return sb.ToString().Trim()
}

let uid = id ["-u"]
let uid = id [ "-u" ]

let gid = id ["-g"]
let gid = id [ "-g" ]
5 changes: 2 additions & 3 deletions src/FSharp/UnMango.Tdl.FSharp.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="Library.fs"/>
<Compile Include="Util.fs" />
<Compile Include="Tools.fs" />
<Compile Include="Broker.fs"/>
<Compile Include="Tdl.fs" />
<Compile Include="Client.fs" />
<Compile Include="GrpcClient.fs" />
<Compile Include="Config.fs" />
</ItemGroup>

Expand Down
File renamed without changes.
8 changes: 4 additions & 4 deletions src/Language.Tests/Program.fs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module Program

[<EntryPoint>]
let main _ = 0
module Program

[<EntryPoint>]
let main _ = 0
Loading

0 comments on commit 68e31a0

Please sign in to comment.