-
Notifications
You must be signed in to change notification settings - Fork 369
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
Implement proper handling of Docker Streams #147
Conversation
Hi @galvesribeiro, I'm your friendly neighborhood Microsoft Pull Request Bot (You can call me MSBOT). Thanks for your contribution! The agreement was validated by Microsoft and real humans are currently evaluating your PR. TTYL, MSBOT; |
@@ -238,7 +238,7 @@ public Task RemoveContainerAsync(string id, ContainerRemoveParameters parameters | |||
return this._client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Delete, $"containers/{id}", queryParameters); | |||
} | |||
|
|||
public Task<Stream> GetContainerLogsAsync(string id, ContainerLogsParameters parameters, CancellationToken cancellationToken) | |||
public async Task GetContainerLogsAsync(string id, ContainerLogsParameters parameters, CancellationToken cancellationToken, IProgress<string> logReport = null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about this. Leave the old method and add an [Obsolete]
tag with reference to the new sig. Have this new method call the old one to get the stream and just do the while (can read) { report }
part. Then we have no breaking changes but we do alert people to use the new method. And then in the next version of docker I will pull the [Obsolete]
method and merge the logic to just the IProgress{T}
variant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also how do you feel about just calling it IProgress<string> progress = null
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure! Let me change that.
var line = await reader.ReadLineAsync(); | ||
if (logReport == null) continue; | ||
|
||
logReport.Report(line); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you kill the part about making this a typed message? Dont we know what the string type is and you could just use:
logReport.Report(this._client.JsonSerializer.DeserialzeObject<Progress>(line);
var line = await reader.ReadLineAsync(); | ||
if (progress == null) continue; | ||
|
||
var @event = JObject.Parse(line); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the complexity here? Cant JSON.NET just handle the deserialization in 1 object definition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason is that I can't find the object structure well defined for those events in go files... So I got the fields that matter and manually read them. If you can point me to the right structure I can make it deserialize direct to the object just like in the others.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Go ahead and leave this for now. I will remove it in the 1.13 branch that my PR eludes to because the type wasnt yet defined.
|
||
namespace Docker.DotNet.Models | ||
{ | ||
public class EventMessage |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah. Add a line to specgen.go by /events
{reflect.TypeOf(events.Message{}), "EventsMessage"},
so that this stays in sync with the docker types. This will also generate for you the Actor struct etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok did some digging. I honestly cant tell from the docker code. I think we actually want jsonmessage.JsonMessage type here instead. @swernli does this seem right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will reflect the JSONError and JSONProgress structs too which is the full message as far as I can tell.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got it from here https://github.com/docker/docker/blob/master/api/types/events/events.go which are the only objects used by this method. Do you want submit a PR with the Go stuff changed? I don't have it here and would take a while to get it working...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added this in the other PR. Rebase on it and you can remove.
@jterry75 done. Now only thing missing is that Go thing... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Almost! Thanks for doing this!
@@ -254,6 +256,21 @@ public Task<Stream> GetContainerLogsAsync(string id, ContainerLogsParameters par | |||
return this._client.MakeRequestForStreamAsync(new[] { NoSuchContainerHandler }, HttpMethod.Get, $"containers/{id}/logs", queryParameters, null, cancellationToken); | |||
} | |||
|
|||
public async Task GetContainerLogsAsync(string id, ContainerLogsParameters parameters, CancellationToken cancellationToken, IProgress<string> progress = null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this compile? I would assume that for this transfer period what we will need to do is to make the progress a non default parameter. Then we will have 2 physical overloads and then when I merge/remove the [Obsolete] version I will make it optional again to keep the same set of overloads.
var line = await reader.ReadLineAsync(); | ||
if (progress == null) continue; | ||
|
||
var report = JsonConvert.DeserializeObject<ContainerStatsResponse>(line); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use the this._client.JsonSerializer.DeserializeObject
it makes it a whole lot easier for writing tests to not hard reference JsonConvert
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And then you dont need the using at the top
@@ -40,6 +41,8 @@ public interface IContainerOperations | |||
|
|||
Task<Stream> GetContainerLogsAsync(string id, ContainerLogsParameters parameters, CancellationToken cancellationToken); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ya now I think I mislead you. We only expose the Interfaces externally. I think you need to make the [Obsolete] tags here instead. My bad
var line = await reader.ReadLineAsync(); | ||
if (progress == null) continue; | ||
|
||
var @event = JObject.Parse(line); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Go ahead and leave this for now. I will remove it in the 1.13 branch that my PR eludes to because the type wasnt yet defined.
@@ -4,6 +4,7 @@ | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
using Docker.DotNet.Models; | |||
using Newtonsoft.Json; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same. If you remove the JsonConvert reference and use this._client.JsonSerializer
we can remove this too
|
||
namespace Docker.DotNet.Models | ||
{ | ||
public class EventMessage |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added this in the other PR. Rebase on it and you can remove.
@@ -0,0 +1,9 @@ | |||
namespace Docker.DotNet.Models | |||
{ | |||
public struct ImageOperationProgress |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep for now. I will remove later in the 1.13 branch
@jterry75 done :) |
This PR implements #108
Read and notify properly Docker event Streams in:
MISC
endpoint Monitor EventThis PR will be update with one commit for each part to make easier to review.